濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > 解決pytorch下只打印tensor的數(shù)值不打印出device等信息的問(wèn)題

解決pytorch下只打印tensor的數(shù)值不打印出device等信息的問(wèn)題

熱門(mén)標(biāo)簽:如何申請(qǐng)400電話費(fèi)用 武漢外呼系統(tǒng)平臺(tái) 富錦商家地圖標(biāo)注 沈陽(yáng)人工外呼系統(tǒng)價(jià)格 池州外呼調(diào)研線路 江西省地圖標(biāo)注 外呼系統(tǒng)哪些好辦 沈陽(yáng)外呼系統(tǒng)呼叫系統(tǒng) 沈陽(yáng)防封電銷(xiāo)卡品牌

torch.Tensor類(lèi)型的數(shù)據(jù)loss和acc打印時(shí)

如果寫(xiě)成以下寫(xiě)法

print('batch_loss: '+str(loss.data)+'batch acc: '+str(acc.data))

則不僅會(huì)打印出loss和acc的值,還會(huì)打印出device信息和 tensor字樣,如下:

如果僅想打印出數(shù)值,使得打印出的信息更加簡(jiǎn)潔

則要用以下寫(xiě)法

print('batch_loss: {:.3f} batch acc: {:.3f}'.format(loss.data, acc.data))

該寫(xiě)法還可控制輸出格式,結(jié)果類(lèi)似如下:

補(bǔ)充:關(guān)于pytorch中用plt顯示tensor的問(wèn)題(tensor轉(zhuǎn)numpy)

問(wèn)題

圖像的張量結(jié)構(gòu)為(C,H,W),而plt可以顯示的圖片格式要求(H,W,C),C為顏色通道數(shù),可以沒(méi)有。

所以問(wèn)題就是將Tensor(C,H,W)=> numpy(H,W,C)

解決辦法

def transimg(img):
    img = img / 2 + 0.5 # unnormalize
    npimg = img.numpy()
    npimg1 = np.transpose(npimg,(1,2,0)) # C*H*W => H*W*C
    return npimg1

補(bǔ)充:PyTorch代碼調(diào)試?yán)? 自動(dòng)print每行代碼的Tensor信息

本文介紹一個(gè)用于 PyTorch 代碼的實(shí)用工具 TorchSnooper。作者是TorchSnooper的作者,也是PyTorch開(kāi)發(fā)者之一。

GitHub 項(xiàng)目地址: https://github.com/zasdfgbnm/TorchSnooper

大家可能遇到這樣子的困擾:比如說(shuō)運(yùn)行自己編寫(xiě)的 PyTorch 代碼的時(shí)候,PyTorch 提示你說(shuō)數(shù)據(jù)類(lèi)型不匹配,需要一個(gè) double 的 tensor 但是你給的卻是 float;再或者就是需要一個(gè) CUDA tensor, 你給的卻是個(gè) CPU tensor。

比如下面這種:

RuntimeError: Expected object of scalar type Double but got scalar type Float

這種問(wèn)題調(diào)試起來(lái)很麻煩,因?yàn)槟悴恢缽哪睦镩_(kāi)始出問(wèn)題的。比如你可能在代碼的第三行用 torch.zeros 新建了一個(gè) CPU tensor, 然后這個(gè) tensor 進(jìn)行了若干運(yùn)算,全是在 CPU 上進(jìn)行的,一直沒(méi)有報(bào)錯(cuò),直到第十行需要跟你作為輸入傳進(jìn)來(lái)的 CUDA tensor 進(jìn)行運(yùn)算的時(shí)候,才報(bào)錯(cuò)。要調(diào)試這種錯(cuò)誤,有時(shí)候就不得不一行行地手寫(xiě) print 語(yǔ)句,非常麻煩。

再或者,你可能腦子里想象著將一個(gè) tensor 進(jìn)行什么樣子的操作,就會(huì)得到什么樣子的結(jié)果,但是 PyTorch 中途報(bào)錯(cuò)說(shuō) tensor 的形狀不匹配,或者壓根沒(méi)報(bào)錯(cuò)但是最終出來(lái)的形狀不是我們想要的。這個(gè)時(shí)候,我們往往也不知道是什么地方開(kāi)始跟我們「預(yù)期的發(fā)生偏離的」。我們有時(shí)候也得需要插入一大堆 print 語(yǔ)句才能找到原因。

