文章目录
- 定义
- 过程
- 前向传播计算过程
- 计算损失函数(采用均方误差MSE)
- 反向传播误差(链式法则)
- 计算梯度
- 更新参数
- 简单实例
定义
反向传播全名是反向传播误差算法(Backpropagation),是一种监督学习方法,用于调整神经网络中权重参数,以最小化模型的预测误差。反向传播通过计算损失函数相对于网络参数的梯度,然后使用梯度下降等优化算法来更新参数,从而提高模型的性能
核心思想是从网络的输出层向输入层传播误差信号,然后根据这些误差信号来更新网络中的权重和偏差,以使模型的输出更接近实际目标
过程
前向传播:将输入数据输入到网络中,通过神经网络的前向传播计算出每个神经元的输出结果,直到输出层输出最终的结果。
计算损失函数:将神经网络输出的结果与真实标签进行比较,计算出损失函数的值。
反向传播误差:从输出层开始,计算每个神经元的误差,然后向前计算每个神经元的误差,直到计算出输入层每个神经元的误差。具体来说,我们首先计算输出层的误差,然后反向传播到前一层隐藏层,计算隐藏层的误差,并将误差反向传播到更早的层,直到计算出输入层的误差。这个过程可以使用链式法则来计算。
计算梯度:根据误差计算每个神经元的梯度,即损失函数对每个神经元权重和偏差的偏导数。
更新参数:使用梯度下降法或其他优化方法来更新每个神经元的权重和偏差,使得损失函数的值最小化。
设置初始值如图:
目标:给出输入数据i1,i2(0.05和0.10),使输出尽可能与原始输出o1,o2(0.01和0.99)接近
神经网络中信息传递的基本原理:
在神经网络中,前一层神经元的输出通常作为下一层神经元的输入
前向传播计算过程
y=wx+b
例如上图中h1的输入input1 = w1i1+w2i2+b1
假设采用的sigmoid激活函数,则输出output1 = 1/(1+e^-input1)
而这个输出output1又会作为下一层神经元o1、o2的输入
由此我们可以轻松计算出最后的输出
计算损失函数(采用均方误差MSE)
将前向传播计算得到的输出与原始输出比较
MSE = Σ(预测值 - 实际观测值)^2 / 观测值的数量
反向传播误差(链式法则)
从输出层开始,计算每个神经元的误差,然后向前计算每个神经元的误差,直到计算出输入层每个神经元的误差
计算梯度
当前层的梯度 = 当前层输出的梯度 × 当前层输入的梯度
以b站某up主讲解中的一个片段为例:
其中绿色字体代表的是输入值,红色字体为反向传播的梯度
我们以最左上角w0,x0那为例,假设得到的是y0,(再次提醒,上面绿色字体为前向传播计算的值)
则x0的梯度为:y0对x0求导再乘以0.2(当前层输出的梯度),最后得到0.40(至于0.39可能是笔误)
同理w0的梯度:y0对w0求导再乘以0.2,即-1.0*0.2 = 0.20
更新参数
设置一个学习率,根据之前计算的梯度就可以进行参数权重更新了
简单实例
import numpy as np
# 定义 Sigmoid 激活函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 定义 Sigmoid 激活函数的导数
def sigmoid_derivative(x):
return x * (1 - x)
# 创建神经网络类
class NeuralNetwork:
def __init__(self, input_size, hidden_size, output_size):
# 初始化权重
self.weights_input_hidden = np.random.rand(input_size, hidden_size)
self.weights_hidden_output = np.random.rand(hidden_size, output_size)
def forward(self, X):
# 前向传播
self.hidden_input = np.dot(X, self.weights_input_hidden)
self.hidden_output = sigmoid(self.hidden_input)
self.output = np.dot(self.hidden_output, self.weights_hidden_output)
return self.output
def backward(self, X, y, output, learning_rate):
# 反向传播
error = y - output
delta_output = error
error_hidden = delta_output.dot(self.weights_hidden_output.T)
delta_hidden = error_hidden * sigmoid_derivative(self.hidden_output)
# 更新权重
self.weights_hidden_output += self.hidden_output.T.dot(delta_output) * learning_rate
self.weights_input_hidden += X.T.dot(delta_hidden) * learning_rate
def train(self, X, y, learning_rate, epochs):
for i in range(epochs):
output = self.forward(X)
self.backward(X, y, output, learning_rate)
if i % 1000 == 0:
loss = np.mean(np.square(y - output))
print(f"Epoch {i}, Loss: {loss}")
# 示例数据
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])
# 创建神经网络
input_size = 2
hidden_size = 4
output_size = 1
learning_rate = 0.1
epochs = 10000
nn = NeuralNetwork(input_size, hidden_size, output_size)
# 训练神经网络
nn.train(X, y, learning_rate, epochs)