PyTorch 有哪些坑/bug?
轉 PyTorch 的人越來越多了,不過 PyTorch 現在還不夠完善吧~
有哪些已知的坑呢?
分享一下我最近的踩坑經歷吧
這幾天在實現一個語義分割的loss
該loss考慮了邊緣,結果一致性等因素 如圖
由於公式較為複雜, 決定用風格和numpy相似的pytorch來實現
再由於torch是動態圖 而且 Python的for循環很慢, 所以打算全用Tensor操作。
想著應該和numpy差不多 難度中等 加上熟悉API的時間 一天足夠了
開工前 準備了一組(image, ground truth, 及假裝是分割網路結果的概率矩陣prob) 作為測試用例, 然後 正式開工!
寫著寫著 發現處理後的圖片根本不對,可視化一下.發現 ground truth轉化成`FloatTensor`後 就成了這個鬼樣子
查明後 原因是: 對`torch.FloatTensor`傳一個bool的numpy array , 即`torch.FloatTensor(Bool_Ndarray)` 就會成為上面這樣的亂碼
得先轉化為float32 即 `torch.FloatTensor(np.float32(labels))`
繼續寫 咦 torch不支持[::-1]和flip?那自己寫一個flip
又繼續寫, 全Tensor操作, 遇到複雜公式, 就意味著超多維度的select, index, 緯度變換,緯度匹配 ,若出了bug 分析起來特別麻煩
比如:
otherSideEdgeLossMap = -th.log(((probnb*gtind).sum(-3)*gtdf).sum(-3)/gtdf.sum(-3))
這麼黑燈瞎火地寫下去,調試又複雜又慢。
工欲善其事, 必先利其器
於是 我便先去改之前只支持numpy可視化的工具代碼 yllab ,增加其對torch的支持。
配合`Ipython@Spyder` 調試效率提高不少 比`print xx.shape,xx.mean()` 不知高到哪裡去了
最後, loss總算寫出來了, 而且可視化出來的 loss map 符合預想效果,還很好看!
最後一到工序 將概率矩陣prob變成Variable 測試一下反向傳播,我天真得以為 工作馬上就要被完成了
改成Variable(prob)後, loss.backward()一下, 啥?Error?Variable 竟然不能和 Tensor 運算 ! 不用記錄grad的Variable和 Tensor 有啥區別? 無語, 那全改為Variable 吧
嚓, Tensor和Variable部分api竟然不一樣 比如(`.type`). 行, 為了兼容性 函數都加上判斷是否為Variable, 並轉化為Variable.data
繼續吐槽一下 torch的類型系統 `Tensor/Variable *
8個數據類型` * `cuda/cpu` 共 `2*8*2=32` 類啊!! 而且 8個數據類型不支持類型自動轉換,所以 這32個類型的數據 都是兩兩互斥
不同類型間 操作前都得轉化, 可怕的是轉換操作還有許多像上文提到的那種坑!
改好代碼, 反向傳播通了 趕忙可視化一下 prob.grad
毛線!! 全是白的 分析一下 grad 中 99.97%的是nan, 人家 loss 都好人一個 你梯度怎麼就成了nan! 數學上不成立啊
遂開始了漫長的DEBUG之路, 終於 在不斷地拆開loss
分別 Backpropagation 後 將兇手精準定位了導致nan的loss
進一步分析 果然是pyTroch的BUG 整理好BUG後 就提交到了pytorch 的 GitHub上了
x.grad should be 0 but get NaN after x/0 · Issue #4132 · pytorch/pytorch
BUG如下
Reproduction BUG code
x = Variable(torch.FloatTensor([1.,1]), requires_grad=True)
div = Variable(torch.FloatTensor([0.,1]))
y = x/div # =&> y is [inf, 1]
mask = (div!=0) # =&> mask is [0, 1]
loss = y[mask]
loss.backward()
print(x.grad) # grad is [nan, 1], but expected [0, 1]
由於被`mask`阻擋, `x[0]`根本就沒在計算圖中 所以`x[0]`梯度應該為0 卻返回了`nan`
我還給出了BUG的解決方案:
Your code should"t generat any inf in forward, which often produce by torch.log(0) and x/[0, ]
That means 0 should be filtered before do torch.log(x) and x/div
為避免這個BUG 代碼變得更複雜了
variables
└─ /: 4
├── gtind: torch.Size([1, 2, 300, 400]) torch.cuda.FloatTensor
├── edge: torch.Size([1, 300, 400]) torch.cuda.ByteTensor
├── probnb: torch.Size([1, 8, 2, 300, 400]) torch.cuda.FloatTensor
└── gtdf: torch.Size([1, 8, 300, 400]) torch.cuda.FloatTensor
th = torch
tots = lambda x:x.data
code(before)
otherSideEdgeLossMap = -th.log(((probnb*gtind).sum(-3)*gtdf).sum(-3)/gtdf.sum(-3))
otherSideEdgeLossMap[~tots(edge)] = 0
code(after)
numerator = ((probnb*gtind).sum(-3)*gtdf).sum(-3)
numerator[tots(edge)] /= gtdf.sum(-3)[tots(edge)]
numerator[tots(edge)] = -th.log(numerator[tots(edge)])
otherSideEdgeLossMap = (numerator)
otherSideEdgeLossMap[~tots(edge)] = 0
最後 把代碼適配成多batch版本加上分割網路 順利跑通了 。 回想著一路下來 還好用的是動態圖的pyTorch, 調試靈活 可視化方便 若是靜態圖 恐怕會調試得吐血,曾經就為了提取一個mxnet的featrue 麻煩得要死。
不過 換成靜態圖的話 可能就不會顧著效率,用那麼多矩陣操作了,直接for循環定義網路結構 更簡單直接 。
寫於 2017.12
torch version : 0.3
誒。瀉藥。
1 torch和numpy的function名字不太一樣:
我反正numpy也用不太來。(據說會有torch.np,得等第二個改完)
2 要寫一個對於Variable和Tensor都通用的function時:一般的加減乘除還可以,最蛋疼就是新建tensor。
假設,我要輸出一個和輸入一樣類型的全零的tensor:
如果是tensor:
tensor.new(tensor.size()).zero_()
如果是Variable,得是:
Variable(tensor.new(tensor.size()).zero_())
(這個現在正在改,可能下個版本就有了吧。就是Variable Tensor完全一樣用法,Tensor只是一個 requires_grad為False的Variable)
3 cuda和cpu自動轉換
沒有一個context manager能夠說這下面默認都是cpu或者都是cuda。
麻煩的在於,如果要定義一個新的tensor,必須得input.data.new而不能torch.Tensor(xxxx)。
嗯。以上的問題gluon好像都沒有(刷個好感度)。(然而我還是用pytorch)
補充:
backward報錯沒有operator定位。(雖然我也不知道為什麼能forward不能backward,照理說不應該)
忘了zero_grad各種nan(血與淚的教訓)
Tensor和Variable的問題
為了對齊類型經常要Variable(tensor)或者variable.data……然而每個變數到底是Tensor還是Variable並不是很容易推斷,只能寫完跑一遍再慢慢改。
還有就是argmax.data.cpu().numpy().transpose().astype(int)[0],當然也可以寫成out.cpu().data.numpy().squeeze(axis=0).tolist(),並沒有什麼區別……
再補充一個:pytorch沒有提供Flatten()這個module,同樣也不支持shape的自動推斷。沒有Flatten這個作者沒有給出具體原因,論壇里討論過最後決定不加入這個Module。不支持shape自動推斷是因為Pytorch的分散式是一開始就要在多進程當中分配好Tensor,所以不能在第一遍forward的時候再推斷shape
總體來說Pytorch設計的非常優雅,大部分問題應該都是設計取捨。顯式的.cpu()和.cuda()能讓用戶意識到顯卡和內存之間的拷貝成本。Gluon在設計的時候也應該借鑒了很多
- 做CPU計算時,0.12版本速度遠高於最新的0.2,https://github.com/pytorch/pytorch/issues/2518
- 還有就是用set_num_threads設線程的時候要小心了,pytorch不一定聽你的,最好設環境變數,而且兩個最好都設:MKL_NUM_THREADS, OMP_NUM_THREADS pytorch not respecting torch.set_num_threads · Issue #975 · pytorch/pytorch
以下坑或 Bug 以 0.3 版本為準,其他人已提出且我贊同的答案不再贅述。
下一個版本得到修正的坑或 bug 會被歸檔,早先已歸檔的則會被刪除。所以要趁此填上項目里的被動坑。
DataLoader 有 ulimit 上限
其實我不清楚這算不算官方的鍋,好像有人批評 DataLoader 沒有釋放好 file descripter: DataLoader causing `RuntimeError: received 0 items of ancdata` · Issue #973 · pytorch/pytorch 某簡易解決方案也在其 issue 樓下給出了。
Advanced Indexing 可能不完善
我曾想取值 a[b, :1]
其中 a
是 Tensor, b
是 LongTensor, 結果報錯: TypeError: Performing basic indexing on a tensor and encountered an error indexing dim 0 with an object of type torch.LongTensor. The only supported types are integers, slices, numpy scalars, or if indexing with a torch.LongTensor or torch.ByteTensor only a single Tensor may be passed. 害得我改成 a[b, :][:, :1]
。
查了下,有很多類似的報告:Add documentation note about currently supported advanced indexing functionality · Issue #2423 · pytorch/pytorch feature 本身似乎也沒徹底完工:Feature Request: Advanced Indexing · Issue #1080 · pytorch/pytorch
Module.parameters() 返回生成器
於是沒法使用多次,官方拒絕修正,參見:`parameters()` should be a list, not an iterator · Issue #2954 · pytorch/pytorch
動態分配的內存很不確定
今天跑腳本,執行完 train 輪到執行 test 時,函數體幾乎一模一樣,用同一個模型,batchsize 也一樣,理論上由於 net.eval() 內存(y &> 0).sum() 之類的運算有可能溢出。內存佔用會更少,但會報內存不夠用的錯誤,不知道這函數跳轉之間到底發生了什麼。害得我只能設置 test 的 batchsize 為 device_id 的數量,同時也沒法用 cudnn.benchmarks 優化了。
PyTorch 沒有上傳到 PyPI
害得大家沒法一鍵 pip 安裝,只能跑去官網扒 URL 下。
然而真正的原因竟然是……rebuild pip wheels with manylinux · Issue #566 · pytorch/pytorch!
torch.cat 不支持直接把 list of int/float 轉變成 LongTensor/Tensor
這和 numpy.concatenate 不一樣。torch.stack 估計也不能。
nonzero 和 Numpy 的同名函數很不一樣
核心開發者之一也想改成後者了:nonzero doesn"t squeeze dimension · Issue #1834 · pytorch/pytorch
Tensor/Variable 的 cuda() 不是 in-place, Module 則反
這不一致的,好在目前也可以把後者賦值給自我一遍。
沒有官方 benchmarks 證實 "Tensors and Dynamic neural networks in Python with strong GPU acceleration." 的主張
這主張就是 PyTorch 官網的第一句話,於是我在論壇提出問題:Do you encourage user to use torch.Tensor instead of Numpy? 沒有官方答覆,於是存疑,用戶得自己親自寫 benchmarks 來解決。
大概由於用戶爆出 PyTorch 0.2 相對於 0.1.9 有嚴重的 CPU 性能下降 bug, 官方終於開始寫 pytorch/benchmark 了。
不支持 negative slice
對 Tensor 取 [::-1] 會報錯:slice step has to be greater than 0
不支持 Poly Scheluer
Poly Scheluer 是 Deeplab 提出的重要語義分割訓練法,我提 feature issue, 一個月過去了沒回應:Add the new lr_scheduler which called poly · Issue #2854 · pytorch/pytorch 真不知道 FAIR 在忙啥。
Tensor 能用的函數,Variable 不一定能用
參見:Implement remaining Variable functions · Issue #440 · pytorch/pytorch 在這個徹底施工完前,你拿不準哪個函數 Variable 能用,踩中坑就要轉成 data 用函數再轉成 Variable,是 cuda 變數時就更麻煩。
torchvision 用 PIL 而不是 scikit-image 圖像處理
於是就要額外花時間記憶 PIL 的 Image 類型以及其方法,沒法像 Numpy 用戶能直接無縫使用 scikit-image.
不完全或不一致的 torch.nn.functional 和 torch.nn.Loss
torch.nn.Softmax 只能處理 2D Tensor, torch.nn.functional.softmax 卻能處理 1D, 2D, 3D, 4D Tensor,後者的文檔也沒說它能處理什麼 Tensor, 從哪個維上 softmax. 還有好多 functional 都沒文檔。從我自己的測試來看,F.softmax 處理 2D 時 axis 為 1,處理 3D 時 axis 為 0,處理 4D 時 axis 為 1. F.cross_entroy 文檔指定了 Input 為 2D Tensor,但我傳 3D Tensor 則報錯:ValueError: Expected 2 or 4 dimensions (got 3).
目前同時實現了 NLLLoss, NLLLoss2d, CrossEntropyLoss, 唯獨缺了 CrossEntropyLoss2d. NLLLoss 接收的輸入得是 2D Tensor, NLLLoss2d 則接收 4D Tensor. 理論不紮實的新手容易被這名字繞暈。雖然官方似乎打算 deprecate NLLLoss2d, 使 NLLLoss2d 和 CrossEntropyLoss 能處理 2D, 4D 輸入,雖然半年過去了還沒弄好:Add CrossEntropyLoss2d by desimone · Pull Request #687 · pytorch/pytorch
參見:Add CrossEntropyLoss2d · Issue #551 · pytorch/pytorch
from_numpy() 不支持把 numpy 里的 int8 ndarray 轉換成 CharTensor
參見:Support int16 numpy conversions · Issue #891 · pytorch/pytorch
optimizer 裡面沒有 lr 作為 attribute
參見:Expose optimizer options as attributes when there"s a single param group · Issue #1736 · pytorch/pytorch
torch.Tensor 某軸的長度為零時,表現不怎麼符合直覺
既然 a 沒有 dimension, 那麼 c 應該也沒有才對;反之,即當 c 為刻意只保留非零值 dimension 的 Tensor, 說明值為零的 dimension 沒有意義,那麼 a 就無法被正常賦於只有零值 dimension 的 Tensor,即會拋異常。
既然 a 沒有 dimension, 那麼取 b[a] 應該返回沒有 dimension 的 Tensor.
不光無法取 b[a], 也不能直接對沒有 dimension 的 Tensor 進行運算以得到沒有 dimension 的 Tensor. 即害得我把某代碼寫成這樣子:
while tmp_order.numel() &> 0:
...清楚
indexes = (over &<= threshold).nonzero().squeeze()
if indexes.numel() == 0:
break
else:
tmp_order = tmp_order[indexes + 1]
如果能運算,代碼能更優雅:
while tmp_order.numel() &> 0:
...
indexes = (over &<= threshold).nonzero().squeeze() + 1
tmp_order = tmp_order[indexes]
後來果然在 PyTorch Issues 找到了類似的看法:
zero-dimensional numpy arrays should raise exception on from_numpy · Issue #2055 · pytorch/pytorch
unexpected behavior when resize shape include 0s. · Issue #2806 · pytorch/pytorch
官方也承認了 PyTorch 的 0 dimensional tensor 有很大的缺陷,甚至提出了可能要大改 API, 在高度貫徹 numpy-like API 的同時順便解決 0 dimensional tensor 問題,並且淘汰 Scalar: introduce torch.Scalar to represent scalars in autograd · Issue #1433 · pytorch/pytorch 不過估計要解決這問題得等很久了……
PyTorch 0.3 版本已解決的舊 bug:
(y &> 0).sum() 之類的運算有可能溢出。
因為 (y &>0) 一般返回 ByteTensor, 哪怕 y 原本是 LongTensor. 畢竟布爾值用 ByteTensor 就夠了,但這意味著 sum() 也返回 ByteTensor. 於是當 y 里大於 0 的元素多於 128 (或 256)時,就溢出了。坑死我了!
可以把 Tensor 傳進一些 Module 或 F
參見:Is is amazing that I can pass a Tensor to nn.AvgPool1d().forward() 返回值類型還神奇地變成 Variable 了。
TypeError: torch.sort received an invalid combination of arguments - got (torch.FloatTensor, descending=bool)
參見:TypeError: torch.sort received an invalid combination of arguments - got (torch.FloatTensor, descending=bool) · Issue #3497 · pytorch/pytorch
torchvision.datasets 的 transform, target_tramsform 不好用
不能同時 transform data 和 target, transform 順序也被定死。
好在 torchvision 改進了 transforms, 大概下一個版本會解決,參見:Proposal for extending transforms · Issue #230 · pytorch/vision
Variable和Tensor不能混合操作……
1.variable, tensor, numpy和cpu/gpu之間的轉換:這個在訓練rl的時候尤其煩。拿openai gym做個例子:
action = net(Variable(torch.from_numpy(obs[np.newaxis])).cuda()action = action.data.cpu().numpy()[0]obs, reward, done, _ = env.step(action)所以前兩天寫了個gym env wrapper來自動轉換。跟tensorflow相比,由於tf是直接定義好圖,輸出輸入直接是numpy,不需要再轉換。
2. contiguous:view只能用在contiguous的variable上。如果在view之前用了transpose,需要叫contiguous來返回一個contiguous copy。
先想這麼多,想到了再來答。不過總的來說pytorch用起來還是比tf舒服多了。- 不熟悉計算圖的運作原理可能埋雷
loss_total = 0
for ....
loss = loss_function(input,target)
loss_total += loss # 正確做法是 loss_total += (loss.data.cpu())
loss.backward()
print(loss_total/step)
這個一言難盡,慢慢學吧, 任何一個框架, 不學好計算圖都會踩到各種奇怪的坑
- Python2 multiprocessing 殭屍進程
如果你使用Python 2.7的話,程序不正常退出(一般是Ctrl C強制退出時出現, 程序因為Exception退出沒問題),可能會導致顯存/內存未釋放.
問題描述和臨時解決方法參考論壇的帖子: GPU memory not returned
這個嚴格來說並不算PyTorch的問題,應該算是multiprocessing 庫的bug
先寫這麼多 慢慢補充
還有一些bug/坑, 大多是一些細枝末節, 看報錯信息,就能解決,第二次基本也就不會再犯了,
- 對輸入類型要求,比如 nn.Embedding的輸入必須是LongTensor
- 忘記把數據轉移到GPU,(模型轉移了數據沒轉移)
更多的bug可以去github上的issue裡面找 pytorch/pytorch , 不過基本不會遇到. 遇到了也容易調試,畢竟動態圖, pdb.set_trace() 全搞定.
- 部分tensor的操作並不支持Variable,比如torch.histc 和 torch.eig,如果你想用Variable作為這些操作的輸入的話,就只有自己手寫了。
- 單機多卡在運行時,有時會出現Nan的問題,完全相同的代碼在單卡上是正常的。我目前的解決方案是在出現Nan的層之前加個eps。。。
- Pytorch對於多機多卡的支持實在是有點不給力
- 單機多卡的情況下,會出現某張卡(默認第一張)負載遠大於其他幾張卡的情況。不過在一些第三方的parallel上面有修復[DataParallel](Data Parallel - Encoding master documentation)
pytorch 的dataloader 進程經常殺不幹凈,導致GPU內存沒有釋放。
還得使用 ps aux|grep lk|grep python|awk "{print $2}"|xargs kill 來進一步殺死進程,
才能徹底釋放GPU
曾經遇到的,lstm內存泄漏,訓練著訓練著就掛了,用了master branch的fix問題還是存在。。。
說個我的痛點(如果有大神能幫解決的話當然更好~):
Pytorch定義網路非常靈活,定義一個Resnet152所需要的代碼量比caffe要少的多得多。
但就是因為太靈活了,所以有的時候,也會遇到麻煩。
舉個例子,經常會有這種情況:假設已經預訓練了一個網路A,然後我們不想要A的FC層了,只想要它的pool5層,然後在後面再接一個其他的網路B,如圖所示:
如果在caffe中,這個問題十分好辦,因為caffe的每一層都定義在prototxt文件中,每一層都需要指定一個top blob和bottom blob,我們只要改寫相應層代碼就好了。
但這件事兒在Pytorch裡面有點麻煩。Pytorch是這樣定義網路的:首先在__init__函數中實例化所有有參數的層,在forward過程中,再調用它們。它的top-bottom關係反映在你的forward代碼裡面,定義方式類似:
def forward(self, x):
x = F.relu(F.maxpool(nn.conv2d(x)))
...
上述定義方式,雖然有助於我們定義動態的、複雜的網路,但是層與層的關係並不十分明確,需要我們仔細閱讀代碼,才能明白。
如果是一個Sequential model,這個事還有解決的辦法:
import torch
import torch.nn as nn
from torchvision import models
model = models.alexnet(pretrained=True)
# remove last fully-connected layer
new_classifier = nn.Sequential(*list(model.classifier.children())[:-1])
model.classifier = new_classifier
或者:
import torch
import torch.nn as nn
from torchvision import models
original_model = models.alexnet(pretrained=True)
class AlexNetConv4(nn.Module):
def __init__(self):
super(AlexNetConv4, self).__init__()
self.features = nn.Sequential(
# stop at conv4
*list(original_model.features.children())[:-3]
)
def forward(self, x):
x = self.features(x)
return x
model = AlexNetConv4()
但如果是非Sequential的模型,就有點兒複雜了,比如說下圖:
紅色是原有網路,一個類似resnet的結構,現在我們想把第二個單元的結果引出一條綠線,到一個新的網路,如果用上面代碼的方法,無疑會破壞原有的結構。
希望有大神能幫忙解答一下這個問題......
我覺得模型的保存就有坑。自定義class保存後,如果在新的文件里load,還需要重新定義class。
1/2更新:因為onnx需要用源碼編譯pytorch,所以重新安裝一遍。首先就是版本問題,cudnn/cuda版本如果不對,是無法編譯完成的。重點是,編譯完成後,你迫不及待的import torch想驗證是否安裝成功時,出現了importerror,更神奇的是,官方給出的解釋是,不要在pytorch根目錄下import…
在做inference時,千萬要記住對輸入的Variable設置volatile 為true.而不能設置requires_grad 為false.血的教訓。。。
1、Variable 和 Tensor 的操作不統一,有些函數可以在Tensor上做,但不可以在Variable上做
2、分散式訓練,官方給的ImageNet Tutorial 分散式訓練多GPU可以,但是多機多卡訓練會有問題
3、網路架構名字定義:卷積神經網路里每一層的名字是4.1.0.1,這誰看得懂是第幾層,是conv層還是relu層還是BN層...
然而我還是支持pytorch,同時支持mxnet。 逃...
一個最近一直被困擾的問題:由於pytorch的rnn實現默認直接拉的cudnn,導致如果想customize某些特殊rnn的話非常麻煩,顯存佔用明顯上升的同時速度慢個幾倍……(也包括了其他答案說到的for循環的問題)還有之前遇到的:用兩張卡做data parallel訓練的時候loss的下降顯著慢於單卡訓練,至今沒明白我哪裡弄錯了,於是再沒用過多卡訓練…
舉個我沒解決的例子:
想跑Wikipedia這樣的數據集,發現顯存用著用著就out of memory了。按道理說,假如我有Variable使用了沒釋放,那麼我的gpu memory應該是逐步增加的。但我目前的狀態是每隔半小時顯存使用突然上跳1G。崩潰。找不到什麼太好的debug方法,如果是tensorflow,看一下tensorboard就能解決。
希望大佬們給點意見。
這個問題終於解決了,自己手動build from source pytorch 顯存就正常了!WQNMLGB
PS:
1.如果你搜一下Softmax這個函數,你就會發現吐槽無數。。。softmax比如輸入一維,是對第一維做softmax;輸入二維,那麼是對第二維做softmax;輸入三維是對第二維做。。。維數選擇像隨機數一樣。
2.算grad要register_hook
3.數據格式NCHW,NHWC隨機跳轉。使用MKL時候NCHW會更快,GPU時NHWC更快。 尼瑪給我隨便跳,你讓我用MKL還是GPU?
4.LSTM里的drop_out 參數在一層LSTM時是無用的, 但一般人就用一層。
5. for循環效率太差
pytorch訓練得到的結果總是會比caffe的差一點點??
本答案適用於 0.2.0 版。
- (極為嚴重,已在 master 版修復)用 np.newaxis (None) 給 Tensor/Variable 加維度的時候,和 numpy 不一致 Parity with NumPy newaxis placement in indexing by killeent · Pull Request #2779 · pytorch/pytorch。剛剛遇到這個坑,於是儘可能把 code 換成用 Tensor.view 改寫了。
- DataLoader 有時候會死掉 possible deadlock in dataloader · Issue #1355 · pytorch/pytorch。我是在使用 0.1.2 版本的時候遇到的這個問題。目前(在 master 版上)似乎還是沒有解決,大家眾說紛紜。
原來想在自己踩過的坑上點個贊... 結果看下來幾乎都踩了...
補充一個神一樣的inplace operation, tensor可以跑 variable不可以, forward可以跑 backward不可以
"""
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation
RuntimeError: in-place operations can be only used on variables that don"t share storage with any other variables, but detected that there are 2 objects sharing it
"""
不懂計算圖的原理真的很難寫對
推薦閱讀:
※PyTorch提取中間層特徵?
※如何評價 2017 年 12 月 5 日發布的 PyTorch 0.3.0?
※如何評價MXNet發布的1.0版本?
※PyTorch到底好用在哪裡?
※2017年1月18日Facebook發行的PyTorch相比TensorFlow、MXNet有何優勢?
TAG:深度學習DeepLearning | PyTorch |