Pytorch中關(guān)于inplace的操作
Pytorch中inplace操作
之前在寫(xiě)訓(xùn)練代碼時(shí),遇到了inplace operation導(dǎo)致的問(wèn)題,所以就了解了一下pytorch的inplace operation,記錄一下inplace操作的知識(shí)。
報(bào)錯(cuò)信息如下:
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation.
Inplace操作概述
稍微了解過(guò)python的人應(yīng)該會(huì)知道python的變量名是一個(gè)類似索引的東西,其指向內(nèi)存中的一個(gè)對(duì)象。
而對(duì)該變量重新賦值,實(shí)際上是將該變量名指向內(nèi)存中的其它對(duì)象,原對(duì)象本身其實(shí)并未改變。而Inplace操作并非如此,該操作會(huì)直接改變?cè)瓕?duì)象的內(nèi)容,這樣能減少內(nèi)存的消耗,但也會(huì)帶來(lái)一些隱患。
非inplace操作如下圖所示,運(yùn)算操作先是開(kāi)辟了一塊新的內(nèi)存存放運(yùn)算后的結(jié)果,然后再將引用指向新內(nèi)存,而舊內(nèi)存的內(nèi)容保持不變。
而inplace操作則不同,運(yùn)算操作會(huì)直接在舊內(nèi)存上進(jìn)行更改,而并不會(huì)另外開(kāi)辟一個(gè)新內(nèi)存進(jìn)行運(yùn)算結(jié)果的存放。
inplace操作的優(yōu)缺點(diǎn)
要使用好inplace操作,首先肯定需要知道其存在的優(yōu)點(diǎn)以及缺點(diǎn)。根據(jù)inplace操作的原理,其實(shí)不難發(fā)現(xiàn)其優(yōu)點(diǎn)就在于節(jié)省內(nèi)存,尤其是在處理高維數(shù)據(jù)時(shí)能顯著減少額外的內(nèi)存開(kāi)銷,這在訓(xùn)練神經(jīng)網(wǎng)絡(luò)時(shí)是很有價(jià)值的一個(gè)特性。
但在節(jié)省內(nèi)存的同時(shí),inplace操作也帶來(lái)了一些隱患,pytorch的官方文檔是這樣說(shuō)的:
- inplace操作可能會(huì)覆蓋計(jì)算梯度所需的值。
- 每個(gè)inplace操作實(shí)際上都需要實(shí)現(xiàn)重寫(xiě)計(jì)算圖。Out-of-place版本只是簡(jiǎn)單地分配新對(duì)象并保持對(duì)舊圖的引用,而inplace操作則要求將所有輸入的創(chuàng)建者更改為表示該操作的函數(shù)。
也就是說(shuō),在Autograd中支持inplace操作很困難,有時(shí)候會(huì)在不經(jīng)意間導(dǎo)致自動(dòng)求導(dǎo)失敗,得到上文所提到的報(bào)錯(cuò)。同時(shí),Autograd積極的緩沖區(qū)釋放和重用使其非常高效,inplace操作實(shí)際上并不能降低太多內(nèi)存的消耗,因此在大多數(shù)情況下不鼓勵(lì)使用。除非在沉重的內(nèi)存壓力下運(yùn)行,否則可能永遠(yuǎn)不需要使用inplace操作。
PS:如果你使用了inplace操作而沒(méi)有報(bào)錯(cuò)的話,那么你可以確定你的梯度計(jì)算是正確的。但是,這僅僅表示Autograd計(jì)算梯度無(wú)誤,如果出現(xiàn)了該內(nèi)存被其他變量引用而未注意,依舊可能存在計(jì)算一致性的風(fēng)險(xiǎn)。
常見(jiàn)的inplace操作
inplace操作有優(yōu)點(diǎn)也有缺點(diǎn),但總體來(lái)說(shuō)還是弊大于利,所以如果顯存足夠的話,還是盡量少用inplace操作。那inplace操作有哪些呢?
- 1.數(shù)值運(yùn)算,如
x+=1
屬于inplace操作,會(huì)直接對(duì)x的值進(jìn)行操作;而y=x+5
則不屬于inplace操作(PS:x+=1
雖然是inplace操作,但求導(dǎo)時(shí)其導(dǎo)數(shù)為1,導(dǎo)數(shù)值并不與x的值相關(guān),所以不會(huì)對(duì)反向傳播產(chǎn)生影響,故這種情況的影響不大) - 2.pytorch提供的一些inplace選項(xiàng),如
nn.ReLU(inplace=True)
、nn.LeakyReLU(inplace=True)
,這些選項(xiàng)的安全性要高一些,但也需要注意中間變量后續(xù)是否需要,如果后面還需要使用中間變量,就應(yīng)當(dāng)設(shè)置inplace=False
- 3.具有 _ 后綴的方法,如
x.copy_(y)
,x.t_()
,將直接改變x。同時(shí),一些常見(jiàn)的操作如x.add_(y)
、x.mul_(y)
也會(huì)直接改變x,除非有特定需求,否則不建議使用這類inplace操作,隱患比前兩種情況高很多。
以上是常見(jiàn)的一些inplace操作,雖然不建議使用inplace操作,但還是需要了解一下,以免日后遇到問(wèn)題。
注意:
inplace操作會(huì)直接修改原內(nèi)存處的值,雖然會(huì)節(jié)省一些內(nèi)存,但也會(huì)帶來(lái)一些隱患,如自動(dòng)求導(dǎo)出錯(cuò)等。因此如果不是內(nèi)存十分緊缺,不建議使用inplace操作。
pytorch的inplace的問(wèn)題
最近將一個(gè)模型訓(xùn)練代碼從caffe平臺(tái)移植到pytorch平臺(tái)過(guò)程中遇到了一個(gè)詭異的inplace坑,特別記錄一下防止大家掉坑。
relu等激活函數(shù)的inplace
看到官方的relu入?yún)⑹侵衝n.ReLU(inplace=True)是inplace操作,我一想這不是能節(jié)省我的資源占用,毫不猶豫的選擇了True。
搭好模型運(yùn)行,結(jié)果是在backward計(jì)算導(dǎo)數(shù)的時(shí)候。表示inplace操作導(dǎo)致求導(dǎo)結(jié)果有問(wèn)題。
改為**nn.ReLU(inplace=False)**問(wèn)題在pytorch1.3和pytorch1.8解決了。
“+=”操作的默認(rèn)inplace
后來(lái)因?yàn)閾Q了pytorch1.10版本后又報(bào)錯(cuò)了。報(bào)錯(cuò)形式和上面一樣。
后來(lái)查了一下“+=”也是inplace操作,將工程中網(wǎng)絡(luò)的前向傳播方式中:x += feature16改為:“x = x + feature16” 。
問(wèn)題就消失了。
報(bào)錯(cuò)形式
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.HalfTensor [×,×,×,×]], which is output 0 of ReluBackward0, is at version 1; expected version 0 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python爬蟲(chóng)入門(mén)有哪些基礎(chǔ)知識(shí)點(diǎn)
在本篇文章中小編給大家整理的是關(guān)于Python爬蟲(chóng)入門(mén)基礎(chǔ)知識(shí)點(diǎn)整理,有興趣的朋友們可以跟著學(xué)習(xí)下。2020-06-06在類Unix系統(tǒng)上開(kāi)始Python3編程入門(mén)
這篇文章主要介紹了在類Unix系統(tǒng)上開(kāi)始Python3編程入門(mén),講解了最基礎(chǔ)最直觀的利用Print函數(shù)進(jìn)行各種輸出的方法,需要的朋友可以參考下2015-08-08python數(shù)據(jù)處理 根據(jù)顏色對(duì)圖片進(jìn)行分類的方法
今天小編就為大家分享一篇python數(shù)據(jù)處理 根據(jù)顏色對(duì)圖片進(jìn)行分類的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12python cv2.resize函數(shù)high和width注意事項(xiàng)說(shuō)明
這篇文章主要介紹了python cv2.resize函數(shù)high和width注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)(一)
這篇文章主要為大家詳細(xì)介紹了python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)第一篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12python人人網(wǎng)登錄應(yīng)用實(shí)例
這篇文章主要介紹了python人人網(wǎng)登錄應(yīng)用實(shí)例,是一個(gè)非常實(shí)用的技巧,需要的朋友可以參考下2014-09-09Python中使用gzip模塊壓縮文件的簡(jiǎn)單教程
這篇文章主要介紹了Python中使用gzip模塊壓縮文件的簡(jiǎn)單教程,本文的例子主要針對(duì)類UNIXZ系統(tǒng),需要的朋友可以參考下2015-04-04python 實(shí)現(xiàn)網(wǎng)上商城,轉(zhuǎn)賬,存取款等功能的信用卡系統(tǒng)
本篇文章主要介紹 基于python 實(shí)現(xiàn)信用卡系統(tǒng),附有代碼實(shí)例,對(duì)于用python 開(kāi)發(fā)網(wǎng)絡(luò)上傳系統(tǒng)具有參考價(jià)值,有需要的朋友可以看下2016-07-07python numpy之np.random的隨機(jī)數(shù)函數(shù)使用介紹
這篇文章主要介紹了python numpy之np.random的隨機(jī)數(shù)函數(shù)使用介紹,需要的朋友可以參考下2019-10-10