TorchSnooper 就是一個(gè)設(shè)計(jì)了用來(lái)解決這個(gè)問(wèn)題的工具。TorchSnooper 的安裝非常簡(jiǎn)單,只需要執(zhí)行標(biāo)準(zhǔn)的 Python 包安裝指令就好:

pip install torchsnooper

安裝完了以后,只需要用 @torchsnooper.snoop() 裝飾一下要調(diào)試的函數(shù),這個(gè)函數(shù)在執(zhí)行的時(shí)候,就會(huì)自動(dòng) print 出來(lái)每一行的執(zhí)行結(jié)果的 tensor 的形狀、數(shù)據(jù)類(lèi)型、設(shè)備、是否需要梯度的信息。

安裝完了以后,下面就用兩個(gè)例子來(lái)說(shuō)明一下怎么使用。

例子1

比如說(shuō)我們寫(xiě)了一個(gè)非常簡(jiǎn)單的函數(shù):

def myfunc(mask, x):
    y = torch.zeros(6)
    y.masked_scatter_(mask, x)
    return y

我們是這樣子使用這個(gè)函數(shù)的:

mask = torch.tensor([0, 1, 0, 1, 1, 0], device='cuda')
source = torch.tensor([1.0, 2.0, 3.0], device='cuda')
y = myfunc(mask, source)

上面的代碼看起來(lái)似乎沒(méi)啥問(wèn)題,然而實(shí)際上跑起來(lái),卻報(bào)錯(cuò)了:

RuntimeError: Expected object of backend CPU but got backend CUDA for argument #2 'mask'

問(wèn)題在哪里呢?讓我們 snoop 一下!用 @torchsnooper.snoop() 裝飾一下 myfunc 函數(shù):

import torch
import torchsnooper
@torchsnooper.snoop()
def myfunc(mask, x):
    y = torch.zeros(6)
    y.masked_scatter_(mask, x)
    return y

mask = torch.tensor([0, 1, 0, 1, 1, 0], device='cuda')
source = torch.tensor([1.0, 2.0, 3.0], device='cuda')
y = myfunc(mask, source)

然后運(yùn)行我們的腳本,我們看到了這樣的輸出:

Starting var:.. mask = tensor(6,), int64, cuda:0>
Starting var:.. x = tensor(3,), float32, cuda:0>
21:41:42.941668 call 5 def myfunc(mask, x):
21:41:42.941834 line 6 y = torch.zeros(6)
New var:....... y = tensor(6,), float32, cpu>
21:41:42.943443 line 7 y.masked_scatter_(mask, x)
21:41:42.944404 exception 7 y.masked_scatter_(mask, x)

結(jié)合我們的錯(cuò)誤,我們主要去看輸出的每個(gè)變量的設(shè)備,找找最早從哪個(gè)變量開(kāi)始是在 CPU 上的。我們注意到這一行:

New var:....... y = tensor(6,), float32, cpu>

這一行直接告訴我們,我們創(chuàng)建了一個(gè)新變量 y, 并把一個(gè) CPU tensor 賦值給了這個(gè)變量。這一行對(duì)應(yīng)代碼中的 y = torch.zeros(6)。于是我們意識(shí)到,在使用 torch.zeros 的時(shí)候,如果不人為指定設(shè)備的話,默認(rèn)創(chuàng)建的 tensor 是在 CPU 上的。我們把這一行改成 y = torch.zeros(6, device='cuda'),這一行的問(wèn)題就修復(fù)了。

這一行的問(wèn)題雖然修復(fù)了,我們的問(wèn)題并沒(méi)有解決完整,再跑修改過(guò)的代碼還是報(bào)錯(cuò),但是這個(gè)時(shí)候錯(cuò)誤變成了:

RuntimeError: Expected object of scalar type Byte but got scalar type Long for argument #2 'mask'

