您好,登錄后才能下訂單哦!
這篇“Pytorch:dtype不一致問題如何解決”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Pytorch:dtype不一致問題如何解決”文章吧。
RuntimeError: Expected object of scalar type Double but got scalar type Float for argument #3 ‘mat2’ in call to _th_addmm_out
在訓練網絡的過程中由于類型的沖突導致這種錯誤,主要是模型內部參數和輸入類型不一致所導致的。主要有兩個部分需要注意到:1.自己定義的變量要設置為一種數據類型;2.網絡內部的變量類型也要統一。
統一聲明變量的類型。
# 將接下來創建的變量類型均為Double torch.set_default_tensor_type(torch.DoubleTensor)
or
#將接下來創建的變量類型均為Float torch.set_default_tensor_type(torch.FloatTensor)
一定要注意要在變量創建之間聲明類型。
在訓練過程中加入一下兩點即可:
# For your model net = net.double() # For your data net(input_x.double)
1. 用conda安裝pytorch-gpu時
用這個命令就夠了,網上其他人說的都不好使
conda install pytorch cuda92
注意得是清華源的
2. 比較兩個行向量或者列向量
以期求得布爾數組時,必須要保證兩邊的數據類型一樣,并且返回的布爾數組類型和比較的兩個向量結構保持一致。另外,所有torch.返回的東西,如果要取得里面的值,必須要加.item()
# !user/bin/python # -*- coding: UTF-8 -*- import torch a = torch.arange(16).view(4, 4) b = torch.argmax(a, dim = 1) print([round(x.item(), 5) for x in b]) z = torch.tensor([3, 1, 2, 5], dtype = torch.long) # 類型必須保持一致 z = z.view(-1, 1) b = b.view(-1, 1) print(b) print(z) print(b == z) # tensor([[ True], # [False], # [False], # [False]]) print(torch.sum(b == z)) # tensor(1)
3. numpy轉tensor,其中,ndarray必須是等長的
x = np.array([[1, 2, 3], [4, 5, 6]]) # 正確 # x = np.array([[1, 2, 3], [4, 5]]) # 錯誤 print(torch.from_numpy(x))
4. unsqueeze (不改變原有數據)
import torch import numpy as np x = torch.tensor([[1, 2], [3, 4]]) print(x) # tensor([[1, 2], # [3, 4]]) # 在第0維的地方插入一維 print(x.unsqueeze(0)) # tensor([[[1, 2], # [3, 4]]]) print(x.unsqueeze(0).shape) # torch.Size([1, 2, 2]) print(x.unsqueeze(1)) # tensor([[[1, 2]], # [[3, 4]]]) print(x.unsqueeze(1).shape) # torch.Size([2, 1, 2])
5. nn.embedding
# !user/bin/python # -*- coding: UTF-8 -*- import torch import torch.nn as nn import torch.nn.functional as F # 看看torch中的torch.nn.embedding # embedding接收兩個參數 # 第一個是num_embeddings,它表示詞庫的大小,則所有詞的下標從0 ~ num_embeddings-1 # 第二個是embedding_dim,表示詞嵌入維度 # 詞嵌入層有了上面這兩個必須有的參數,就形成了類,這個類可以有輸入和輸出 # 輸入的數據結構不限,但是數據結構里面每個單元的元素必須指的是下標,即要對應0 ~ num_embeddings-1 # 輸出的數據結構和輸入一樣,只不過將下標換成對應的詞嵌入 # 最開始的時候詞嵌入的矩陣是隨機初始化的,但是作為嵌入層,會不斷的學習參數,所以最后訓練完成的參數一定是學習完成的 # embedding層還可以接受一個可選參數padding_idx,這個參數指定的維度,但凡輸入的時候有這個維度,輸出一律填0 # 下面來看一下吧 embedding = nn.Embedding(10, 3) inputs = torch.tensor([[1, 2, 4, 5], [4, 3, 2, 9]]) print(embedding(inputs)) # tensor([[[ 0.3721, 0.3502, 0.8029], # [-0.2410, 0.0723, -0.6451], # [-0.4488, 1.4382, 0.1060], # [-0.1430, -0.8969, 0.7086]], # # [[-0.4488, 1.4382, 0.1060], # [ 1.3503, -0.0711, 1.5412], # [-0.2410, 0.0723, -0.6451], # [-0.3360, -0.7692, 2.2596]]], grad_fn=<EmbeddingBackward>)
6. eq
# !user/bin/python # -*- coding: UTF-8 -*- # eq import torch a = torch.tensor([1, 2, 2, 3]) b = torch.tensor((1, 3, 2, 3)) print(a.eq(b)) # tensor([ True, False, True, True]) print(a.eq(0)) # tensor([False, False, False, False]) print(a.eq(2)) # tensor([False, True, True, False])
7. expand
# expand # expand不修改原有值 # 只能擴展維度是1的那個維度 # 另外,expand還能增加新的維度,不過新的維度必須在已知維度之前比如從2 * 3 到 5 * 2 * 3 a = torch.tensor([[1, 2, 3]]) print(a.size()) # torch.Size([1, 3]),第一維是1,所以只能擴展第一維 print(a.expand(3, 3)) # tensor([[1, 2, 3], # [1, 2, 3], # [1, 2, 3]]) print(a) # tensor([[1, 2, 3]]) a = torch.tensor([[1], [2], [3]]) print(a.size()) # torch.Size([3, 1]),第二維是1,只能擴展第二維 print(a.expand(-1, 4)) # 第一維用-1代表第一維不變,還是3 # tensor([[1, 1, 1, 1], # [2, 2, 2, 2], # [3, 3, 3, 3]]) a = torch.randn(2, 1, 1, 4) # 同理,只能擴展第2和第3維 print(a.expand(-1, 2, 3, -1)) a = torch.tensor([1, 2, 3]) print(a.size()) # torch.Size([3]) print(a.expand(2, 3)) # tensor([[1, 2, 3], # [1, 2, 3]]) # print(a.expand(3, 2)) 會報錯,因為新維度跑到原有維度之后了 print(a.expand(3, 2, -1)) a = torch.rand(2, 3) print(a.expand(5, 2, 3)) # 正確
8. repeat
# repeat # repeat不改變原有值 # repeat傳入的參數的個數等于原有值的維度個數,表示將對應維度的內容重復多少次 a = torch.tensor([1, 2, 3]) # size = [3] print(a.repeat(2)) # 將第一個維度的重復兩次 tensor([1, 2, 3, 1, 2, 3]) print(a) # tensor([1, 2, 3]) a = torch.tensor([[1, 2, 3], [4, 5, 6]]) # 2 * 3 print(a.repeat(2, 3)) # 第一維重復兩次,第二維重復三次,就變成了4 * 9 # tensor([[1, 2, 3, 1, 2, 3, 1, 2, 3], # [4, 5, 6, 4, 5, 6, 4, 5, 6], # [1, 2, 3, 1, 2, 3, 1, 2, 3], # [4, 5, 6, 4, 5, 6, 4, 5, 6]])
9. torch.stack 這個函數接受一個由張量組成的元組或者列表
與cat的區別是,stack會先增加一維,然后再進行拼接
10. 對于一維張量a,維度為m,a[None, :]的shape為1×m,a[:, None]的shape為m×1
11. 兩個不同維度的矩陣比較,利用了廣播機制
12. torch.nn.CrossEntropyLoss(),這個類比較復雜,我們慢點說。
首先,這是一個類,定義如下:
class CrossEntropyLoss(_WeightedLoss): def __init__(self, weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean'): super(CrossEntropyLoss, self).__init__(weight, size_average, reduce, reduction) self.ignore_index = ignore_index def forward(self, input, target): return F.cross_entropy(input, target, weight=self.weight, ignore_index=self.ignore_index, reduction=self.reduction)
可以看到這個類非常簡單。在構造函數中,我們重點關注weight和reduction
weight
:表示每個類的權重,這個在樣本不平衡分類問題中很有用,它應該是一個長度為C的一維張量,C為類別數。
reduction
:用于控制最終的輸出結果,默認為mean,如果是mean,返回的是一個數,即shape為torch.tensor([]) ,如果是none,則返回的情況有兩種,一種是(N,),一種是(N, d_1, ..., d_K),至于是哪一種,得看我們輸入到forward函數中的input和target是哪種形狀的。
可以看到,forward函數直接調用F.cross_entropy這個函數,這個函數中的weight和reduction我們已經講過,不再贅述。我們重點將input和target應該是什么形狀的。
這里分兩種情況。
第一種,input是二維,即(N, C),N代表batch_size,C代表類別,即對于每一個batch,都有一個一維長度為C的向量,通常這里的C表示的是對應類別的得分。target表示標簽,它應該是(N,),表示每一個batch的正確標簽是什么,內容應該在0~C-1之中。如果reduction取默認值mean,則返回的是一個數,這個數是每個batch的損失的平均。如果是none,則返回的是(N,),即代表每一個batch的損失,沒有進行平均。
第二種,input的維度是(N, C, d_1, ... d_K),這里K>=1。N表示batch_size,C表示類別數,d_1...d_K 可以看做一個整體,表示在某個批次,某個類別上,損失并不是一個數字,而是一個張量。按這種方式理解的話,第一種就可以理解為,在某個批次,某個類別上,損失是一個數,而第二種不是一個數,是一個張量,這個張量的形狀是(d_1, ..., d_K),這個張量的每一個位置都代表對應位置的損失。拿NLP中seq2seq的損失函數為例,decoder的輸出應是(batch_size, seq_len, vocab_size),label為(batch_size, seq_len),那么這里我們顯然應該用第二種,因為在某個批次,某個類別上,我們的損失函數并不單單是一個數,而是一個(seq_len,)的張量,對于長度為seq_len的每個單詞,每個位置都有一個損失,所以我們要用第二種。所以這里,我們需要將input的后兩維置換,即transpose(0, 1),使其變成(batch_size, vocab_size, seq_len)。對于第二種,target,也就是label的維度應該是(N, d1, ..., d_K),表示對于每個批次,這個“損失張量”(這個名字我自己起的)的每個位置對應的標簽。因此,對于seq2seq來說,label的維度應該是(N, seq_len)。對于第二種情況,如果reduction是mean,輸出還是一個數,這個數表示所有批次,“損失張量”所有位置的損失的平均值。如果是none,輸出為(N, d1, ...d_K),表示每一個批次,“損失張量”每一個位置的損失。
下面的例子代表第一種情況。
13. torch中mask作為torch的下標,可以不必和torch一樣的shape
當然,也可以直接用下表來進行賦值
14. repeat in torch & numpy is very different.
look at the pic above, repeat in torch does not have a argument 'axis =', and it regard the whole tensor as one which can not be seperated.
Next, we will talk about repeat function in numpy. We would like to divide it into two part. The former is that the array is 1-D and the other is N-D
part 1:
if array is one-dimensional, there is no need to specify the 'axis' argument. It will seperate each number, and repeat them respectively.
part 2:
Here the shape of array c is (2, 2), so we can specify the 'axis'. The condition will be as follows:
(1) If axis is not specified, it will firstly flatten the array and continue repeating operation which is like part 1.
(2) If axis = 0, it will repeat along the first dimension.
(3) If axis = 1, it will repeat along the second dimension.
15. torch的多維張量a,如果a[-1],默認代表第一axis的最后一維,即等價于a[-1,:,:,...,:]
16. torch.cat(XXX, dim = ?) 其中XXX可以是list,不一定非要tensor
17. contiguous()
亦即,對tensor進行transpose時,其實是淺拷貝,如果要深拷貝,就要在后面補上一個contiguous()
18. net是網絡模型的一個object,調用zero_grad函數,表示將網絡內部所有參數的梯度置0
19. torch.utils.data中的DataLoader和TensorDataset
先用TensorDataset對打包的文件進行校對,在DataLoader中會指定batch_size,假設原本data和label各N個,那么DataLoader會將其打亂后,每batch_size為一組,共N/batch_size個。
假設DataLoader返回的是iter,對iter進行for遍歷的時候,假設每一輪取樣為batch,則batch的長度是2,batch為一個list,這個list里面有兩個元素,一個是data,一個是label,data和label的第一維大小都是batch_size。
以上就是關于“Pytorch:dtype不一致問題如何解決”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。