PyTorch 編寫代碼遇到的問題及解決方案
PyTorch編寫代碼遇到的問題
錯誤提示:no module named xxx
xxx為自定義文件夾的名字
因為搜索不到,所以將當(dāng)前路徑加入到包的搜索目錄
解決方法:
import sys sys.path.append('..') #將上層目錄加入到搜索路徑中 sys.path.append('/home/xxx') # 絕對路徑 import os sys.path.append(os.getcwd()) # #將當(dāng)前工作路徑加入到搜索路徑中
還可以在當(dāng)前終端的命令行設(shè)置
export PYTHONPATH=$PYTHONPATH:./
錯誤提示:AttributeError: ‘NoneType' object has no attribute ‘shape' height, width, channel = img.shape
在Linux系統(tǒng)下img.shape報錯AttributeError: ‘NoneType' object has no attribute ‘shape'
img=cv2.imread(),讀取一張圖片時,img.shape是包含三個量的元組,分別是:
img.shape[0]:圖像的高度
img.shape[1]:圖像的寬度
img.shape[2]:圖像的通道數(shù)
解決方法:讀的文件出錯 或者查看文件路徑是否正確
錯誤提示 :TypeError: slice indices must be integers or None or have an index method
cropped_im = img[ny1 : ny2, nx1 : nx2, :]
解決方法:需要將ny1 : ny2, nx1 : nx2轉(zhuǎn)換成int類型
錯誤提示 :Input type (torch.cuda.DoubleTensor) and weight type (torch.cuda.FloatTensor) should be the same
以下三小段分別是Data type CPU tensor GPU tensor
32-bit floating point torch.FloatTensor torch.cuda.FloatTensor
64-bit floating point torch.DoubleTensor torch.cuda.DoubleTensor
出錯在類型轉(zhuǎn)換
np.float更改為np.float32
import torchvision.transforms as transforms import numpy as np transform = transforms.ToTensor() def convert_image_to_tensor(image): """convert an image to pytorch tensor image: numpy array , h * w * c image_tensor: pytorch.FloatTensor, c * h * w """ image = image.astype(np.float32) return transform(image)
錯誤提示:RuntimeError: zero-dimensional tensor (at position 0) cannot be concatenated
版本問題 舊式寫法
import torch x = torch.tensor(0.1) y = torch.tensor(0.2) z = torch.cat((x, y))
改成新式寫法
x = torch.tensor([0.1]) y = torch.tensor([0.2]) z = torch.cat((x, y)) print(z)
結(jié)果
tensor([0.1000, 0.2000])
錯誤提示:TypeError: ‘float' object is not subscriptable
多了下標(biāo) a = x.tolist()[0]
去除下標(biāo) a = x.tolist()
錯誤提示:argument ‘input' (position 1) must be Tensor, not list
需要將list轉(zhuǎn)換成tensor
假設(shè)a是list
torch.tensor(a)
GPU模型和CPU模型之間的轉(zhuǎn)換
假設(shè)原來保存的是GPU模型,要轉(zhuǎn)換為CPU模型
torch.save(model, os.path.join( "./complete.pth")) cpu_model = torch.load("./complete.pth", map_location=lambda storage, loc: storage) dummy_input = torch.randn(1, 3, 224, 224)
假設(shè)原來保存的是CPU模型,要轉(zhuǎn)換為GPU模型
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") torch.save(model, os.path.join( "./complete.pth")) gpu_model = torch.load("./complete.pth", map_location=lambda storage, loc: storage.cuda) dummy_input = torch.randn(1, 3, 224, 224) dummy_input = dummy_input.to(device)
錯誤提示 RuntimeError: Subtraction, the - operator, with a bool tensor is not supported. If you are trying to invert a mask, use the ~ or logical_not() operator instead.
原代碼
# Store only unsuppressed boxes for this class image_boxes.append(class_decoded_locs[1 - suppress]) image_labels.append(torch.LongTensor((1 - suppress).sum().item() * [c]).to(device)) image_scores.append(class_scores[1 - suppress])
更改為
image_boxes.append(class_decoded_locs[~suppress]) image_labels.append(torch.LongTensor((~ suppress).sum().item() * [c]).to(device)) image_scores.append(class_scores[~suppress])
錯誤提示 RuntimeError: Expected object of scalar type Byte but got scalar type Bool for argument #2 ‘other' in call to _th_max
原代碼
suppress = torch.zeros((n_above_min_score), dtype=torch.uint8).to(device)
更改為
suppress = torch.zeros((n_above_min_score), dtype=torch.bool).to(device)
UserWarning: volatile was removed and now has no effect. Use with torch.no_grad(): instead.
#之前舊版本 ... x = Variable(torch.randn(1), volatile=True) return x #新版 with torch.no_grad(): ... x = torch.randn(1) return x
錯誤提示
RuntimeError: Attempting to deserialize object on CUDA device 1 but torch.cuda.device_count() is 1. Please use torch.load with map_location to map your storages to an existing device.
或者是 RuntimeError: expected device cuda:0 but got device cuda:1
錯誤原因之一
使用了CUDA 1顯卡訓(xùn)練保存的模型文件,使用CUDA 0驗證
代碼中寫了
device = torch.device(“cuda” if torch.cuda.is_available() else “cpu”)
可以在命令行設(shè)置讓哪些GPU可見
export CUDA_VISIBLE_DEVICES=1 #GPU編號 export CUDA_VISIBLE_DEVICES=0,1,2,3#4張顯卡可見
也可以在代碼里改成
checkpoint = torch.load(checkpoint,map_location=‘cuda:0')
錯誤提示
raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8097): Max retries exceeded with url: /update (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f3111915e80>: Failed to establish a new connection: [Errno 111] Connection refused',))
Exception in user code:
解決方案
因為沒有啟動visdom可視化程序,所有報錯
在終端執(zhí)行命令 visdom之后就能看到如下信息
Checking for scripts. It's Alive! INFO:root:Application Started You can navigate to http://localhost:8097
nn.Module.cuda() 和 Tensor.cuda()
無論是對于模型還是數(shù)據(jù),cuda() 都能實現(xiàn)從CPU到GPU的內(nèi)存遷移,但是他們的作用效果有所不同。
Model:
model = model.cuda() model.cuda()
上面兩句能夠達(dá)到一樣的效果,即對model自身進(jìn)行的內(nèi)存遷移
Tensor:
model = Model() tensor = torch.zeros([2, 3, 10, 10]) model.cuda() tensor.cuda() tensor_cuda = tensor.cuda() model(tensor) # 會報錯 model(tensor_cuda) # 正常運(yùn)行
和 nn.Module 不同,調(diào)用 tensor.cuda 只是返回這個 tensor 對象在 GPU 內(nèi)存上的拷貝,而不會對自身進(jìn)行改變。因此必須對 tensor 進(jìn)行重新賦值,即 tensor = tensor.cuda()
PyTorch 0.4 計算累積損失的不同
以廣泛使用的模式 total_loss += loss.data[0] 為例。Python0.4.0 之前,loss 是一個封裝了 (1,) 張量的 Variable,但 Python0.4.0 的 loss 現(xiàn)在是一個零維的標(biāo)量。對標(biāo)量進(jìn)行 索引是沒有意義的(似乎會報 invalid index to scalar variable 的錯誤)。使用 loss.item() 可以從標(biāo)量中獲取 Python 數(shù)字。所以改為:
total_loss = total_loss + loss.item()
如果在累加損失時未將其轉(zhuǎn)換為 Python 數(shù)字,則可能出現(xiàn)程序內(nèi)存使用量增加的情況。這是因為上面表達(dá)式的右側(cè)原本是一個 Python 浮點(diǎn)數(shù),而它現(xiàn)在是一個零維張量。因此,總損失累加了張量和它們的梯度歷史,這可能會產(chǎn)生很大的 autograd 圖,耗費(fèi)內(nèi)存和計算資源。
自適應(yīng) CPU 和 GPU設(shè)備的 trick
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = Model().to(device) total_loss = 0 for input, target in train_loader: input, target = input.to(device), target.to(device) ... total_loss = total_loss + loss.item() with torch.no_grad(): for input, target in test_loader: ...
torch.Tensor.detach的使用
官方說明:Returns a new Tensor, detached from the current graph,The result will never require gradient
假設(shè)有模型 A 和模型 B,我們需要將 A 的輸出作為 B 的輸入,但訓(xùn)練時我們只訓(xùn)練模型 B. 那么可以這樣做:
input_B = output_A.detach
它可以使兩個計算圖的梯度傳遞斷開,從而實現(xiàn)我們所需的功能。
pytorch中l(wèi)oss函數(shù)的參數(shù)設(shè)置
以CrossEntropyLoss為例:
CrossEntropyLoss(self, weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean')
若 reduce = False,那么 size_average 參數(shù)失效,直接返回向量形式的 loss,即batch中每個元素對應(yīng)的loss.
若 reduce = True,那么 loss 返回的是標(biāo)量:
如果 size_average = True,返回 loss.mean.
如果 size_average = False,返回 loss.sum.
weight : 輸入一個1D的權(quán)值向量,為各個類別的loss加權(quán),如下公式所示:
ignore_index : 選擇要忽視的目標(biāo)值,使其對輸入梯度不作貢獻(xiàn)。如果 size_average = True,那么只計算不被忽視的目標(biāo)的loss的均值。
reduction : 可選的參數(shù)有:‘none' | ‘elementwise_mean' | ‘sum', 正如參數(shù)的字面意思。
多GPU的處理機(jī)制
使用多GPU時,應(yīng)該記住 PyTorch 的處理邏輯是:
在各個GPU上初始化模型。
前向傳播時,把batch分配到各個GPU上進(jìn)行計算。
得到的輸出在主GPU上進(jìn)行匯總,計算loss并反向傳播,更新主GPU上的權(quán)值。
把主GPU上的模型復(fù)制到其它GPU上。
訓(xùn)練時損失出現(xiàn)nan的問題
訓(xùn)練模型時出現(xiàn)損失為 nan 的情況
可能導(dǎo)致梯度出現(xiàn) nan 的三個原因:
梯度爆炸。也就是說梯度數(shù)值超出范圍變成 nan. 通??梢哉{(diào)小學(xué)習(xí)率、加 BN 層或者做梯度裁剪來試試看有沒有解決。
損失函數(shù)或者網(wǎng)絡(luò)設(shè)計。比方說,出現(xiàn)了除 0,或者出現(xiàn)一些邊界情況導(dǎo)致函數(shù)不可導(dǎo),比方說log(0)、sqrt(0).
臟數(shù)據(jù)。可以事先對輸入數(shù)據(jù)進(jìn)行判斷看看是否存在 nan.
補(bǔ)充一下nan數(shù)據(jù)的判斷方法:
注意!像 nan 或者 inf 這樣的數(shù)值不能使用 == 或者 is 來判斷!為了安全起見統(tǒng)一使用 math.isnan 或者 numpy.isnan 吧。
import numpy as np if np.any(np.isnan(input.cpu().numpy())): print("Input data has NaN!") if(np.isnan(loss.item())): print("Loss value is NaN!")
pytorch 內(nèi)存泄漏
torch.as_tensor(data, dtype=None,device=None)->Tensor : 為data生成tensor。
如果data已經(jīng)是tensor,且dtype和device與參數(shù)相同,則生成的tensor會和data共享內(nèi)存。如果data是ndarray,且dtype對應(yīng),devices為cpu,則同樣共享內(nèi)存。其他情況則不共享內(nèi)存。
import torch import numpy a = numpy.array([1, 2, 3]) t = torch.as_tensor(a)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python結(jié)合Selenium簡單實現(xiàn)Web自動化測試
這篇文章是入門級別的應(yīng)用Python + Selenium進(jìn)行自動化測試,包括環(huán)境搭建及簡單的實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09Pycharm 操作Django Model的簡單運(yùn)用方法
今天小編就為大家分享一篇Pycharm 操作Django Model的簡單運(yùn)用方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05Python數(shù)據(jù)處理的六種方式總結(jié)
在 Python 的數(shù)據(jù)處理方面經(jīng)常會用到一些比較常用的數(shù)據(jù)處理方式,比如pandas、numpy等等。今天介紹的這款 Python 數(shù)據(jù)處理的管道數(shù)據(jù)處理方式,通過鏈?zhǔn)胶瘮?shù)的方式可以輕松的完成對list列表數(shù)據(jù)的處理,希望對大家有所幫助2022-11-11python學(xué)生信息管理系統(tǒng)實現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了python學(xué)生信息管理系統(tǒng)的實現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-06-06Win10下python3.5和python2.7環(huán)境變量配置教程
這篇文章主要為大家詳細(xì)介紹了Win10下python3.5和python2.7環(huán)境變量配置教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09win8.1安裝Python 2.7版環(huán)境圖文詳解
在本篇內(nèi)容里小編給大家分享了關(guān)于win8.1安裝Python 2.7版環(huán)境的詳細(xì)步驟和方法,有興趣的朋友們跟著學(xué)習(xí)下。2019-07-07