神经网络(ANNs)
什么是神经网络
神经网络(Neural Network)是机器学习中的一种模型,它模仿了人脑的工作方式,用来解决复杂的问题,比如图像识别、语音识别或者预测某些结果
神经网络就像一个团队在解决一个问题:团队里的每个人负责处理一小部分信息,然后把结果传递给其他人,最后团队一起得出一个结论。这个团队会通过反复练习(训练),变得越来越擅长解决问题
神经元
神经元(Neuron)是神经网络的基本单位,相当于团队里的“一个人”。它负责接收一些输入信息,做一些简单的计算,然后输出一个结果,并且将这个结果输出给下一个神经元
具体来说,一个神经元会:
- 接收多个输入(比如说特征矩阵)
- 给每个输入分配一个权重(Weight)
- 把所有输入加权求和,再加上一个“偏差”(Bias)
- 最后通过一个激活函数(Activation Function)处理这个结果,激活函数可以是之前学到的线性回归或者是逻辑回归函数
层(Layer)
层(Layer)是神经网络中的一个结构,它是由很多神经元组成的一个“小组”。每一层负责处理一部分信息,然后把结果传递给下一层。神经网络通常由多层组成,不同的层有不同的作用
- 输入层(Input Layer):第一层,负责接收原始数据。比如你给神经网络一张图片,输入层就把图片的像素值作为输入
- 隐藏层(Hidden Layer):中间的层,负责处理和转换信息。隐藏层可能有很多层,每一层都对数据进行更复杂的计算,提取特征(比如从图片中找出边缘、形状等)
- 输出层(Output Layer):最后一层,负责给出最终结果。比如判断这张图片是猫还是狗,输出层会输出一个概率或分类结果
上图绿色的为输入层,蓝色的为隐藏层,黄色的为输出层,一般来说,在讨论神经网络层数的时候,输入层不参与计算,只计算隐藏层和输出层
任意隐藏层的输出激活值计算
一般形式(第 层)
对于第
符号 | 含义 |
---|---|
第 | |
第 | |
上一层(第 | |
激活函数(如 ReLU, sigmoid, tanh 等) | |
当前层神经元的线性加权和(未激活前的输入) | |
当前层神经元的输出(激活值) |
假设:
第
层输出: 当前第
层有 2 个神经元,那么:
计算过程如下:
算出
总结为:
线性组合 + 偏置 → 激活函数 → 输出
手写前向传播
import numpy as np
# 设置随机种子以确保结果可重复
np.random.seed(42)
# 定义激活函数
def relu(x):
"""
ReLU激活函数:如果输入大于0,返回输入;否则返回0
"""
return np.maximum(0, x)
def sigmoid(x):
"""
Sigmoid激活函数:将输入映射到0到1之间
"""
return 1 / (1 + np.exp(-x))
# 定义神经网络的结构
input_size = 2 # 输入层:2个神经元
hidden1_size = 3 # 第一隐藏层:3个神经元
hidden2_size = 2 # 第二隐藏层:2个神经元
output_size = 1 # 输出层:1个神经元
# 初始化权重和偏差(随机初始化)
# 权重矩阵的形状为 (前一层神经元数, 当前层神经元数)
W1 = np.random.randn(input_size, hidden1_size) * 0.01 # 输入层到第一隐藏层的权重
b1 = np.zeros((1, hidden1_size)) # 第一隐藏层的偏差
W2 = np.random.randn(hidden1_size, hidden2_size) * 0.01 # 第一隐藏层到第二隐藏层的权重
b2 = np.zeros((1, hidden2_size)) # 第二隐藏层的偏差
W3 = np.random.randn(hidden2_size, output_size) * 0.01 # 第二隐藏层到输出层的权重
b3 = np.zeros((1, output_size)) # 输出层的偏差
# 定义前向传播函数
def forward_propagation(X):
"""
实现前向传播
输入:
X: 输入数据,形状为 (样本数, 输入层神经元数)
输出:
a3: 输出层的输出值
cache: 存储中间结果(用于反向传播或其他用途)
"""
# 第一隐藏层的计算
z1 = np.dot(X, W1) + b1 # 加权求和 + 偏差
a1 = relu(z1) # 应用ReLU激活函数
# 第二隐藏层的计算
z2 = np.dot(a1, W2) + b2 # 加权求和 + 偏差
a2 = relu(z2) # 应用ReLU激活函数
# 输出层的计算
z3 = np.dot(a2, W3) + b3 # 加权求和 + 偏差
a3 = sigmoid(z3) # 应用sigmoid激活函数
# 存储中间结果(可选,用于反向传播)
cache = (z1, a1, z2, a2, z3, a3)
return a3, cache
# 测试前向传播
# 假设有一个输入样本,值为 [1.0, 2.0]
X = np.array([[1.0, 2.0]]) # 形状为 (1, 2),表示1个样本,2个特征
# 执行前向传播
output, cache = forward_propagation(X)
# 打印结果
print("输入数据:", X)
print("输出结果:", output)
print("\n中间结果(z1, a1, z2, a2, z3, a3):")
for i, val in enumerate(cache):
print(f"中间值 {i+1}: {val}")
如何理解前向传播,前向传播主要用于推理,在训练完成参数固定之后,用来预测最终结果的
上面的代码只是单个样本的特征值,我们将原始输入特征的矩阵
在上面的代码中,我的输入层的矩阵特征有两个,第一层有三个,第二层有两个,最后一层为标量,即最终的概率
不同层的神经元数量(比如从 3 个特征到 4 个神经元)可以帮助网络调整数据的表示方式,适应不同的任务需求(分类、回归等)
最终这个概率会被整合为 cost function,在反向传播中用来优化神经元中的
一个简单神经网络的组成(Tensorflow)
使用 Tensorflow 构建一个简单的神经网络分为三步
构建神经网络模型
这一步是定义神经网络的结构 —— 有哪些层,每层有几个神经元,是否使用激活函数等:
# 构建神经网络模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(units=1, input_shape=[1]) # 输入层+输出层,简单线性关系
# 如果需要更复杂的关系,可以加隐藏层,比如:
# tf.keras.layers.Dense(units=10, activation='relu'), # 隐藏层
])
编译模型,选择合适的 cost function
选择优化算法(比如 SGD、Adam)和损失函数(比如均方误差)来衡量模型误差
# 编译模型:定义优化器、损失函数
model.compile(optimizer='sgd', loss='mean_squared_error')
反向传播,确定迭代次数
使用已有数据进行训练,Tensorflow 会自动进行前向传播和反向传播,更新参数
# 训练模型:用数据“喂”模型,让它学习
model.fit(X, y, epochs=500, verbose=0) # epochs 是训练的轮数,verbose=0 表示不显示训练过程
完整代码如下:
import tensorflow as tf
import numpy as np
# 准备数据:房子的面积(平方米)和价格(万元)
X = np.array([100, 150, 200, 250, 300], dtype=float) # 面积
y = np.array([200, 300, 400, 500, 600], dtype=float) # 价格
# 构建神经网络模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(units=1, input_shape=[1]) # 输入层+输出层,简单线性关系
# 如果需要更复杂的关系,可以加隐藏层,比如:
# tf.keras.layers.Dense(units=10, activation='relu'), # 隐藏层
])
# 编译模型:定义优化器、损失函数
model.compile(optimizer='sgd', loss='mean_squared_error')
# 训练模型:用数据“喂”模型,让它学习
model.fit(X, y, epochs=500, verbose=0) # epochs 是训练的轮数,verbose=0 表示不显示训练过程
# 用模型预测新数据
# 假设有一个面积为 180 平米的房子,预测它的价格
new_house = np.array([[180]])
predicted_price = model.predict(new_house)
print(f"预测房价为:{predicted_price[0][0]:.2f} 万元")