好吧,這次錯(cuò)誤出在了數(shù)據(jù)類(lèi)型上。這次錯(cuò)誤報(bào)告比較有提示性,我們大概能知道是我們的 mask 的數(shù)據(jù)類(lèi)型錯(cuò)了。再看一遍 TorchSnooper 的輸出,我們注意到:

Starting var:.. mask = tensor(6,), int64, cuda:0>

果然,我們的 mask 的類(lèi)型是 int64, 而不應(yīng)該是應(yīng)有的 uint8。我們把 mask 的定義修改好:

mask = torch.tensor([0, 1, 0, 1, 1, 0], device='cuda', dtype=torch.uint8)

然后就可以運(yùn)行了。

例子 2

這次我們要構(gòu)建一個(gè)簡(jiǎn)單的線性模型:

model = torch.nn.Linear(2, 1)

我們想要擬合一個(gè)平面 y = x1 + 2 * x2 + 3,于是我們創(chuàng)建了這樣一個(gè)數(shù)據(jù)集:

x = torch.tensor([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]])
y = torch.tensor([3.0, 5.0, 4.0, 6.0])

我們使用最普通的 SGD 優(yōu)化器來(lái)進(jìn)行優(yōu)化,完整的代碼如下:

import torch
model = torch.nn.Linear(2, 1)
x = torch.tensor([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]])
y = torch.tensor([3.0, 5.0, 4.0, 6.0])

optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
for _ in range(10):
    optimizer.zero_grad()
    pred = model(x)
    squared_diff = (y - pred) ** 2
    loss = squared_diff.mean()
    print(loss.item())
    loss.backward()
    optimizer.step()

然而運(yùn)行的過(guò)程我們發(fā)現(xiàn),loss 降到 1.5 左右就不再降了。這是很不正常的,因?yàn)槲覀儤?gòu)建的數(shù)據(jù)都是無(wú)誤差落在要擬合的平面上的,loss 應(yīng)該降到 0 才算正常。

乍看上去,不知道問(wèn)題在哪里。抱著試試看的想法,我們來(lái) snoop 一下子。這個(gè)例子中,我們沒(méi)有自定義函數(shù),但是我們可以使用 with 語(yǔ)句來(lái)激活 TorchSnooper。把訓(xùn)練的那個(gè)循環(huán)裝進(jìn) with 語(yǔ)句中去,代碼就變成了:

import torch
import torchsnooper
model = torch.nn.Linear(2, 1)
x = torch.tensor([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]])
y = torch.tensor([3.0, 5.0, 4.0, 6.0])
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)

with torchsnooper.snoop():
    for _ in range(10):
        optimizer.zero_grad()
        pred = model(x)
        squared_diff = (y - pred) ** 2
        loss = squared_diff.mean()
        print(loss.item())
        loss.backward()
        optimizer.step()

運(yùn)行程序,我們看到了一長(zhǎng)串的輸出,一點(diǎn)一點(diǎn)瀏覽,我們注意到

New var:....... model = Linear(in_features=2, out_features=1, bias=True)
New var:....... x = tensor(4, 2), float32, cpu>
New var:....... y = tensor(4,), float32, cpu>
New var:....... optimizer = SGD (Parameter Group 0 dampening: 0 lr: 0....omentum: 0 nesterov: False weight_decay: 0)
02:38:02.016826 line 12 for _ in range(10):
New var:....... _ = 0
02:38:02.017025 line 13 optimizer.zero_grad()
02:38:02.017156 line 14 pred = model(x)
New var:....... pred = tensor(4, 1), float32, cpu, grad>
02:38:02.018100 line 15 squared_diff = (y - pred) ** 2
New var:....... squared_diff = tensor(4, 4), float32, cpu, grad>
02:38:02.018397 line 16 loss = squared_diff.mean()
New var:....... loss = tensor(), float32, cpu, grad>
02:38:02.018674 line 17 print(loss.item())
02:38:02.018852 line 18 loss.backward()
26.979290008544922
02:38:02.057349 line 19 optimizer.step()

