1.return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)RuntimeError: Expected tensor for argument #1 'indices' to have scalar type Long; but got torch.IntTensor instead (while checking arguments for embedding)
torch.nn.Embedding類要求該class的輸入input必須是LongTensor
1 embedding = nn.Embedding(10, 3, padding_idx=0) 2 input = torch.LongTensor([[0,2,0,5]]) 3 embedding(input) 4 #tensor([[[ 0.0000, 0.0000, 0.0000], 5 # [ 0.1535, -2.0309, 0.9315], 6 # [ 0.0000, 0.0000, 0.0000], 7 # [-0.1655, 0.9897, 0.0635]]])
2.關於安裝Spacy以及de和en模塊遇到的坑
https://www.pythonheidong.com/blog/article/233961/aff07bd143f34d50f1fa/
3.RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.LongTensor [4, 20]] is at version 21; expected version 20 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
loss.backward()報錯說某個變量在前向計算時是一個值,在求梯度時變成了另一個值(inplace 操作導致),使得pytorch在反向梯度求導時產生了錯誤,這個變量不會在報錯時指明,需要分析程序找出;
常見的解決方案可以把原地操作改成非原地操作(我沒有成功),或者切斷反向傳播;
把訓練過程中值會變化的變量加.data;
關於pytorch..detach() 和 .data用於切斷反向傳播,參考鏈接https://www.cnblogs.com/wanghui-garcia/p/10677071.html
4.在讀取其他文件夾下的.py文件時,報錯ModuleNotFoundError: No module named '文件夾'
假設有文件夾A和B,A中有文件a.py和aa.py,B中有文件b.py,(兩個文件夾中都要有__init__.py函數)
當a.py想要調用b.py中的函數XX,from B.b import XX(不在同一文件夾)
當a.py想要調用aa.py中的函數,from .aa import XX(在同一文件夾,要加.)
實際中的例子:
Tip:在程序最上面查看當前運行目錄print(os.getcwd())
5.巨坑!!!GPU下訓練函數在遍歷train_iterator時陷入死循環(而迭代器本身長度為5),但在CPU下能正常運行
問題出在使用torch.data.BucketIterator.splits來構建迭代器時沒有指定參數repeat=False
1 #創建iterator 2 train_iterator, test_iterator = data.BucketIterator.splits( 3 (train_data, test_data), 4 batch_size=BATCH_SIZE, 5 sort_within_batch=False, 6 repeat=False, 7 sort = False)
另外在本身文件和調用的文件中,不能重復占用不同的GPU,即下面的語句(GPU序號不同)不能同時出現在調用和被調用的文件開頭;
6.[:, None, None]
1 import torch 2 3 B = 16 4 print(torch.arange(B)[:, None, None].shape) #[16, 1, 1] 5 print(torch.arange(B)[None, :, None].shape) #[1, 16, 1]
7.模型的保存和載入
情況一:保存和載入網絡的結構
1 torch.save(net, "ney.pkl") 2 3 net1 = torch.load("net.pkl")
情況二:保存和載入網絡的參數
1 torch.save(net.state_dict(), "net_params.pkl") 2 3 net2.load_state_dict(torch.load("net_params.pkl"), strict=False)
8.linux環境下安裝pytorch(對應cuda9.0,學校服務器的08節點)
使用清華源,老是忘記,在此記錄一下
1 conda install pytorch==1.1.0 torchvision==0.3.0 cudatoolkit=9.0
9.計算模型參數量和FLOPs
1 #計算參數量,這里的參數量是指參數通過模型經過的參數量 2 inputs = (imgs, labels, fast) 3 flops, params = profile(net, inputs, verbose=False) 4 total_flops += flops 5 model_params_num += params 6 7 loss, logits = net(imgs, labels, fast)
Tip:inputs里面的參數個數和net要傳入的參數要一致;
如果只有一個imgs參數,inputs = (imgs, ),逗號不能少,需要傳入的是元組類型,不加逗號就相當於imgs
1 #真實的模型參數 2 num_params = (sum(p.numel() for p in model.parameters())/1000000.0) 3 logging.info('student model Total params: %.2fM' % num_params)
10.多標簽分類的衡量指標
下面以20分類為例,如果是最后一個維度是2,看成20個2分類,即shape=[8, 20, 2],可以直接根據二分類判別是否是當前該類,而不用先sigmoid再和0.5比較;
1 #多分類正確率 2 def cal_multi_to_single_acc(predict_y, true_y): #predict_y.shape=[8, 20], true_y.shape=[8, 20],類型都是numpy 3 predict_y = torch.from_numpy(predict_y) 4 predict_y = torch.sigmoid(predict_y) #先把值壓縮到0~1之間 5 preds = [] 6 for line in predict_y: 7 8 preds_line = [0 for i in range(predict_y.size(1))] 9 for i in range(len(line)): 10 prob = float(line[i]) 11 if prob > 0.5: 12 preds_line[i] = 1 13 else: 14 preds_line[i] = 0 15 preds.append(preds_line) #preds是列表類型 16 17 acc = 0 18 for y_test, y_pred in zip(true_y, preds): 19 if list(y_test) == y_pred: 20 acc += 1 21 print("acc", acc / len(true_y)) 22 preds = np.array(preds) 23 true_y = np.array(true_y) 24 25 print("Test Precision, Recall and F1-Score...") 26 print(classification_report(true_y, preds, digits=4))
11.多GPU運行