深度学习入门:从零理解bp反向传播算法的数学原理与实现

1次阅读
没有评论

共计 1967 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

神经网络基础回顾

在开始反向传播之前,我们需要明确几个基本概念。神经网络由输入层、隐藏层和输出层组成,每层包含若干神经元。神经元之间的连接具有权重,这些权重决定了信号的传递强度。

深度学习入门:从零理解 bp 反向传播算法的数学原理与实现

  • 前向传播 :输入数据从输入层经过隐藏层传递到输出层的过程。每个神经元接收上一层神经元的输出,经过加权求和后通过激活函数产生输出。

  • 损失函数 :衡量网络输出与真实值差异的函数,常见的如均方误差(MSE)和交叉熵损失。

  • 反向传播 :通过计算损失函数对权重的梯度,从输出层反向逐层调整权重,以最小化损失函数。

反向传播数学原理推导

反向传播的核心是链式法则。我们以单隐藏层的全连接网络为例,推导反向传播的数学过程。

  1. 前向传播公式
  2. 隐藏层输出:$h = \sigma(W_1 x + b_1)$
  3. 输出层输出:$y = W_2 h + b_2$
  4. 损失函数:$L = \frac{1}{2}(y – t)^2$,其中 $t$ 为真实值

  5. 反向传播梯度计算

  6. 输出层权重梯度:$\frac{\partial L}{\partial W_2} = \frac{\partial L}{\partial y} \frac{\partial y}{\partial W_2} = (y – t) h^T$
  7. 隐藏层权重梯度:$\frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial h} \frac{\partial h}{\partial W_1} = (W_2^T (y – t)) \odot \sigma'(W_1 x + b_1) x^T$

其中 $\odot$ 表示逐元素相乘,$\sigma’$ 是激活函数的导数。

Python 实现与代码解析

import numpy as np

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

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

# 网络参数
input_size = 2
hidden_size = 3
output_size = 1
learning_rate = 0.1

# 初始化权重
W1 = np.random.randn(input_size, hidden_size)
W2 = np.random.randn(hidden_size, output_size)
b1 = np.zeros(hidden_size)
b2 = np.zeros(output_size)

# 训练数据
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y_true = np.array([[0], [1], [1], [0]])

# 训练循环
for epoch in range(10000):
    # 前向传播
    hidden_input = np.dot(X, W1) + b1
    hidden_output = sigmoid(hidden_input)
    output = np.dot(hidden_output, W2) + b2

    # 计算损失
    loss = np.mean(0.5 * (output - y_true) ** 2)

    # 反向传播
    # 输出层梯度
    d_output = (output - y_true) / X.shape[0]
    dW2 = np.dot(hidden_output.T, d_output)
    db2 = np.sum(d_output, axis=0)

    # 隐藏层梯度
    d_hidden = np.dot(d_output, W2.T) * sigmoid_derivative(hidden_output)
    dW1 = np.dot(X.T, d_hidden)
    db1 = np.sum(d_hidden, axis=0)

    # 更新权重
    W2 -= learning_rate * dW2
    b2 -= learning_rate * db2
    W1 -= learning_rate * dW1
    b1 -= learning_rate * db1

    if epoch % 1000 == 0:
        print(f'Epoch {epoch}, Loss: {loss:.4f}')

常见问题与调优建议

  1. 梯度消失
  2. 当使用 sigmoid 或 tanh 激活函数时,深层网络容易出现梯度消失问题
  3. 解决方案:使用 ReLU 等激活函数,或采用 Batch Normalization

  4. 学习率设置

  5. 学习率过大会导致震荡,过小会导致收敛缓慢
  6. 建议:使用学习率衰减策略,如指数衰减

  7. 权重初始化

  8. 避免全零初始化,会导致对称性问题
  9. 推荐:Xavier 初始化或 He 初始化

  10. 过拟合

  11. 解决方案:加入 L2 正则化,或使用 Dropout 技术

延伸练习与总结

  1. 练习任务
  2. 实现 ReLU 激活函数的反向传播
  3. 尝试增加网络深度,观察梯度消失现象
  4. 实现学习率衰减策略

  5. 总结

  6. 反向传播是神经网络训练的核心算法
  7. 理解链式法则的应用是关键
  8. 在实践中需要注意梯度消失、学习率设置等问题

通过本文的学习,你应该已经掌握了反向传播的基本原理和实现方法。建议动手实现代码并尝试不同的网络结构和参数设置,这将帮助你更深入地理解神经网络的训练过程。

正文完
 0
评论(没有评论)