Appearance
章节1:神经网络原理
学习目标
- 理解感知机与多层感知机(MLP)的结构与局限
- 掌握反向传播算法中的链式法则与梯度计算流程
- 熟悉常用激活函数的特性与适用场景
- 理解损失函数与优化器的作用机制
- 掌握批量归一化与Dropout等正则化技术
1.1 感知机与多层感知机
1.1.1 感知机(Perceptron)
感知机是神经网络的最基本单元,由 Rosenblatt 于 1958 年提出。它接受多个输入,乘以权重后求和,再通过阶跃函数输出。
数学定义:
$$ y = \begin{cases} 1, & \sum_{i=1}^{n} w_i x_i + b > 0 \ 0, & \text{otherwise} \end{cases} $$
其中 $w_i$ 是权重,$b$ 是偏置,$x_i$ 是输入特征。
局限性: 单层感知机只能解决线性可分问题(如 AND、OR),无法解决 XOR 等非线性问题。
1.1.2 多层感知机(MLP)
多层感知机通过在输入层与输出层之间引入一个或多个隐藏层,并使用非线性激活函数,解决了非线性分类问题。
数学定义:
$$ \begin{aligned} h &= f(W_1 x + b_1) \ y &= g(W_2 h + b_2) \end{aligned} $$
其中 $f$ 和 $g$ 为激活函数,$W_1, W_2$ 为权重矩阵。
PyTorch 实现一个简单 MLP:
python
import torch
import torch.nn as nn
class MLP(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, output_dim)
)
def forward(self, x):
return self.net(x)
# 测试
model = MLP(784, 256, 10)
x = torch.randn(32, 784) # batch_size=32
print(model(x).shape) # torch.Size([32, 10])1.2 反向传播算法(Backpropagation)
1.2.1 链式法则
反向传播的核心是链式法则(Chain Rule):复合函数的导数等于各层导数的乘积。
对于 $L = f(g(h(x)))$,有:
$$ \frac{\partial L}{\partial x} = \frac{\partial L}{\partial f} \cdot \frac{\partial f}{\partial g} \cdot \frac{\partial g}{\partial h} \cdot \frac{\partial h}{\partial x} $$
1.2.2 梯度计算流程
- 前向传播:计算每层输出与最终损失值
- 反向传播:从输出层向输入层逐层计算梯度
- 参数更新:使用梯度下降更新权重
PyTorch 自动梯度示例:
python
import torch
x = torch.tensor([2.0, 3.0], requires_grad=True)
w = torch.tensor([1.5, -0.5], requires_grad=True)
b = torch.tensor([0.1], requires_grad=True)
y = (x * w).sum() + b # 前向计算
loss = y ** 2 # 假损失
loss.backward() # 反向传播(自动计算梯度)
print(f"dw: {w.grad}") # 权重梯度
print(f"db: {b.grad}") # 偏置梯度1.3 激活函数
激活函数为神经网络引入非线性,使其能够拟合复杂函数。
1.3.1 Sigmoid
将输入映射到 $(0, 1)$ 区间,常用于二分类输出层。
公式:
$$ \sigma(x) = \frac{1}{1 + e^{-x}} $$
梯度:
$$ \sigma'(x) = \sigma(x)(1 - \sigma(x)) $$
缺点: 当 $x$ 绝对值很大时梯度趋近于 0,导致梯度消失。
1.3.2 Tanh
将输入映射到 $(-1, 1)$ 区间,零中心化。
公式:
$$ \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} $$
梯度:
$$ \tanh'(x) = 1 - \tanh^2(x) $$
1.3.3 ReLU
目前最常用的隐藏层激活函数。
公式:
$$ \text{ReLU}(x) = \max(0, x) $$
优点: 计算简单、缓解梯度消失、稀疏激活。 缺点: 神经元死亡(负半轴梯度为 0)。
1.3.4 LeakyReLU
改进 ReLU 的负半轴问题。
公式:
$$ \text{LeakyReLU}(x) = \max(\alpha x, x), \quad \alpha \text{ 通常取 } 0.01 $$
PyTorch 激活函数对比:
python
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
x = torch.linspace(-5, 5, 100)
sigmoid = torch.sigmoid(x)
tanh = torch.tanh(x)
relu = F.relu(x)
leaky_relu = F.leaky_relu(x, negative_slope=0.01)
plt.figure(figsize=(10, 6))
plt.plot(x, sigmoid, label='Sigmoid')
plt.plot(x, tanh, label='Tanh')
plt.plot(x, relu, label='ReLU')
plt.plot(x, leaky_relu, label='LeakyReLU')
plt.legend()
plt.grid()
plt.show()1.4 损失函数与优化器
1.4.1 交叉熵损失(Cross-Entropy Loss)
用于分类任务,衡量预测分布与真实分布的差异。
公式(多分类):
$$ \mathcal{L} = -\sum_{i=1}^{C} y_i \log(\hat{y}_i) $$
其中 $y_i$ 是真实标签的 one-hot 编码,$\hat{y}_i$ 是预测概率。
1.4.2 均方误差(MSE Loss)
用于回归任务。
公式:
$$ \mathcal{L} = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2 $$
1.4.3 SGD(随机梯度下降)
每次用单个样本(或 mini-batch)更新参数。
$$ \theta_{t+1} = \theta_t - \eta \nabla_{\theta} L(\theta_t) $$
1.4.4 Adam 优化器
结合 Momentum(动量)与 RMSProp(自适应学习率),是深度学习中最常用的优化器。
$$ \begin{aligned} m_t &= \beta_1 m_{t-1} + (1-\beta_1) g_t \ v_t &= \beta_2 v_{t-1} + (1-\beta_2) g_t^2 \ \hat{m}_t &= m_t / (1-\beta_1^t) \ \hat{v}t &= v_t / (1-\beta_2^t) \ \theta &= \theta_t - \eta \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} \end{aligned} $$
PyTorch 损失与优化器示例:
python
import torch
import torch.nn as nn
import torch.optim as optim
# 定义模型
model = nn.Linear(10, 2)
# 损失函数
criterion = nn.CrossEntropyLoss() # 分类
# criterion = nn.MSELoss() # 回归
# 优化器
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# optimizer = optim.Adam(model.parameters(), lr=0.001)
# 模拟训练一步
x = torch.randn(16, 10)
y = torch.randint(0, 2, (16,))
output = model(x)
loss = criterion(output, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"Loss: {loss.item():.4f}")1.5 批量归一化与 Dropout 正则化
1.5.1 批量归一化(Batch Normalization)
对每个 mini-batch 进行归一化,使激活值分布在合理范围内,加速训练并缓解过拟合。
公式:
$$ \hat{x}^{(k)} = \frac{x^{(k)} - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}} $$
$$ y^{(k)} = \gamma^{(k)} \hat{x}^{(k)} + \beta^{(k)} $$
其中 $\mu_B, \sigma_B$ 分别是 mini-batch 的均值和方差,$\gamma, \beta$ 是可学习参数。
1.5.2 Dropout
训练时以概率 $p$ 随机丢弃神经元,迫使网络学习冗余特征,防止过拟合。
python
import torch.nn as nn
class RegularizedMLP(nn.Module):
def __init__(self, input_dim=784, hidden_dim=512, output_dim=10):
super().__init__()
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.BatchNorm1d(hidden_dim), # 批量归一化
nn.ReLU(),
nn.Dropout(0.5), # 50% Dropout
nn.Linear(hidden_dim, output_dim)
)
def forward(self, x):
return self.net(x)
model = RegularizedMLP()
print(model)小结
| 概念 | 关键要点 |
|---|---|
| 感知机 | 线性分类器,无法解决 XOR |
| 多层感知机 | 引入隐藏层 + 激活函数解决非线性 |
| 反向传播 | 链式法则逐层计算梯度 |
| 激活函数 | ReLU 默认首选,Sigmoid 用于二分类输出 |
| 损失函数 | CrossEntropy(分类)、MSE(回归) |
| 优化器 | Adam 最常用,SGD + Momentum 也有效 |
| 正则化 | BatchNorm 加速训练,Dropout 防过拟合 |
练习
- 代码填空:手写一个 3 层 MLP(输入 784 → 隐藏 256 → 隐藏 128 → 输出 10),使用 ReLU 激活和 Adam 优化器。
- 推导题:画出反向传播中 $L = (wx + b)^2$ 的计算图,并写出 $\partial L / \partial w$ 的链式展开。
- 对比分析:分别用 Sigmoid 和 ReLU 作为隐藏层激活函数训练 MLP,观察收敛速度差异并解释原因。
- 调优实验:在同一个 MLP 上对比不加正则化、加 BatchNorm、加 Dropout(p=0.5) 三种情况下的验证集准确率。