仔細(xì)觀察這里面各個(gè) tensor 的形狀,我們不難發(fā)現(xiàn),y 的形狀是 (4,),而 pred 的形狀卻是 (4, 1),他們倆相減,由于廣播的存在,我們得到的 squared_diff 的形狀就變成了 (4, 4)。

這自然不是我們想要的結(jié)果。這個(gè)問(wèn)題修復(fù)起來(lái)也很簡(jiǎn)單,把 pred 的定義改成 pred = model(x).squeeze() 即可?,F(xiàn)在再看修改后的代碼的 TorchSnooper 的輸出:

New var:....... model = Linear(in_features=2, out_features=1, bias=True)
New var:....... x = tensor(4, 2), float32, cpu>
New var:....... y = tensor(4,), float32, cpu>
New var:....... optimizer = SGD (Parameter Group 0 dampening: 0 lr: 0....omentum: 0 nesterov: False weight_decay: 0)
02:46:23.545042 line 12 for _ in range(10):
New var:....... _ = 0
02:46:23.545285 line 13 optimizer.zero_grad()
02:46:23.545421 line 14 pred = model(x).squeeze()
New var:....... pred = tensor(4,), float32, cpu, grad>
02:46:23.546362 line 15 squared_diff = (y - pred) ** 2
New var:....... squared_diff = tensor(4,), float32, cpu, grad>
02:46:23.546645 line 16 loss = squared_diff.mean()
New var:....... loss = tensor(), float32, cpu, grad>
02:46:23.546939 line 17 print(loss.item())
02:46:23.547133 line 18 loss.backward()
02:46:23.591090 line 19 optimizer.step()

現(xiàn)在這個(gè)結(jié)果看起來(lái)就正常了。并且經(jīng)過(guò)測(cè)試,loss 現(xiàn)在已經(jīng)可以降到很接近 0 了。大功告成。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

您可能感興趣的文章:
  • Pytorch自定義Dataset和DataLoader去除不存在和空數(shù)據(jù)的操作
  • pytorch Dataset,DataLoader產(chǎn)生自定義的訓(xùn)練數(shù)據(jù)案例
  • PyTorch實(shí)現(xiàn)重寫(xiě)/改寫(xiě)Dataset并載入Dataloader
  • 一文弄懂Pytorch的DataLoader, DataSet, Sampler之間的關(guān)系
  • PyTorch 解決Dataset和Dataloader遇到的問(wèn)題
  • PyTorch 如何自動(dòng)計(jì)算梯度
  • pytorch中F.avg_pool1d()和F.avg_pool2d()的使用操作
  • 我對(duì)PyTorch dataloader里的shuffle=True的理解
  • pytorch 帶batch的tensor類(lèi)型圖像顯示操作
  • Pytorch 如何查看、釋放已關(guān)閉程序占用的GPU資源
  • pytorch中的squeeze函數(shù)、cat函數(shù)使用
  • Pytorch數(shù)據(jù)讀取之Dataset和DataLoader知識(shí)總結(jié)

標(biāo)簽:黑龍江 呂梁 銅川 阿里 潛江 常德 通遼 株洲

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《解決pytorch下只打印tensor的數(shù)值不打印出device等信息的問(wèn)題》,本文關(guān)鍵詞  解決,pytorch,下,只,打印,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《解決pytorch下只打印tensor的數(shù)值不打印出device等信息的問(wèn)題》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于解決pytorch下只打印tensor的數(shù)值不打印出device等信息的問(wèn)題的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    贡觉县| 克什克腾旗| 龙里县| 江安县| 琼海市| 双桥区| 绥德县| 安岳县| 皋兰县| 静安区| 景谷| 都匀市| 呼玛县| 乌海市| 吴堡县| 边坝县| 德安县| 汶川县| 巩留县| 卢氏县| 贵南县| 淄博市| 诸暨市| 永川市| 江油市| 简阳市| 宁明县| 甘谷县| 裕民县| 肃宁县| 英超| 丰县| 错那县| 友谊县| 开鲁县| 武鸣县| 公主岭市| 夏河县| 雷州市| 泰兴市| 高陵县|