Pytorch中.detach()與.data的用法小結(jié)
Pytorch中.detach()與.data的用法
這里是官方文檔對detach的定義

實際上,detach()就是返回一個新的tensor,并且這個tensor是從當(dāng)前的計算圖中分離出來的。但是返回的tensor和原來的tensor是共享內(nèi)存空間的。
import torch a = torch.tensor([1.0, 2.0, 3.0], requires_grad = True) a = a.detach() # 會將requires_grad 屬性設(shè)置為False print(a.requires_grad)
舉個例子來說明一下detach有什么用。 如果A網(wǎng)絡(luò)的輸出被喂給B網(wǎng)絡(luò)作為輸入, 如果我們希望在梯度反傳的時候只更新B中參數(shù)的值,而不更新A中的參數(shù)值,這時候就可以使用detach()
a = A(input) a = a.deatch() # 或者a.detach_()進行in_place操作 out = B(a) loss = criterion(out, labels) loss.backward()
如果希望修改A的參數(shù), 而不希望修改B的參數(shù), 那么就需要手動將B中參數(shù)的requires_grad屬性設(shè)置為False
for param in B.parameters():
param.requires_grad = False還有一點需要注意的是Tensor.detach()和Tensor.data的區(qū)別
Tensor.data和Tensor.detach()一樣, 都會返回一個新的Tensor, 這個Tensor和原來的Tensor共享內(nèi)存空間,一個改變,另一個也會隨著改變,且都會設(shè)置新的Tensor的requires_grad屬性為False。這兩個方法只取出原來Tensor的tensor數(shù)據(jù), 丟棄了grad、grad_fn等額外的信息。區(qū)別在于Tensor.data不能被autograd追蹤到,如果你修改了Tensor.data返回的新Tensor,原來的Tensor也會改變, 但是這時候的微分并沒有被追蹤到,那么當(dāng)你執(zhí)行l(wèi)oss.backward()的時候并不會報錯,但是求的梯度就是錯誤的!因此, 如果你使用了Tensor.data,那么切記一定不要隨便修改返回的新Tensor的值。如果你使用的是Tensor.detach()方法,當(dāng)你修改他的返回值并進行求導(dǎo)操作,會報錯。 因此,Tensor.detach()是安全的。
pytorch中的.detach和.data深入詳解
前言:這兩個方法都可以用來從原有的計算圖中分離出某一個tensor,有相似的地方,也有不同的地方,下面來比較性的看一看。PyTorch0.4以及之后的版本中,.data 仍保留,但建議使用 .detach()
一、tensor.data的使用
先直接看一段代碼:
import torch
a = torch.tensor([1,2,3.], requires_grad = True)
out = a.sigmoid()
c = out.data # 需要走注意的是,通過.data “分離”得到的的變量會和原來的變量共用同樣的數(shù)據(jù),而且新分離得到的張量是不可求導(dǎo)的,c發(fā)生了變化,原來的張量也會發(fā)生變化
c.zero_() # 改變c的值,原來的out也會改變
print(c.requires_grad)
print(c)
print(out.requires_grad)
print(out)
print("----------------------------------------------")
out.sum().backward() # 對原來的out求導(dǎo),
print(a.grad) # 不會報錯,但是結(jié)果卻并不正確
'''運行結(jié)果為:
False
tensor([0., 0., 0.])
True
tensor([0., 0., 0.], grad_fn=<SigmoidBackward>)
----------------------------------------------
tensor([0., 0., 0.])
'''tensor.data的兩點總結(jié):
(1)tensor .data 返回和 x 的相同數(shù)據(jù) tensor,而且這個新的tensor和原來的tensor是共用數(shù)據(jù)的,一者改變,另一者也會跟著改變,而且新分離得到的tensor的require s_grad = False, 即不可求導(dǎo)的。(這一點其實detach是一樣的)
(2)使用tensor.data的局限性。文檔中說使用tensor.data是不安全的, 因為 x.data 不能被 autograd 追蹤求微分 。什么意思呢?從上面的例子可以看出,由于我更改分離之后的變量值c,導(dǎo)致原來的張量out的值也跟著改變了,但是這種改變對于autograd是沒有察覺的,它依然按照求導(dǎo)規(guī)則來求導(dǎo),導(dǎo)致得出完全錯誤的導(dǎo)數(shù)值卻渾然不知。它的風(fēng)險性就是如果我再任意一個地方更改了某一個張量,求導(dǎo)的時候也沒有通知我已經(jīng)在某處更改了,導(dǎo)致得出的導(dǎo)數(shù)值完全不正確,故而風(fēng)險大。
二、tensor.detach()的使用
同樣是使用上面的案例代碼,將.data 更改成 .detach,如下:
import torch
a = torch.tensor([1,2,3.], requires_grad = True)
out = a.sigmoid()
c = out.detach() # 需要走注意的是,通過.detach() “分離”得到的的變量會和原來的變量共用同樣的數(shù)據(jù),而且新分離得到的張量是不可求導(dǎo)的,c發(fā)生了變化,原來的張量也會發(fā)生變化
c.zero_() # 改變c的值,原來的out也會改變
print(c.requires_grad)
print(c)
print(out.requires_grad)
print(out)
print("----------------------------------------------")
out.sum().backward() # 對原來的out求導(dǎo),
print(a.grad) # 此時會報錯,錯誤結(jié)果參考下面,顯示梯度計算所需要的張量已經(jīng)被“原位操作inplace”所更改了。
'''
False
tensor([0., 0., 0.])
True
tensor([0., 0., 0.], grad_fn=<SigmoidBackward>)
----------------------------------------------
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation
'''tensor.detach()的兩點總結(jié):
(1)tensor .detach() 返回和 x 的相同數(shù)據(jù) tensor,而且這個新的tensor和原來的tensor是共用數(shù)據(jù)的,一者改變,另一者也會跟著改變,而且新分離得到的tensor的require s_grad = False, 即不可求導(dǎo)的。(這一點其實 .data是一樣的)
(2)使用tensor.detach()的優(yōu)點。從上面的例子可以看出,由于我更改分離之后的變量值c,導(dǎo)致原來的張量out的值也跟著改變了,這個時候如果依然按照求導(dǎo)規(guī)則來求導(dǎo),由于out已經(jīng)更改了,所以不會再繼續(xù)求導(dǎo)了,而是報錯,這樣就避免了得出完全牛頭不對馬嘴的求導(dǎo)結(jié)果。
三、總結(jié)
相同點:tensor.data和tensor.detach() 都是變量從圖中分離,但而這都是“原位操作 inplace operation”。
不同點:
(1).data 是一個屬性,二.detach()是一個方法;
(2).data 是不安全的,.detach()是安全的。
到此這篇關(guān)于Pytorch中.detach()與.data的用法的文章就介紹到這了,更多相關(guān)Pytorch中.detach()與.data內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
caffe的python接口繪制loss和accuracy曲線
這篇文章主要為大家介紹了caffe的python接口繪制loss和accuracy曲線示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
基于MSELoss()與CrossEntropyLoss()的區(qū)別詳解
今天小編就為大家分享一篇基于MSELoss()與CrossEntropyLoss()的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01
PyCharm安裝Python時的常見pip報錯原因與解決方案全解析
在使用 PyCharm 進行 Python 開發(fā)時,許多開發(fā)者常遇到 pip install 失敗的問題,本文將系統(tǒng)梳理常見錯誤場景,并提供高效、可靠的解決方法,有需要的小伙伴可以了解下2026-02-02
Python使用Pydantic進行數(shù)據(jù)驗證與序列化詳解
Pydantic庫通過使用Python類型注解來提供數(shù)據(jù)驗證和設(shè)置管理,使得數(shù)據(jù)處理變得更加可靠和高效,本文將深入探討Pydantic的使用,通過理論講解和實際代碼示例,展示如何在項目中高效利用Pydantic進行數(shù)據(jù)驗證與序列化,需要的可以了解下2025-12-12
django rest framework 實現(xiàn)用戶登錄認證詳解
這篇文章主要介紹了django rest framework 實現(xiàn)用戶登錄認證詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-07-07

