创作理由:看了很多,我就发现很多都绕不开梯度问题,很多东西都说可以减轻训练过程中的梯度消失问题(比如某些激活函数、Resunit残差单元),如果你的神经网络梯度问题不再是问题,或者你解决的很好,那就很牛逼了,今天我就对这个论论,集集资料。
是什么?
梯度问题一般分两种:
- 梯度消失:梯度层层传播时变得越来越小,导致前面几层的参数几乎无法更新,网络“学不会”基础特征。
- 梯度爆炸:梯度传播中变得越来越大,导致参数更新剧烈震荡,训练发散。
这两种问题都是在深层网络中进行反向传播时出现的。
为啥这么重要呢?
- 如果梯度太小,前面的层无法学习;如果太大,模型根本不收敛。反正就是训练都是个问题,更何谈预测了。
2. 它影响训练效率和效果
- 比如你想训练一个识别手写数字的网络,结果训练了半天发现Loss下降非常慢,或者训练根本就无法收敛。
怎么优化?
①残差网络:自从残差网络出现,如今的深度网络很轻松就能够构建几百层,千层也不用担心梯度消失过快的问题,原因就在于跨层连接,而非直来直去,其中残差单元如下图所示:

import torch
import torch.nn as nn
import torch.nn.functional as F
class ResidualBlock(nn.Module):
def __init__(self, in_channels):
super(ResidualBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)
def forward(self, x):
return F.relu(self.conv2(F.relu(self.conv1(x))) + x) # 残差连接
# 测试
x = torch.randn(1, 64, 32, 32) # 输入
block = ResidualBlock(64)
y = block(x)
print(y.shape) # 输出大小保持不变
import torch
import torch.nn as nn
import torch.nn.functional as F
class SimpleMLP(nn.Module):
def __init__(self):
super(SimpleMLP, self).__init__()
self.fc1 = nn.Linear(784, 256)
self.fc2 = nn.Linear(256, 10)
def forward(self, x):
return self.fc2(F.relu(self.fc1(x))) # 使用ReLU激活
# 测试
x = torch.randn(1, 784) # 输入
model = SimpleMLP()
out = model(x)
print(out.shape) # 输出是10个类别
③优化方法集合:
方法类别 | 具体技术或策略 | 原理概述 |
激活函数优化 | ReLU, LeakyReLU, ELU 等 | 保持非零梯度 |
网络结构设计 | ResNet, DenseNet, HighwayNet | 保证梯度流畅传播 |
参数初始化 | Xavier, He | 防止前向/反向过程中方差偏移 |
正则化方法 | BatchNorm, LayerNorm | 稳定分布,防止梯度震荡 |
优化器改进 | Adam, RMSProp | 自适应调整学习率,应对不同梯度规模 |
梯度裁剪 | Gradient Clipping | 限制最大梯度,防止爆炸 |
损失函数设计 | Focal Loss(分类中处理样本不均衡) | 间接解决梯度不平衡问题 |
















