神经网络的核心组件
1️⃣ 网络层(Layers)------负责"特征变换"
神经网络的本质,是把原始输入一步步变换为更有用、更抽象的特征表示,最终完成分类、预测或生成任务。这个"变换"的工作,就由**网络层(Layers)**来完成。它们就像大楼的"结构梁柱",支撑起整个模型的计算流程。
换句话说,网络层的任务是:
把输入的特征 xxx 通过一系列线性或局部运算,映射到新的空间中,让模型能够逐步提取出更有价值的信息。
1. 线性层(Linear / 全连接层)
作用:完成"特征的线性变换",是最基础、最常见的神经网络层。
数学形式 :
y=Wx+b y = W x + b y=Wx+b
- x:输入向量(特征)
- WWW:权重矩阵(模型要学习的参数)
- bbb:偏置项(bias)
- yyy:输出向量(新的特征表示)
它的功能就像一个"线性投影":从原始特征空间投射到另一个维度空间,为后续处理打下基础。
代码示例(PyTorch):
python
import torch
import torch.nn as nn
# 输入维度: 100个特征, 输出维度: 128个特征
linear = nn.Linear(in_features=100, out_features=128)
# 输入: batch_size=32, 每个样本100个特征
x = torch.randn(32, 100) # shape: [32, 100]
y = linear(x) # shape: [32, 128]
# 参数数量计算: out_features × in_features + out_features = 128 × 100 + 128 = 12,928
print(f"权重矩阵形状: {linear.weight.shape}") # [128, 100]
print(f"偏置向量形状: {linear.bias.shape}") # [128]
🔎 应用场景:
- 多层感知机(MLP)中最基本的计算单元
- Transformer 中的前馈网络(Feed-Forward)层
- 分类器输出层(例如:
nn.Linear(128, 10)输出 10 个类别的 logits)
2. 卷积层(Conv1d / Conv2d)
作用 :提取局部特征,常用于处理具有空间结构的数据(如图像、语音、时间序列)。
核心思想 :与其让全连接层"看见"全部特征,不如让卷积层关注局部邻域,一步步从局部构建整体认知。
数学形式(二维卷积,完整公式):
yi,j=∑m=0kh−1∑n=0kw−1Wm,n⋅xi×sh+m−ph,j×sw+n−pw+b y_{i,j} = \sum_{m=0}^{k_h-1} \sum_{n=0}^{k_w-1} W_{m,n} \cdot x_{i \times s_h + m - p_h, j \times s_w + n - p_w} + b yi,j=m=0∑kh−1n=0∑kw−1Wm,n⋅xi×sh+m−ph,j×sw+n−pw+b
- kh,kwk_h, k_wkh,kw:卷积核高度、宽度
- sh,sws_h, s_wsh,sw:垂直、水平步长(stride)
- ph,pwp_h, p_wph,pw:垂直、水平填充(padding)
代码示例(PyTorch):
python
# 二维卷积示例
conv = nn.Conv2d(
in_channels=3, # 输入通道数(RGB图像)
out_channels=64, # 输出通道数(卷积核数量)
kernel_size=3, # 卷积核大小 3x3
stride=1, # 步长
padding=1 # 填充(保持尺寸不变)
)
# 输入: batch=8, 3通道, 224x224图像
x = torch.randn(8, 3, 224, 224)
y = conv(x) # shape: [8, 64, 224, 224]
输出尺寸计算公式 :
KaTeX parse error: Expected 'EOF', got '_' at position 13: \text{output_̲size} = \left\l...
- 卷积核(Kernel)在输入上滑动,提取局部模式
- 权重共享、稀疏连接 → 参数量大幅减少
- 可视为"特征提取器",能自动发现边缘、纹理、形状等结构特征
🔎 应用场景:
- 图像分类(CNN)
- 时间序列模式提取(Conv1d)
- 自然语言处理中的局部 n-gram 提取
3. 池化层(Pooling)
作用 :对特征图进行降维与摘要 ,保留最重要的信息,提升模型的平移不变性 和计算效率。
常见类型:
- 最大池化(MaxPool):取窗口内最大值,突出"最强信号"。
- 平均池化(AvgPool):取窗口内平均值,保留整体趋势。
例子(最大池化):
输入:[[1, 3],
[2, 4]]
输出:4 (窗口内最大值)
代码示例(PyTorch):
python
# 最大池化和平均池化
max_pool = nn.MaxPool2d(kernel_size=2, stride=2)
avg_pool = nn.AvgPool2d(kernel_size=2, stride=2)
# 输入: 64通道, 224x224特征图
x = torch.randn(8, 64, 224, 224)
y_max = max_pool(x) # shape: [8, 64, 112, 112] → 尺寸减半
y_avg = avg_pool(x) # shape: [8, 64, 112, 112]
🔎 应用场景:
- CNN 中减少特征图尺寸,降低计算量
- 提高模型的鲁棒性(不敏感于平移或小扰动)
4. 归一化层(Normalization Layers)
作用:稳定训练过程、加速收敛,让模型更容易"学会"。
为什么需要它?在深层网络中,随着数据一层层传递,分布可能发生漂移(Internal Covariate Shift),导致训练难以收敛。归一化层通过"重置"分布,让每层看到的数据都处于合适的范围。
常见类型:
- BatchNorm:对每个 mini-batch 的均值和方差归一化(常用于 CNN)
- LayerNorm:对单个样本的所有特征归一化(常用于 Transformer)
完整公式(BatchNorm):
x^=x−μBσB2+ϵ \hat{x} = \frac{x - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}} x^=σB2+ϵ x−μB
y=γ⋅x^+β y = \gamma \cdot \hat{x} + \beta y=γ⋅x^+β
- μB\mu_BμB、σB\sigma_BσB:该 batch 的均值与标准差
- γ\gammaγ、β\betaβ:可学习参数(缩放和偏移)
- ϵ\epsilonϵ:防止除零的小常数(通常为 10−510^{-5}10−5)
代码示例(PyTorch):
python
# BatchNorm示例(CNN常用)
batch_norm = nn.BatchNorm2d(num_features=64)
# LayerNorm示例(Transformer常用)
layer_norm = nn.LayerNorm(normalized_shape=512)
# 使用
x = torch.randn(8, 64, 224, 224)
y = batch_norm(x) # 对每个通道的batch维度归一化
x_seq = torch.randn(8, 128, 512) # [batch, seq_len, hidden_dim]
y_seq = layer_norm(x_seq) # 对最后一维归一化
🔎 效果:
- 减少梯度爆炸/消失
- 提高训练速度
- 对初始学习率不敏感
5. Dropout 层
作用 :防止过拟合(overfitting),提升模型的泛化能力。
工作机制 :在训练时,随机"丢弃"一部分神经元的输出(例如 30%),迫使网络不能依赖某个特定路径,而是学会冗余表达。
简单示意:
原始输出:[0.2, 0.5, 0.7, 0.9]
Dropout后:[0.2, 0.0, 0.7, 0.0]
典型 Dropout Rate 范围:
| 位置 | 推荐 Dropout Rate |
|---|---|
| 全连接层 | 0.3 ~ 0.5 |
| Transformer注意力 | 0.1 ~ 0.3 |
| 卷积层 | 0.1 ~ 0.2 |
代码示例(PyTorch):
python
dropout = nn.Dropout(p=0.5) # 随机丢弃50%的神经元
# 训练模式(默认)
x = torch.randn(32, 128)
y_train = dropout(x) # 部分神经元被置零
# 推理模式(关闭dropout)
dropout.eval()
y_infer = dropout(x) # 输出不变,自动按1/(1-p)缩放
- 推理阶段(inference)自动关闭 Dropout,并按比例缩放输出。
🔎 应用场景:
- 全连接层之后(MLP、分类器)
- Transformer 的注意力和 FFN 中
小结:网络层的本质
| 层类型 | 核心功能 | 本质机制 |
|---|---|---|
| 线性层 | 全局特征变换 | 矩阵乘法 + 参数学习 |
| 卷积层 | 局部特征提取 | 权重共享 + 局部感受野 |
| 池化层 | 降维与特征摘要 | 无参数的聚合操作 |
| 归一化层 | 稳定分布、加速收敛 | 标准化 + 可学习仿射变换 |
| Dropout 层 | 防止过拟合、提升泛化能力 | 随机屏蔽部分神经元输出 |
2️⃣ 激活函数(Activations)------负责"非线性表达"
如果只有线性层的叠加,整体仍等价于一个线性变换(线性可合并)。激活函数 通过在每一层引入非线性,让网络能表示复杂函数、学习高阶模式,是"让网络真正有智力"的关键。
概念要点:输出范围、是否零中心、是否有饱和区、梯度形态、计算代价、鲁棒性。
1) Sigmoid(S 形函数)
定义
σ(x)=11+e−x,σ′(x)=σ(x) 1−σ(x) \sigma(x)=\frac{1}{1+e^{-x}},\quad \sigma'(x)=\sigma(x)\,1-\\sigma(x) σ(x)=1+e−x1,σ′(x)=σ(x)1−σ(x)
性质与优缺点
- 输出范围:(0,1) ;非零中心(平均偏正),对后续层的梯度传播不利。
- 饱和 :当 |x| 很大时,梯度接近 0 → 梯度消失问题严重。
- 计算代价:包含
exp,略高于分段线性函数。 - 典型用途:输出层 的二分类概率(配合
BCELoss/BCEWithLogitsLoss)。 - 隐藏层中较少使用(容易梯度消失、收敛慢)。
PyTorch
python
act = torch.nn.Sigmoid()
2) Tanh(双曲正切)
定义
tanh(x)=ex−e−xex+e−x,tanh′(x)=1−tanh2(x) \tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}},\quad \tanh'(x)=1-\tanh^2(x) tanh(x)=ex+e−xex−e−x,tanh′(x)=1−tanh2(x)
性质与优缺点
- 输出范围:(-1, 1) ;零中心,相对 Sigmoid 更利于优化。
- 仍有饱和区(|x| 大时梯度趋近 0),深层网络中也会造成梯度衰减。
- 在浅层或循环网络的早期实践中较常见,现代深网多被 ReLU 系列替代。
PyTorch
python
act = torch.nn.Tanh()
3) ReLU(Rectified Linear Unit)
定义
ReLU(x)=max(0,x),ReLU′(x)={0,x<01,x>0 \mathrm{ReLU}(x)=\max(0,x),\quad \mathrm{ReLU}'(x)=\begin{cases} 0, & x<0\\ 1, & x>0 \end{cases} ReLU(x)=max(0,x),ReLU′(x)={0,1,x<0x>0
(在 0 处不可导,实践中取次梯度 0 或 1 均可。)
性质与优缺点
- 输出范围:[0, +∞) ;非零中心。
- 无上饱和、计算便宜(分段线性),大幅缓解梯度消失 → 训练深网"默认首选"。
- 缺点:ReLU 死亡(dead ReLU)------若权重更新使大量神经元长期处于负半轴,梯度为 0,单元"失活"。
- 与 He/Kaiming 初始化、较大学习率、BatchNorm 常搭配。
PyTorch
python
act = torch.nn.ReLU(inplace=True)
4) LeakyReLU(带泄露的 ReLU)
定义
LeakyReLU(x)={x,x≥0αx,x<0,α∈(0,1) \mathrm{LeakyReLU}(x)=\begin{cases} x, & x\ge 0\\ \alpha x, & x<0 \end{cases},\quad \alpha\in(0,1) LeakyReLU(x)={x,αx,x≥0x<0,α∈(0,1)
性质与优缺点
- 在负半轴保留一个小斜率 α\alphaα (如 0.01),降低 dead ReLU 风险。
- 输出范围:负无穷, 正无穷;非零中心。
- 与 ReLU 计算代价相近,训练更稳定;常作为 ReLU 的"稳健替代"。
PyTorch
python
act = torch.nn.LeakyReLU(negative_slope=0.01, inplace=True)
5) ELU(Exponential Linear Unit)
定义
ELU(x)={x,x≥0α (ex−1),x<0 \mathrm{ELU}(x)=\begin{cases} x, & x\ge 0\\ \alpha\,(e^x-1), & x<0 \end{cases} ELU(x)={x,α(ex−1),x≥0x<0
常取 α=1.0。
性质与优缺点
- 负半轴是平滑的指数曲线 ,输出可为负值,更接近零中心。
- 相比 ReLU,负侧有非零梯度(缓解 dead ReLU),并在小负值附近提供更平滑更新。
- 计算代价略高(需要
exp)。 - 在噪声较大或对平滑性更敏感的场景,ELU 往往更稳。
PyTorch
python
act = torch.nn.ELU(alpha=1.0, inplace=True)
6) 导数特性对比
| 函数 | 导数范围 | 梯度流动特性 |
|---|---|---|
| Sigmoid | (0, 0.25] | 易消失 |
| Tanh | (0, 1] | 较易消失 |
| ReLU | {0, 1} | 梯度恒为1或0 |
| LeakyReLU | α, 1 | 梯度有下界 |
| ELU | (-α, 1] | 平滑非零 |
7) 完整模型示例
python
class MyNet(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 256)
self.act1 = nn.ReLU(inplace=True) # inplace节省内存
self.fc2 = nn.Linear(256, 128)
self.act2 = nn.LeakyReLU(negative_slope=0.1)
self.fc3 = nn.Linear(128, 10) # 输出层不加激活(配合CrossEntropyLoss)
def forward(self, x):
x = x.view(-1, 784) # 展平
x = self.act1(self.fc1(x))
x = self.act2(self.fc2(x))
x = self.fc3(x)
return x
8) 选择与实践建议(面向工程落地)
| 函数 | 输出范围 | 零中心 | 饱和区 | 计算代价 | 常见问题/优势 | 常用场景 |
|---|---|---|---|---|---|---|
| Sigmoid | (0, 1) | 否 | 是 | 中 | 梯度消失,非零中心 | 二分类输出层(配合 BCE) |
| Tanh | (-1, 1) | 是 | 是 | 中 | 比 Sigmoid 好,但仍会消失 | 较浅网络/特定 RNN 旧方案 |
| ReLU | [0, +∞) | 否 | 否(负半轴梯度0) | 低 | 训练快,可能出现 dead ReLU | 默认首选隐藏层 |
| LeakyReLU | (-∞, +∞) | 否 | 否 | 低 | 缓解 dead ReLU,稳健 | ReLU 的稳健替代 |
| ELU | (-α, +∞) | 近似是 | 否 | 中 | 平滑、负侧非零梯度,稳定但稍贵 | 对稳定/平滑敏感的隐藏层 |
经验法则
- 默认用 ReLU ;若发现大量神经元失活或训练不稳,改 LeakyReLU (
negative_slope=0.01~0.2可调)。 - 对数值稳定和平滑性有要求(如对噪声敏感、轻量网络),可尝试 ELU。
- 输出层 :
- 二分类 →
nn.Sigmoid(或直接用BCEWithLogitsLoss+ 去掉 Sigmoid,由 loss 内部稳定计算)。 - 多分类 →
nn.Softmax(dim=1)(或CrossEntropyLoss+ 直接用 logits,不显式 Softmax)。
- 二分类 →
- 初始化与归一化:ReLU/LeakyReLU 常配 Kaiming(He) 初始化 ;配合 BatchNorm/LayerNorm 往往更稳。
- 学习率:ReLU 系列常可用稍大 学习率,Sigmoid/Tanh 宜小,避免饱和。
3️⃣ 学习机制(Learning Components)------ 负责"训练与优化"
如果说"网络层"和"激活函数"共同构建了模型的身体,让它能够从输入数据一路走到输出预测,那么"学习机制"就是模型的大脑和教练,负责指导这个身体如何通过学习变得更聪明、更准确。
这一类组件本身不参与模型最终的"前向推理"(即预测过程),但它们是模型训练阶段的核心,定义了"好"模型的标准,并指导模型如何一步步达到这个标准。
损失函数(Loss Functions)
损失函数,也叫成本函数(Cost Function),是用来"量化"模型预测结果与真实标签之间差距的工具。这个"差距"就是我们常说的"损失"(Loss)。损失越小,说明模型预测得越准。训练模型的目标,本质上就是最小化损失函数的值。
更多损失函数类型
| 损失函数 | 适用场景 | 特点 |
|---|---|---|
| MSELoss | 回归 | 对大误差惩罚重 |
| L1Loss | 回归 | 对异常值更鲁棒 |
| SmoothL1Loss | 回归 | 结合MSE和L1优点 |
| CrossEntropyLoss | 多分类 | 内置Softmax |
| BCEWithLogitsLoss | 二分类 | 数值稳定 |
| NLLLoss | 多分类 | 需要LogSoftmax输出 |
代码示例(PyTorch)
python
import torch.nn.functional as F
# 回归任务
mse_loss = nn.MSELoss()
l1_loss = nn.L1Loss()
smooth_l1 = nn.SmoothL1Loss()
y_true = torch.randn(32, 10)
y_pred = torch.randn(32, 10)
loss = mse_loss(y_pred, y_true)
# 分类任务
ce_loss = nn.CrossEntropyLoss()
bce_loss = nn.BCEWithLogitsLoss()
# 多分类:logits直接输入(无需Softmax)
logits = torch.randn(32, 10)
labels = torch.randint(0, 10, (32,))
ce = ce_loss(logits, labels)
# 二分类:logits直接输入(无需Sigmoid)
logits_bin = torch.randn(32, 1)
labels_bin = torch.randint(0, 2, (32, 1)).float()
bce = bce_loss(logits_bin, labels_bin)
-
均方误差损失 (MSELoss - Mean Squared Error Loss)
- 应用场景 :最常用于回归任务,例如预测房价、股票价格或温度。
- 工作原理 :它会计算每个预测值与真实值之差的平方,然后求所有样本的平均值。公式为:L=1N∑i=1N(yi−y^i)2 L = \frac{1}{N}\sum_{i=1}^{N}(y_i - \hat{y}_i)^2 L=N1i=1∑N(yi−y^i)2 其中,yi 是真实值,y^i 是模型的预测值。
- 直观理解:MSE 对较大的误差给予"更重"的惩罚。比如,误差为 2 时,损失是 4;误差为 3 时,损失是 9。这使得模型会更努力地去修正那些离谱的预测。
-
交叉熵损失 (CrossEntropyLoss)
-
应用场景 :分类任务的"黄金标准",包括二分类 和多分类。
-
工作原理:它衡量的是模型预测的概率分布与真实的概率分布之间的"距离"。在分类问题中,真实标签的概率分布是"one-hot"形式(即正确类别为 1,其他为 0)。如果模型预测的概率分布与这个真实分布越接近,交叉熵损失就越小。
-
直观理解:假设模型预测图片是"猫"的概率为 0.9,是"狗"的概率为 0.1。如果真实标签是"猫",那么损失就很小;如果真实标签是"狗",那么这个预测的"自信"就用错了地方,损失就会很大。它不仅关心模型是否"猜对",更关心它对正确答案的"确信程度"。
-
注意 :在 PyTorch 等框架中,
CrossEntropyLoss通常已经内置了Softmax或LogSoftmax操作,因此我们不需要在网络最后一层手动添加它。
-
优化器(Optimizers)
有了损失函数计算出的"误差信号",优化器就知道模型"错得有多离谱"。接下来,优化器的任务就是根据这个误差,去调整网络中所有可学习的参数(主要是权重 weights 和偏置 biases),目标是让损失下一次能变得更小。
这个过程就像下山:损失函数告诉我们当前在山上的哪个位置以及有多高(损失值),而优化器则负责决定下一步该朝哪个方向、迈多大的步子,才能最快到达山底(损失最低点)。
优化器参数对比
| 参数 | SGD | Adam | AdamW |
|---|---|---|---|
| lr | 需要手动调 | 自适应 | 自适应 |
| momentum | 可选 | 内置 | 内置 |
| weight_decay | 直接应用 | 与梯度耦合 | 解耦应用 |
| 收敛速度 | 较慢 | 较快 | 较快 |
| 内存占用 | 低 | 较高 | 较高 |
完整训练循环示例
python
import torch.optim as optim
# 定义模型、损失、优化器
model = MyNet()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-4)
# 训练循环
num_epochs = 10
for epoch in range(num_epochs):
model.train() # 设置训练模式
running_loss = 0.0
for batch_idx, (data, targets) in enumerate(train_loader):
# 前向传播
outputs = model(data)
loss = criterion(outputs, targets)
# 反向传播
optimizer.zero_grad() # 清空梯度
loss.backward() # 计算梯度
optimizer.step() # 更新参数
running_loss += loss.item()
# 验证
model.eval() # 设置评估模式
correct = 0
total = 0
with torch.no_grad(): # 禁用梯度计算
for data, targets in val_loader:
outputs = model(data)
_, predicted = torch.max(outputs.data, 1)
total += targets.size(0)
correct += (predicted == targets).sum().item()
print(f"Epoch {epoch+1}/{num_epochs}, "
f"Loss: {running_loss/len(train_loader):.4f}, "
f"Accuracy: {100*correct/total:.2f}%")
- 随机梯度下降 (SGD - Stochastic Gradient Descent)
- 工作原理:最基础、最经典的优化器。它会随机抽取一小批(mini-batch)数据,计算这批数据的平均梯度(即损失函数对每个参数的偏导数),然后让参数沿着梯度的反方向更新一小步。
- 特点:简单有效,但可能收敛较慢,且容易陷入局部最优解(卡在某个小山谷出不来)。它的一个重要改进是加入了"动量(Momentum)",模拟了物理世界中物体运动的惯性,有助于冲出局部最优,并加速收敛。
- Adam (Adaptive Moment Estimation)
- 工作原理:目前最主流、最常用的优化器之一,被誉为是"集大成者"。它结合了动量(Momentum)和 RMSProp 两种优化算法的思想。
- 特点 :
- 自适应学习率:它能为网络中的每一个参数计算出不同的、自适应的学习率。对于不常更新的参数,它会用较大的步长;对于频繁更新的参数,它会用较小的步长,使得训练过程更稳定、高效。
- 动量:它也借鉴了动量的思想,会累积过去的梯度信息,帮助加速收敛。
- 适用性:由于其鲁棒性和高效性,Adam 通常是大多数任务的"首选默认优化器"。
- AdamW (Adam with Weight Decay)
- 工作原理:这是对 Adam 的一个重要改进。原始的 Adam 算法中,权重衰减(Weight Decay,一种防止过拟合的技术)的实现方式与梯度更新耦合在一起,效果并不理想。
- 特点:AdamW 将权重衰减从梯度更新中"解耦"出来,使其成为一个独立的步骤。这种修正方式被证明在很多现代深度学习模型(如 Transformers)中能取得更好的性能和泛化能力。
👉 总结: 这一类组件的本质是 "如何学习",它们不参与前向推理,但决定了模型能否、以及能多快地从训练数据中学习到有用的模式,最终变得更好。一个好的模型,离不开损失函数和优化器的精妙配合。