固定随机种子后,PyTorch未使用参数为何影响模型性能?
未使用的PyTorch层为何会影响模型输出?
问题场景
在PyTorch中编写深度学习模型并固定了随机种子后,发现一个奇怪的现象:StaticEmbedding类的__init__方法里定义了linear_1和linear_2两个线性层,但这两个层从未在forward方法中被调用。然而移除它们之后,模型的输出结果却发生了变化。
示例代码如下:
class StaticEmbedding(nn.Module): def __init__(self, d_model, seq_len, mode='l'): super(StaticEmbedding, self).__init__() self.seq_len = seq_len self.linear_l = nn.Linear(27, seq_len) self.linear_d = nn.Linear(27, d_model//2) self.linear_p = nn.Linear(d_model//2, d_model) self.linear_1 = nn.Linear(27, d_model//2) # 未使用的层 self.linear_2 = nn.Linear(d_model//2, d_model) # 未使用的层 self.gelu = nn.GELU() self.tanh = nn.Tanh() def forward(self, static): static = static[:,None,:] if self.mode =='d': static = self.linear_d(static) elif self.mode == 'l': static = self.linear_l(static).transpose(1,2) elif self.mode == 'p': static = self.linear_d(static) static = self.linear_p(self.gelu(static)) static = self.tanh(static) return static
原因解析
这问题的核心和PyTorch的随机数生成逻辑、模型参数初始化流程直接相关:
全局随机种子的状态被消耗:PyTorch的随机种子是全局生效的,所有需要随机数的操作(比如层权重初始化)会按顺序消耗随机数生成器的状态。保留
linear_1和linear_2时,这两个层会在初始化阶段占用一部分随机数生成权重;移除它们后,后续真正用到的层(比如linear_l、linear_d)会使用之前被未使用层占用的随机数来初始化,导致这些层的初始权重和原来完全不同,最终模型输出自然产生差异。未使用层的参数注册间接影响:只要是
nn.Module子类的属性,都会被自动注册为模型的参数,哪怕没被forward调用。如果后续使用优化器,这些未使用的参数会被纳入优化器的参数列表,虽然训练时不会更新它们,但优化器的状态(比如动量缓存)可能会因为参数数量变化产生细微差异——不过这一点对输出的影响远小于初始化阶段的随机数消耗。
验证方法
如果想确认这个逻辑,可以做两个小实验:
- 保留未使用层,但把它们的初始化代码移到所有用到的层之后,此时模型输出会和移除它们后的结果一致(因为用到的层的初始化随机数状态没变)。
- 移除未使用层后,手动将用到的层的权重设置为保留未使用层时的权重值,此时模型输出会和原来完全相同。
内容的提问来源于stack exchange,提问作者Jay Li
相关产品推荐
相关产品推荐

