单TransformerEncoder层模型训练前确定,训练后为何非确定性?
问题原因及解决方案
核心原因
你的代码里有两个关键问题,其中直接导致推理结果不稳定的是动态创建未注册的线性层:
- 在
forward函数中直接用nn.Linear(2,1)(y),会让每次执行推理时都新建一个随机初始化的线性层,该层的权重和偏置完全随机,所以每次输出结果必然不同。 - 这个动态创建的线性层没被注册为模型的子模块,既不会参与训练(优化器不会更新它的参数),也不受
model.eval()的影响——不过Linear层本身没有随机组件,核心问题还是每次新建带来的随机性。
你提到“未训练时具备确定性”,大概率是因为未训练时只执行了一次推理,或是误判了多次执行的结果;实际上如果未训练时多次调用模型,同样会因为动态创建线性层导致输出不同。
修复方案
把线性层的定义移到模型的__init__方法中,注册为模型的子模块,确保训练时参数被优化,推理时使用固定的训练后参数:
import torch from torch import nn import torch.optim as optim class MyModel(nn.Module): def __init__(self): super().__init__() self.encoder_layer = nn.TransformerEncoderLayer(d_model=1, nhead=1, dim_feedforward=2) self.trans = nn.TransformerEncoder(self.encoder_layer, num_layers=1) # 将线性层注册为模型子模块 self.fc = nn.Linear(2, 1) def forward(self, x): y = self.trans(x) y = torch.flatten(y) # 使用注册好的线性层 y = self.fc(y) return y model = MyModel() model.train() optimizer = optim.Adam(model.parameters(), lr=0.01) for epoch in range(1): training = torch.rand(size=(2,1)) labels = training[0] + 1 optimizer.zero_grad() outputs = model(training) loss = nn.MSELoss()(outputs, labels) loss.backward() optimizer.step() model.eval() x = torch.tensor([[1.],[1.]]) # 多次执行也会得到相同输出 print(model(x)) print(model(x))
额外说明
TransformerEncoderLayer默认包含Dropout层,在train模式下会启用随机失活导致输出不确定,但你在推理前调用了model.eval(),该方法会自动关闭所有子模块的训练模式(包括Dropout),因此这部分不会导致推理结果不稳定。
内容的提问来源于stack exchange,提问作者JobHunter69
相关产品推荐
相关产品推荐

