先说解决结果,不使用list来保存多组参数,而使用nn.ModuleList保存参数
在写一个模型时发现第一个epoch的loss就出现了值为nan,而网上对于nan的出现多属于
(1)在较后的epoch存在参数消失或爆炸、
(2)除0
(3)不合理的激活函数等情况出现
而在我的源码中也对参数进行了xavier初始化,前向传播过程中未进行除法,仅使用了relu激活函数,并不符合以上的情况,因此对出现nan的情况进行排查,发现在第二个多层感知机时就出现了nan:
def forward(self, v, c):
# mask_v
input_v_mask = np.zeros_like(v) # 输入mask
input_v_mask[v != 0] = 1
input_v_mask = torch.from_numpy(input_v_mask)
# encoder_gtr_rbm
gtr_rbm_v = torch.matmul(v, self.weight_v)
time_condition = [torch.matmul(c[n], self.weight_c2) for n in range(self.n_condition)]
time_condition_sum = time_condition[0]
if self.n_condition>1:
for t in range(1, self.n_condition):
time_condition_sum+=time_condition[t]
# 第一个感知机,数据正常
output = F.relu(gtr_rbm_v+time_condition_sum+self.bias_h)
print('output',output)
# encoder_rbm
for i in range(self.n_layer_rbm):
# 第二个感知机,出现nan
print('output',output,'weight',self.rbm_weight_lis[i],'bias',self.rbm_bias_h_lis[i])
output = F.relu(torch.matmul(output, self.rbm_weight_lis[i])+self.rbm_bias_h_lis[i])
因此怀疑是参数初始化的问题,参数出现问题的地方我用了列表来对参数进行了保存,并在前向传播过程中使用了该参数(上面代码的rbm_weight_lis,rbm_bias_h_lis),其出现问题的初始化代码如下:
self.rbm_weight_lis=[]
self.rbm_bias_v_lis=[]
self.rbm_bias_h_lis = []
for i in range(self.n_layer_rbm):
self.rbm_weight_lis.append(nn.Parameter(torch.FloatTensor(self.n_visible_rbm[i],self.n_hidden_rbm[i])))
self.rbm_bias_v_lis.append(nn.Parameter(torch.FloatTensor(self.n_visible_rbm[i])))
self.rbm_bias_h_lis.append(nn.Parameter(torch.FloatTensor(self.n_hidden_rbm[i])))
通过查阅nn.ModuleList这一个函数时,有人提到用列表append参数进去会出现问题,因此对这一参数初始化进行了修改,由于这个列表中我的这个需要实现的功能基本上就是一个全连接层,因此直接使用了nn.Linear这个函数:
self.rbm_weight_lis = nn.ModuleList([nn.Linear(self.n_visible_rbm[i],self.n_hidden_rbm[i]) for i in range(self.n_layer_rbm)])
至此遇到的nan问题得到解决。