共计 2426 个字符,预计需要花费 7 分钟才能阅读完成。
历史背景:DBN 如何破解梯度消失难题
2006 年 Hinton 团队在《Science》发表的论文《A Fast Learning Algorithm for Deep Belief Nets》提出深度信念网络 (DBN),其核心是通过 分层无监督预训练 解决反向传播 (BP) 在深层网络中的梯度消失问题。DBN 的基础构件是受限玻尔兹曼机(RBM),其能量函数定义为:

$$E(v,h) = -\sum_{i}a_iv_i – \sum_{j}b_jh_j – \sum_{i,j}v_iw_{ij}h_j$$
其中 $v$ 为可见层,$h$ 为隐藏层,$w_{ij}$ 是连接权重。训练采用对比散度 (CD-k) 算法,只需 k 步吉布斯采样即可近似梯度:
- 正向传播:$p(h_j=1|v) = \sigma(b_j + \sum_{i}v_iw_{ij})$
- 反向重构:$p(v_i=1|h) = \sigma(a_i + \sum_{j}h_jw_{ij})$
- 权重更新:$\Delta w_{ij} = \epsilon(\langle v_ih_j \rangle_{data} – \langle v_ih_j \rangle_{recon})$
这种逐层训练方式让每层 RBM 都能学习到数据的层次化表示,为后续微调提供良好初始化。
现代方案对比:从 RBM 到 ResNet
| 维度 | 2006 方案(RBM+DBN) | 现代方案(ReLU+ResNet) |
|---|---|---|
| 训练效率 | 需逐层预训练(小时级) | 端到端训练(分钟级) |
| 梯度传播 | 依赖 CD- k 近似 | 通过恒等连接直传梯度 |
| 初始化 | 数据依赖的预训练初始化 | Xavier/He 初始化 |
关键进步体现在:
– ReLU 激活函数缓解梯度饱和:$f(x)=max(0,x)$
– BatchNorm 层稳定分布:$\hat{x}=\frac{x-E[x]}{\sqrt{Var[x]+\epsilon}}$
– 残差连接实现恒等映射:$H(x)=F(x)+x$
代码实战:从原始方法到现代实践
RBM 预训练实现(PyTorch)
class RBM(nn.Module):
def __init__(self, visible_dim, hidden_dim):
super().__init__()
self.W = nn.Parameter(torch.randn(hidden_dim, visible_dim) * 0.1) # 权重矩阵
self.v_bias = nn.Parameter(torch.zeros(visible_dim)) # 可见层偏置
self.h_bias = nn.Parameter(torch.zeros(hidden_dim)) # 隐藏层偏置
def forward(self, v):
# CD- k 采样过程 (k=1)
h_prob = torch.sigmoid(F.linear(v, self.W, self.h_bias)) # p(h|v)
h_sample = torch.bernoulli(h_prob) # 采样隐藏层
v_recon = torch.sigmoid(F.linear(h_sample, self.W.t(), self.v_bias)) # 重构可见层
return v_recon
# 训练循环示例
for epoch in range(epochs):
for batch in dataloader:
v0 = batch # 原始数据 [batch_size, visible_dim]
vk = model(v0) # 重构数据
# 计算梯度并更新(简化版)positive_grad = torch.matmul(v0.t(), model(v0))
negative_grad = torch.matmul(vk.t(), model(vk))
model.W.grad = -(positive_grad - negative_grad).t()
optimizer.step()
Xavier 初始化对比实验
# 随机初始化 vs Xavier 初始化
def train_with_init(init_func):
model = nn.Sequential(nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
apply_init(model, init_func) # 应用初始化方法
# 训练并记录 loss 曲线
losses = []
for x, y in dataloader:
out = model(x)
loss = F.cross_entropy(out, y)
losses.append(loss.item())
return losses
# Xavier 初始化公式:W ~ U(-sqrt(6/(fan_in+fan_out)), sqrt(6/(fan_in+fan_out)))
xavier_loss = train_with_init(lambda m: nn.init.xavier_uniform_(m.weight))
random_loss = train_with_init(lambda m: nn.init.uniform_(m.weight, -1, 1))
生产建议:经久不衰的实践智慧
-
小数据迁移学习:当标注数据少于 1 万样本时,仍可采用 RBM-style 的预训练提升性能。例如在医疗影像分析中,先用无标注 CT 扫描预训练底层特征
-
学习率与深度关系:初始学习率应随网络深度 $L$ 调整,建议公式:$\eta = \eta_{base} \times \frac{1}{\sqrt{L}}$,避免深层参数更新震荡
-
梯度范数监控:在训练深度网络时,建议每 100 次迭代计算 $||\nabla_h^{(l)}||_2$(第 $l$ 层梯度范数),正常范围应在 $[10^{-5}, 10^{-3}]$ 之间
延伸思考
尽管 Transformer 等架构主导当前研究,但无监督预训练的思想在以下场景仍具价值:
– 当标注成本极高时(如蛋白质结构预测)
– 处理非平稳数据分布(如金融时间序列)
– 需要可解释性特征的领域(如医疗诊断)
一个开放问题:如果 2006 年就有现代 GPU,DBN 是否会发展出不同的技术路线?
