多层感知机参数计算与反向传播详解:从基础到避坑指南

1次阅读
没有评论

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

image.webp

一、理解多层感知机的参数计算

以一个输入层 33 节点、隐层 512 节点、输出层 10 节点的网络为例,参数包含两部分:

多层感知机参数计算与反向传播详解:从基础到避坑指南

  1. 权重参数
  2. 输入层到隐层:$W_1 \in \mathbb{R}^{33×512}$,共 33×512=16,896 个参数
  3. 隐层到输出层:$W_2 \in \mathbb{R}^{512×10}$,共 512×10=5,120 个参数

  4. 偏置参数

  5. 隐层偏置:$b_1 \in \mathbb{R}^{512}$
  6. 输出层偏置:$b_2 \in \mathbb{R}^{10}$

总参数量 = 16,896 + 512 + 5,120 + 10 = 22,538 个可训练参数

import numpy as np

# 参数初始化实现
input_dim, hidden_dim, output_dim = 33, 512, 10
W1 = np.random.randn(input_dim, hidden_dim) * 0.01
b1 = np.zeros(hidden_dim)
W2 = np.random.randn(hidden_dim, output_dim) * 0.01
b2 = np.zeros(output_dim)

二、反向传播的梯度计算与权重更新

梯度计算步骤(以 SGD 为例):

  1. 前向传播计算各层输出:
    $$z_1 = W_1^Tx + b_1$$
    $$a_1 = \sigma(z_1)$$
    $$z_2 = W_2^Ta_1 + b_2$$
    $$\hat{y} = \text{softmax}(z_2)$$

  2. 计算输出层梯度:
    $$\frac{\partial L}{\partial z_2} = \hat{y} – y$$

  3. 反向传播隐层梯度:
    $$\frac{\partial L}{\partial W_2} = a_1^T \frac{\partial L}{\partial z_2}$$
    $$\frac{\partial L}{\partial z_1} = W_2 \frac{\partial L}{\partial z_2} \odot \sigma'(z_1)$$

  4. 计算输入层梯度:
    $$\frac{\partial L}{\partial W_1} = x^T \frac{\partial L}{\partial z_1}$$

权重更新实现:

# 简化版反向传播实现
learning_rate = 0.01

def backward(x, y, cache):
    W1, b1, W2, b2, a1, z2 = cache
    m = x.shape[0]

    # 输出层梯度
    dz2 = cache['probs'] - y
    dW2 = np.dot(a1.T, dz2) / m
    db2 = np.sum(dz2, axis=0) / m

    # 隐层梯度
    dz1 = np.dot(dz2, W2.T) * (a1 * (1 - a1))  # 假设使用 sigmoid 激活
    dW1 = np.dot(x.T, dz1) / m
    db1 = np.sum(dz1, axis=0) / m

    # 参数更新
    W1 -= learning_rate * dW1
    b1 -= learning_rate * db1
    W2 -= learning_rate * dW2
    b2 -= learning_rate * db2

三、过拟合的三大应对策略

1. Dropout 方法

  • 训练时随机丢弃部分神经元(通常丢弃率 p =0.5)
  • 测试时使用全部神经元但乘以保留概率(1-p)
# Dropout 实现示例
keep_prob = 0.5
mask = (np.random.rand(*a1.shape) < keep_prob) / keep_prob
a1_drop = a1 * mask

2. L2 正则化

  • 在损失函数中加入权重平方和项:
    $$L_{new} = L + \frac{\lambda}{2}(|W_1|^2 + |W_2|^2)$$
l2_lambda = 0.01
l2_loss = 0.5 * l2_lambda * (np.sum(W1**2) + np.sum(W2**2))

3. 早停法(Early Stopping)

  • 在验证集性能不再提升时终止训练
  • 需要监控验证集准确率曲线

四、实战避坑指南

参数初始化注意事项

  • 使用 Xavier 初始化:$W \sim N(0, \sqrt{\frac{2}{n_{in}+n_{out}}})$
  • ReLU 网络建议使用 He 初始化:$W \sim N(0, \sqrt{\frac{2}{n_{in}}})$

学习率设置经验

  • 初始学习率可尝试 0.1~0.001
  • 使用学习率衰减策略:
    lr = initial_lr * (1 + decay_rate * epoch)**(-0.5)

梯度问题应对方案

  • 梯度消失:改用 ReLU/LeakyReLU,合理初始化
  • 梯度爆炸:梯度裁剪(gradient clipping)
    max_grad_norm = 5.0
    total_norm = np.sum([np.linalg.norm(g) for g in grads])
    clip_coef = max_grad_norm / (total_norm + 1e-6)
    grads = [g * clip_coef if clip_coef < 1 else g for g in grads]

思考题

如果隐层使用 ReLU 激活函数,反向传播时梯度计算需要修改为:
$$\frac{\partial L}{\partial z_1} = W_2 \frac{\partial L}{\partial z_2} \odot \mathbb{I}(z_1 > 0)$$
其中 $\mathbb{I}(·)$ 是指示函数,当输入 >0 时输出 1,否则输出 0。

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