神经网络的核心组件

神经网络的核心组件

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−tanh⁡2(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 (-α, +∞) 近似是 平滑、负侧非零梯度,稳定但稍贵 对稳定/平滑敏感的隐藏层

经验法则

  1. 默认用 ReLU ;若发现大量神经元失活或训练不稳,改 LeakyReLUnegative_slope=0.01~0.2 可调)。
  2. 对数值稳定和平滑性有要求(如对噪声敏感、轻量网络),可尝试 ELU
  3. 输出层
    • 二分类 → nn.Sigmoid(或直接用 BCEWithLogitsLoss + 去掉 Sigmoid,由 loss 内部稳定计算)。
    • 多分类 → nn.Softmax(dim=1)(或 CrossEntropyLoss + 直接用 logits,不显式 Softmax)。
  4. 初始化与归一化:ReLU/LeakyReLU 常配 Kaiming(He) 初始化 ;配合 BatchNorm/LayerNorm 往往更稳。
  5. 学习率: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 通常已经内置了 SoftmaxLogSoftmax 操作,因此我们不需要在网络最后一层手动添加它。

优化器(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 两种优化算法的思想。
    • 特点
      1. 自适应学习率:它能为网络中的每一个参数计算出不同的、自适应的学习率。对于不常更新的参数,它会用较大的步长;对于频繁更新的参数,它会用较小的步长,使得训练过程更稳定、高效。
      2. 动量:它也借鉴了动量的思想,会累积过去的梯度信息,帮助加速收敛。
    • 适用性:由于其鲁棒性和高效性,Adam 通常是大多数任务的"首选默认优化器"。
  • AdamW (Adam with Weight Decay)
    • 工作原理:这是对 Adam 的一个重要改进。原始的 Adam 算法中,权重衰减(Weight Decay,一种防止过拟合的技术)的实现方式与梯度更新耦合在一起,效果并不理想。
    • 特点:AdamW 将权重衰减从梯度更新中"解耦"出来,使其成为一个独立的步骤。这种修正方式被证明在很多现代深度学习模型(如 Transformers)中能取得更好的性能和泛化能力。

👉 总结: 这一类组件的本质是 "如何学习",它们不参与前向推理,但决定了模型能否、以及能多快地从训练数据中学习到有用的模式,最终变得更好。一个好的模型,离不开损失函数和优化器的精妙配合。