Pytorch:dtype不一致問題(expected dtype Double but got dtype Float)
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. 說明
在訓(xùn)練網(wǎng)絡(luò)的過程中由于類型的沖突導(dǎo)致這種錯(cuò)誤,主要是模型內(nèi)部參數(shù)和輸入類型不一致所導(dǎo)致的。主要有兩個(gè)部分需要注意到:1.自己定義的變量要設(shè)置為一種數(shù)據(jù)類型;2.網(wǎng)絡(luò)內(nèi)部的變量類型也要統(tǒng)一。
2. 解決辦法一
統(tǒng)一聲明變量的類型。
# 將接下來創(chuàng)建的變量類型均為Double torch.set_default_tensor_type(torch.DoubleTensor)
or
#將接下來創(chuàng)建的變量類型均為Float torch.set_default_tensor_type(torch.FloatTensor)
一定要注意要在變量創(chuàng)建之間聲明類型。
3. 解決辦法二
在訓(xùn)練過程中加入一下兩點(diǎn)即可:
# For your model net = net.double() # For your data net(input_x.double)
Pytorch:盲點(diǎn)
1. 用conda安裝pytorch-gpu時(shí)
用這個(gè)命令就夠了,網(wǎng)上其他人說的都不好使
conda install pytorch cuda92
注意得是清華源的
2. 比較兩個(gè)行向量或者列向量
以期求得布爾數(shù)組時(shí),必須要保證兩邊的數(shù)據(jù)類型一樣,并且返回的布爾數(shù)組類型和比較的兩個(gè)向量結(jié)構(gòu)保持一致。另外,所有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轉(zhuǎn)tensor,其中,ndarray必須是等長的
x = np.array([[1, 2, 3], [4, 5, 6]]) # 正確 # x = np.array([[1, 2, 3], [4, 5]]) # 錯(cuò)誤 print(torch.from_numpy(x))
4. unsqueeze (不改變原有數(shù)據(jù))
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接收兩個(gè)參數(shù) # 第一個(gè)是num_embeddings,它表示詞庫的大小,則所有詞的下標(biāo)從0 ~ num_embeddings-1 # 第二個(gè)是embedding_dim,表示詞嵌入維度 # 詞嵌入層有了上面這兩個(gè)必須有的參數(shù),就形成了類,這個(gè)類可以有輸入和輸出 # 輸入的數(shù)據(jù)結(jié)構(gòu)不限,但是數(shù)據(jù)結(jié)構(gòu)里面每個(gè)單元的元素必須指的是下標(biāo),即要對應(yīng)0 ~ num_embeddings-1 # 輸出的數(shù)據(jù)結(jié)構(gòu)和輸入一樣,只不過將下標(biāo)換成對應(yīng)的詞嵌入 # 最開始的時(shí)候詞嵌入的矩陣是隨機(jī)初始化的,但是作為嵌入層,會(huì)不斷的學(xué)習(xí)參數(shù),所以最后訓(xùn)練完成的參數(shù)一定是學(xué)習(xí)完成的 # embedding層還可以接受一個(gè)可選參數(shù)padding_idx,這個(gè)參數(shù)指定的維度,但凡輸入的時(shí)候有這個(gè)維度,輸出一律填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不修改原有值 # 只能擴(kuò)展維度是1的那個(gè)維度 # 另外,expand還能增加新的維度,不過新的維度必須在已知維度之前比如從2 * 3 到 5 * 2 * 3 a = torch.tensor([[1, 2, 3]]) print(a.size()) # torch.Size([1, 3]),第一維是1,所以只能擴(kuò)展第一維 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,只能擴(kuò)展第二維 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) # 同理,只能擴(kuò)展第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)) 會(huì)報(bào)錯(cuò),因?yàn)樾戮S度跑到原有維度之后了 print(a.expand(3, 2, -1)) ? a = torch.rand(2, 3) print(a.expand(5, 2, 3)) # 正確
8. repeat
# repeat # repeat不改變原有值 # repeat傳入的參數(shù)的個(gè)數(shù)等于原有值的維度個(gè)數(shù),表示將對應(yīng)維度的內(nèi)容重復(fù)多少次 ? a = torch.tensor([1, 2, 3]) # size = [3] print(a.repeat(2)) # 將第一個(gè)維度的重復(fù)兩次 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)) # 第一維重復(fù)兩次,第二維重復(fù)三次,就變成了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 這個(gè)函數(shù)接受一個(gè)由張量組成的元組或者列表
與cat的區(qū)別是,stack會(huì)先增加一維,然后再進(jìn)行拼接
10. 對于一維張量a,維度為m,a[None, :]的shape為1×m,a[:, None]的shape為m×1
11. 兩個(gè)不同維度的矩陣比較,利用了廣播機(jī)制
12. torch.nn.CrossEntropyLoss(),這個(gè)類比較復(fù)雜,我們慢點(diǎn)說。
首先,這是一個(gè)類,定義如下:
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)
可以看到這個(gè)類非常簡單。在構(gòu)造函數(shù)中,我們重點(diǎn)關(guān)注weight和reduction
weight
:表示每個(gè)類的權(quán)重,這個(gè)在樣本不平衡分類問題中很有用,它應(yīng)該是一個(gè)長度為C的一維張量,C為類別數(shù)。reduction
:用于控制最終的輸出結(jié)果,默認(rèn)為mean,如果是mean,返回的是一個(gè)數(shù),即shape為torch.tensor([]) ,如果是none,則返回的情況有兩種,一種是(N,),一種是(N, d_1, ..., d_K),至于是哪一種,得看我們輸入到forward函數(shù)中的input和target是哪種形狀的。
可以看到,forward函數(shù)直接調(diào)用F.cross_entropy這個(gè)函數(shù),這個(gè)函數(shù)中的weight和reduction我們已經(jīng)講過,不再贅述。我們重點(diǎn)將input和target應(yīng)該是什么形狀的。
這里分兩種情況。
第一種,input是二維,即(N, C),N代表batch_size,C代表類別,即對于每一個(gè)batch,都有一個(gè)一維長度為C的向量,通常這里的C表示的是對應(yīng)類別的得分。target表示標(biāo)簽,它應(yīng)該是(N,),表示每一個(gè)batch的正確標(biāo)簽是什么,內(nèi)容應(yīng)該在0~C-1之中。如果reduction取默認(rèn)值mean,則返回的是一個(gè)數(shù),這個(gè)數(shù)是每個(gè)batch的損失的平均。如果是none,則返回的是(N,),即代表每一個(gè)batch的損失,沒有進(jìn)行平均。
第二種,input的維度是(N, C, d_1, ... d_K),這里K>=1。N表示batch_size,C表示類別數(shù),d_1...d_K 可以看做一個(gè)整體,表示在某個(gè)批次,某個(gè)類別上,損失并不是一個(gè)數(shù)字,而是一個(gè)張量。按這種方式理解的話,第一種就可以理解為,在某個(gè)批次,某個(gè)類別上,損失是一個(gè)數(shù),而第二種不是一個(gè)數(shù),是一個(gè)張量,這個(gè)張量的形狀是(d_1, ..., d_K),這個(gè)張量的每一個(gè)位置都代表對應(yīng)位置的損失。拿NLP中seq2seq的損失函數(shù)為例,decoder的輸出應(yīng)是(batch_size, seq_len, vocab_size),label為(batch_size, seq_len),那么這里我們顯然應(yīng)該用第二種,因?yàn)樵谀硞€(gè)批次,某個(gè)類別上,我們的損失函數(shù)并不單單是一個(gè)數(shù),而是一個(gè)(seq_len,)的張量,對于長度為seq_len的每個(gè)單詞,每個(gè)位置都有一個(gè)損失,所以我們要用第二種。所以這里,我們需要將input的后兩維置換,即transpose(0, 1),使其變成(batch_size, vocab_size, seq_len)。對于第二種,target,也就是label的維度應(yīng)該是(N, d1, ..., d_K),表示對于每個(gè)批次,這個(gè)“損失張量”(這個(gè)名字我自己起的)的每個(gè)位置對應(yīng)的標(biāo)簽。因此,對于seq2seq來說,label的維度應(yīng)該是(N, seq_len)。對于第二種情況,如果reduction是mean,輸出還是一個(gè)數(shù),這個(gè)數(shù)表示所有批次,“損失張量”所有位置的損失的平均值。如果是none,輸出為(N, d1, ...d_K),表示每一個(gè)批次,“損失張量”每一個(gè)位置的損失。
下面的例子代表第一種情況。
13. torch中mask作為torch的下標(biāo),可以不必和torch一樣的shape
當(dāng)然,也可以直接用下表來進(jìn)行賦值
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],默認(rèn)代表第一axis的最后一維,即等價(jià)于a[-1,:,:,...,:]
16. torch.cat(XXX, dim = ?) 其中XXX可以是list,不一定非要tensor
17. contiguous()
亦即,對tensor進(jìn)行transpose時(shí),其實(shí)是淺拷貝,如果要深拷貝,就要在后面補(bǔ)上一個(gè)contiguous()
18. net是網(wǎng)絡(luò)模型的一個(gè)object,調(diào)用zero_grad函數(shù),表示將網(wǎng)絡(luò)內(nèi)部所有參數(shù)的梯度置0
19. torch.utils.data中的DataLoader和TensorDataset
先用TensorDataset對打包的文件進(jìn)行校對,在DataLoader中會(huì)指定batch_size,假設(shè)原本data和label各N個(gè),那么DataLoader會(huì)將其打亂后,每batch_size為一組,共N/batch_size個(gè)。
假設(shè)DataLoader返回的是iter,對iter進(jìn)行for遍歷的時(shí)候,假設(shè)每一輪取樣為batch,則batch的長度是2,batch為一個(gè)list,這個(gè)list里面有兩個(gè)元素,一個(gè)是data,一個(gè)是label,data和label的第一維大小都是batch_size。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python人工智能實(shí)戰(zhàn)之對話機(jī)器人的實(shí)現(xiàn)
本文將通過Python開發(fā)一個(gè)可以講笑話的機(jī)器人,可以自由定制功能,想講幾個(gè)笑話就講幾個(gè)笑話。文中的示例代碼講解詳細(xì),感興趣的可以動(dòng)手試一試2022-02-02淺談Django中view對數(shù)據(jù)庫的調(diào)用方法
今天小編就為大家分享一篇淺談Django中view對數(shù)據(jù)庫的調(diào)用方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07解決pytorch報(bào)錯(cuò):AssertionError: Invalid device id的問題
今天小編就為大家分享一篇解決pytorch報(bào)錯(cuò):AssertionError: Invalid device id的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01Python實(shí)現(xiàn)的matplotlib動(dòng)畫演示之細(xì)胞自動(dòng)機(jī)
這篇文章主要介紹了Python實(shí)現(xiàn)的matplotlib動(dòng)畫演示之細(xì)胞自動(dòng)機(jī),用python來模擬,首先嘗試表示Beacon,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04python環(huán)境路徑配置以及命令行運(yùn)行腳本
這篇文章主要為大家詳細(xì)介紹了python環(huán)境路徑配置以及命令行運(yùn)行腳本,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04可用于監(jiān)控 mysql Master Slave 狀態(tài)的python代碼
用于監(jiān)控MySQL Master Slave 狀態(tài)的python代碼,有需要的朋友可以參考下2013-02-02利用soaplib搭建webservice詳細(xì)步驟和實(shí)例代碼
這篇文章主要介紹了使用python soaplib搭建webservice詳細(xì)步驟和實(shí)例代碼,大家可以參考使用2013-11-11