我正在尝试学习一个seq2seq模型。 嵌入层位于编码器中,有时会在迭代后输出 nan 值。 我无法确定原因。 我该如何解决这个问题?? 问题是下面代码中转发函数中的第一个emb_layer。
class TransformerEncoder(nn.Module):
def __init__(self, vocab_size, hidden_size=1024, num_layers=6, dropout=0.2, input_pad=1, batch_first=False, embedder=None, init_weight=0.1):
super(TransformerEncoder, self).__init__()
self.input_pad = input_pad
self.vocab_size = vocab_size
self.num_layers = num_layers
self.embedder = embedder
if embedder is not None:
self.emb_layer = embedder
else:
self.emb_layer = nn.Embedding(vocab_size, hidden_size, padding_idx=1)
self.positional_encoder = PositionalEncoder()
self.transformer_layers = nn.ModuleList()
for _ in range(num_layers):
self.transformer_layers.append(
TransformerEncoderBlock(num_heads=8, embedding_dim=1024, dropout=dropout))
def set_mask(self, inputs):
self.input_mask = (inputs == self.input_pad).unsqueeze(1)
def forward(self, inputs):
x = self.emb_layer(inputs)
x = self.positional_encoder(x)
通常是输入多于权重,往往会变成nan(要么太高,要么太低(。也许这些开始是不正确的,并在一些梯度后恶化。您可以通过简单的条件检查运行张量或 np.array 来识别这些输入,例如:
print("Inp value too high") if len(bert_embeddings[bert_embeddings>1000]) > 1 else None
对于初学者来说,一个常见的错误是使用torch.empty而不是torch.zeros。随着时间的推移,这总是导致楠
。如果你所有的输入都是好的,那么这就是消失或爆炸梯度的问题。查看几次迭代后问题是否恶化。探索通常可以解决此类问题的不同激活或剪切渐变。如果您使用的是最新的优化器,则通常不必担心调整学习率。
看起来有些权重变成了nan。其中一个可能的原因是,在某些迭代中,层输出是 +-inf。如果它向前输出为 +-inf,向后输出它将具有 +-inf,并且由于 inf - inf = none,权重将变为 none,并且在所有后续迭代中将输出 none。
您可以通过跟踪 inf 输出来检查这一点 emb_layer.
如果这是原因,请尽量避免可能返回 inf 值的函数。
与我所遵循的教程的维度相比,我的数据库非常小,而且我的嵌入对于我的可用数据来说太大了,所以最终 NaN 通过网络传播。使我的嵌入网络更小(矩阵中的因子/列数量较少(为我解决了 NaN 问题。