反向传播

在神经网络中,反向传播(Backpropagation) 是一种高效计算损失函数梯度的算法,也是训练深度学习模型的核心技术。以下从原理、数学推导、计算流程、代码实现等方面详细解析:

一、核心原理

反向传播算法基于链式法则,将损失函数对每个参数的梯度计算分解为从输出层到输入层的反向传递过程,大幅降低计算复杂度(从指数级降至线性级)。

四、代码示例(手动实现反向传播)

以下是一个简化的单隐藏层神经网络的反向传播实现:
import numpy as np

# 激活函数及其导数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return sigmoid(x) * (1 - sigmoid(x))

# 损失函数及其导数
def mse_loss(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

def mse_derivative(y_true, y_pred):
    return 2 * (y_pred - y_true) / y_true.size

# 神经网络类
class NeuralNetwork:
    def __init__(self, input_size, hidden_size, output_size):
        # 随机初始化权重和偏置
        self.w1 = np.random.randn(input_size, hidden_size)
        self.b1 = np.zeros((1, hidden_size))
        self.w2 = np.random.randn(hidden_size, output_size)
        self.b2 = np.zeros((1, output_size))

    def forward(self, x):
        # 前向传播
        self.z1 = np.dot(x, self.w1) + self.b1
        self.a1 = sigmoid(self.z1)
        self.z2 = np.dot(self.a1, self.w2) + self.b2
        self.a2 = sigmoid(self.z2)
        return self.a2

    def backward(self, x, y, learning_rate):
        # 反向传播
        m = x.shape[0]  # 样本数
        
        # 计算输出层梯度
        delta2 = mse_derivative(y, self.a2) * sigmoid_derivative(self.z2)
        dw2 = np.dot(self.a1.T, delta2) / m
        db2 = np.sum(delta2, axis=0, keepdims=True) / m
        
        # 计算隐藏层梯度
        delta1 = np.dot(delta2, self.w2.T) * sigmoid_derivative(self.z1)
        dw1 = np.dot(x.T, delta1) / m
        db1 = np.sum(delta1, axis=0, keepdims=True) / m
        
        # 更新参数
        self.w2 -= learning_rate * dw2
        self.b2 -= learning_rate * db2
        self.w1 -= learning_rate * dw1
        self.b1 -= learning_rate * db1

# 训练示例
x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])  # 输入数据
y = np.array([[0], [1], [1], [0]])              # 目标输出

nn = NeuralNetwork(input_size=2, hidden_size=2, output_size=1)

# 训练循环
epochs = 10000
for epoch in range(epochs):
    # 前向传播
    output = nn.forward(x)
    
    # 反向传播
    nn.backward(x, y, learning_rate=0.1)
    
    # 每1000轮打印损失
    if epoch % 1000 == 0:
        loss = mse_loss(y, output)
        print(f"Epoch {epoch}, Loss: {loss:.4f}")

六、使用深度学习框架(PyTorch)的实现

现代框架(如 PyTorch、TensorFlow)会自动计算梯度,无需手动实现反向传播:
import torch
import torch.nn as nn
import torch.optim as optim

# 定义模型
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(2, 2)  # 输入层到隐藏层
        self.fc2 = nn.Linear(2, 1)  # 隐藏层到输出层
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(self.fc1(x))
        x = self.sigmoid(self.fc2(x))
        return x

# 初始化模型、损失函数和优化器
model = SimpleNN()
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.1)

# 训练数据
x = torch.tensor([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=torch.float32)
y = torch.tensor([[0], [1], [1], [0]], dtype=torch.float32)

# 训练循环
epochs = 10000
for epoch in range(epochs):
    # 前向传播
    outputs = model(x)
    loss = criterion(outputs, y)
    
    # 反向传播和优化
    optimizer.zero_grad()  # 清零梯度
    loss.backward()        # 自动计算梯度
    optimizer.step()       # 更新参数
    
    # 打印进度
    if (epoch+1) % 1000 == 0:
        print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')

总结

反向传播是神经网络训练的核心算法,通过链式法则高效计算梯度。实际应用中需注意激活函数选择、梯度消失 / 爆炸问题,并合理使用优化器和正则化方法。现代深度学习框架已封装了自动求导功能,大幅简化了开发流程,但理解反向传播的底层原理对模型调优至关重要。
posted @ 2025-07-11 09:14  姚春辉  阅读(319)  评论(0)    收藏  举报