1.问题描述
在跑TNT_Distmult和T_Distmult模型的时候,有的时候回出现loss=nan的情况。有的时候则不会出现,相比来说TNT模型出现nan的情况更多一些。为了弄清楚是什么原因,进行如下实验。
2.实验过程
2.1实验一
猜测可能是因为梯度爆炸导致的,所以在l.backward()后面加了下面这条命令。(参考PyTorch梯度裁剪避免nan PyTorch梯度裁剪避免训练loss nan的操作(IT技术))
nn.utils.clip_grad_norm_(self.model.parameters(), max_norm=20, norm_type=2) ## 防止梯度爆炸
发现没什么卵用,结果还是会出现nan。
2.2实验二
因为每次训练参数初始化使用的是nn.Embedding这种,为了获得一致的初始化参数,固定随机化种子。使用这三条命令:
torch.manual_seed(0)
torch.cuda.manual_seed(0)
np.random.seed(0)
然后,重复实验发现每次都是在第四个epoch进行到中间的时候,出现nan报错。所以在进行到第四个epoch的时候,我就想把所有的训练参数全部print出来,看一下到底是哪一个训练参数出现了问题。使用的命令为:
if epoch ==3:
for name, param in self.model.named_parameters():
if param.requires_grad:
assert torch.isnan(param).sum()==0, print("{0}={1}".format(name, param))
(因为,对于实体的嵌入表示,在按照索引取值的时候,我增加了一步
node_embeds = self.embeddings[0].weight.data
right = node_embeds
在之前的实验过程中发现,这样做会是的node的嵌入表示参数的required_grad=False,不会对节点的嵌入参数进行更新,print输出时发现这个参数果然没有发生变化。)
第一次出现nan的参数为关系的嵌入表示(embeddings.1),然后是时间的嵌入表示和无时间关系的嵌入表示。
embeddings.1.weight=Parameter containing:
tensor([[ nan, nan, nan, ..., nan, nan, nan],
[-0.0846, -0.1179, -0.0586, ..., 0.1764, 0.4586, 0.2314],
[ nan, nan, nan, ..., nan, nan, nan],
...,
[ 0.3071, 0.2690, 0.5669, ..., 0.2193, -0.0346, -0.0254],
[ 0.3635, -0.2287, -0.0272, ..., -0.0766, -0.5287, 0.5063],
[ nan, nan, nan, ..., nan, nan, nan]],
device='cuda:1', requires_grad=T