torch.nn.init常用函数包括kaiming_normal_(适配ReLU)、xavier_normal_(适配Sigmoid/Tanh)、orthogonal_(LSTM/GRU隐藏权重)、constant_(偏置初始化);需用model.apply()批量按类型初始化,注意下划线原地修改、判空bias、GPU兼容性及预训练模型中慎重置关键层。

torch.nn.init 有哪些常用初始化函数,各自适用什么场景
权重初始化不是“随便设个随机数”,不同层、不同激活函数对初始分布敏感度差异很大。比如 ReLU 激活的网络用 torch.nn.init.normal_ 容易导致大量神经元死亡,而 torch.nn.init.kaiming_normal_ 就是专为它设计的。
常见组合:
-
kaiming_normal_:配合ReLU或其变体(LeakyReLU),默认mode='fan_in',推荐作为 CNN 和大多数 MLP 的首选 -
xavier_normal_:适合Sigmoid或Tanh激活,假设输入输出方差相近,现在用得少了 -
orthogonal_:LSTM、GRU 的隐藏到隐藏权重常用,保持梯度传播稳定性 -
constant_:偏置项常设为0,但某些任务(如检测中分类头的背景先验)会设为负值(如-math.log((1 - 0.01) / 0.01))
怎么给模型中特定类型的层批量初始化,而不是逐层手写
手动调用 init.xxxx_(m.weight) 很容易漏掉某一层,或误对 BatchNorm 的 weight 做了不该做的初始化。正确做法是用 model.apply() 遍历所有子模块,并加类型判断。
典型写法:
def init_weights(m):
if isinstance(m, torch.nn.Linear) or isinstance(m, torch.nn.Conv2d):
torch.nn.init.kaiming_normal_(m.weight, nonlinearity='relu')
if m.bias is not None:
torch.nn.init.constant_(m.bias, 0)
elif isinstance(m, torch.nn.BatchNorm2d):
torch.nn.init.constant_(m.weight, 1)
torch.nn.init.constant_(m.bias, 0)
<p>model.apply(init_weights)
注意:BatchNorm 的 weight 默认是 1,不是随机初始化;它的 running_mean 和 running_var 是运行时统计量,不能用 init 函数碰。
为什么 init.xxxx_ 后模型没变化,或者报错 “can't assign a Tensor”
最常见原因是忘了下划线后缀 —— torch.nn.init.xavier_normal(无下划线)返回新 Tensor,不修改原参数;而 torch.nn.init.xavier_normal_(带下划线)才原地修改。PyTorch 所有 in-place 初始化函数都带 _。
其他高频错误:
- 对已绑定的参数(如
nn.Parameter)直接赋值失败:必须用.data或.copy_(),但更安全的是用_版本函数 - 对
None的bias调用初始化:务必先判空,否则AttributeError - 在模型已 move to GPU 后再初始化:没问题,
init函数会自动适配 tensor 设备
预训练模型加载后还能不能重新初始化某几层
可以,但要注意顺序。如果先 load_state_dict() 再初始化,那初始化会被覆盖;必须在 load_state_dict(..., strict=False) 之后,单独对要重置的层调用 init 函数。
例如只重置分类头:
model.load_state_dict(checkpoint, strict=False) torch.nn.init.kaiming_normal_(model.classifier.weight, nonlinearity='relu') torch.nn.init.constant_(model.classifier.bias, 0)
这里 strict=False 很关键:避免因分类头维度不匹配导致整个加载失败。另外,别试图用 init 重置 Embedding 层的 weight —— 它通常依赖预训练语义,乱初始化会让下游任务彻底崩掉。
真正容易被忽略的是:初始化操作本身没有“记忆”,也不会影响后续 optimizer.step() 的行为。它只是一次性写入数值,后续是否更新,完全由参数是否 requires_grad 和 optimizer 是否管理它决定。


















