原因:在将pytorch的longTensor转为numpy,并用于dict的key的时候,会出现这样的错误。其实程序输出已经是int了,但是还是会被认为是ndarray。
解决:在原来的基础上加上.item()
classId = support_y[i].long().cpu().detach().numpy().item()
原因:数据不是Tensor类型的而是np.array或其他类型的。
解决:
tensor = torch.LongTensor(data_x)
data_x = autograd.Variable(tensor)
tensor = torch.LongTensor(data_y)
data_y = autograd.Variable(tensor)
解决:loader中令num_workers=0
原因: 使用view时维度指定错误,LSTM(input,(h0,c0)) 指定batch_first=True后,input就是(batch_size,seq_len,input_size)否则为input(seq_len, batch, input_size)
解决:
lstm_out, self.hidden = self.lstm(
embeds.view(self.batch_size, 200, EMBEDDING_DIM), self.hidden)
原因:pytorch1.1.0
版本的random_split在torch.utils.data
里,而0.4.0版本的random_split在torch.utils.data.dataset
里。
解决:from torch.utils.data.dataset import random_split
。
原因:数据集问题。
解决:将准确率计算改为:
acc1 = (pred_cls1 == val_y1).cpu().sum().numpy() / pred_cls1.size()[0]
原因:因为使用了
if torch.cuda.device_count() > 1:
print("Let's use", torch.cuda.device_count(), "GPUs!")
model = nn.DataParallel(model)
model.to(device)
而tensor没有指定卡的ID。
解决:两种方式。
1)先定义一个device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
(这里面已经定义了device在卡0上“cuda:0”),然后将model = torch.nn.DataParallel(model,devices_ids=[0, 1, 2])
(假设有三张卡)。此后需要将tensor 也迁移到GPU上去。注意所有的tensor必须要在同一张GPU上面,即:tensor1 = tensor1.to(device), tensor2 = tensor2.to(device)
等等。注意:一定不能仅仅是tensor1.to(device)
而不赋值,这样只会创建副本。
2)直接用tensor.cuda()
的方法。即先model = torch.nn.DataParallel(model, device_ids=[0, 1, 2])
(假设有三块卡, 卡的ID 为0, 1, 2),然后tensor1 = tensor1.cuda(0), tensor2=tensor2.cuda(0)
等等。(我这里面把所有的tensor全放进ID 为 0 的卡里面,也可以将全部的tensor都放在ID 为1 的卡里面)
参考网址:学习Pytorch过程遇到的坑(持续更新中)
原因:nn.DataParallel(m)
这句返回的已经不是原始的m了,而是一个DataParallel
,原始的m保存在DataParallel
的module
变量里面。
解决: 在DataParallel
和to(device)
之后如果需要修改model
,则需要
if isinstance(model, nn.DataParallel):
model = model.module
原因:在分类训练中经常遇到这个问题,一般来说在网络中输出的种类数和label设置的种类数量不同的时候就会出现这个错误。Pytorch
有个要求,在使用CrossEntropyLoss
这个函数进行验证时label
必须是以0
开始的。
解决:
tags_ids = range(len(tags_set)) # 从0开始
tag2id = pd.Series(tags_ids, index=tags_set)
原因:原本是GPU
训练的模型要加载在CPU
上。
解决:model = torch.load(model_path, map_location='cpu')
同理,如果原本4
块GPU
训练的,改为一块,则model = torch.load(model_path, map_location='cuda:0');
如果是4块到两块:就把map_location
改为:map_location={'cuda:1': 'cuda:0'}
。
原因:加载的模型的word_embedding
层参数和当前model
输入的参数不匹配。
解决:word2id、tag2id
的长度要一致。
原因:使用了DataLoader加载数据,数据集中的训练实例数不能被batch_size整除,最后一个batch的大小不等于batch_size,而hidden_layer初始化的时候用固定的batch_size初始化:autograd.Variable(torch.zeros(self.num_layers * 2, self.batch_size, self.hidden_dim // 2))
解决:如果模型不能处理批量大小的在线更改,就应在torch.utils.data中设置drop_last=True,因此,在培训期间只处理整批数据。即testset_loader = DataLoader(test_db, batch_size=args.batch_size, shuffle=False, num_workers=1, pin_memory=True,drop_last=True)
原因:
1.学习率太高。学习率比较大的时候,参数可能over shoot
了,结果就是找不到极小值点; 减小学习率可以让参数朝着极值点前进
2.loss
函数有问题。
3.对于回归问题,可能出现了除0 的计算,加一个很小的余项可能可以解决。
4.数据本身,是否存在Nan
,可以用numpy.any(numpy.isnan(x))
检查一下input和target。
5.target本身应该是能够被loss函数计算的,比如sigmoid
激活函数的target
应该大于0,同样的需要检查数据集。
解决:减小学习速率或者增大batch_size
。
原因:网络中存在多个sub-network,有2个甚至2个以上的loss需要分别对网络参数进行更新,比如两个需要分别执行loss1.backward() loss2.backward()。两个loss可能会有共同的部分,所以在执行第一次loss1.backward()完成之后,Pytorch会自动释放保存着的计算图,所以执行第二次loss2.backward()的时候就会出现计算图丢失的情况。
解决:
loss.backward(retain_graph=True)
保留计算图,但这样很可能会出现内存溢出(CUDA out of memory)
的情况。因为Pytorch的机制是每次调用.backward()
都会free掉所有buffers,所以它提示,让retain_graph。然而当retain后,buffers就不会被free了,所以会OOM。参考网址:https://blog.csdn.net/Mundane_World/article/details/81038274.detach()
作为输入数据,这样就对当前图进行拆分,返回一个新的从当前图中分离的Variable
,返回的 Variable
retain_graph=True
则内存溢出,又找不到需要.detach()
的地方,最后发现是因为我的model每次训练的时候没有重新初始化隐藏层。需要在model.zero_grad()
之后model.hidden = model.init_hidden()
来清空 LSTM 的隐状态,将其从上个实例的历史中分离出来,避免受之前运行代码的干扰。如果不重新初始化,会有报错。