我有三個簡單的問題。PyTorch中的自定義丟失函數
- 如果我的自定義丟失函數不可區分會發生什麼?將pytorch通過錯誤或做別的?
- 如果我在自定義函數中聲明瞭一個將代表模型最終損失的損失變量,那麼我應該爲該變量放置
requires_grad = True
嗎?或者沒關係?如果沒關係,那爲什麼? - 我已經看到人們有時會編寫一個單獨的圖層並計算
forward
函數中的損失。編寫一個函數或一個圖層最好採用哪種方法?爲什麼?
我需要對這些問題有一個清晰而好的解釋來解決我的困惑。請幫忙。
我有三個簡單的問題。PyTorch中的自定義丟失函數
requires_grad = True
嗎?或者沒關係?如果沒關係,那爲什麼?forward
函數中的損失。編寫一個函數或一個圖層最好採用哪種方法?爲什麼?我需要對這些問題有一個清晰而好的解釋來解決我的困惑。請幫忙。
讓我走了。
這取決於你的意思是「不可微分」。第一個有意義的定義是PyTorch不知道如何計算漸變。如果您嘗試計算漸變,則會產生錯誤。這兩種可能的情況是:
a)您正在使用自定義的PyTorch操作,其漸變尚未實現,例如, torch.svd()
。在這種情況下,你會得到一個TypeError
:
import torch
from torch.autograd import Function
from torch.autograd import Variable
A = Variable(torch.randn(10,10), requires_grad=True)
u, s, v = torch.svd(A) # raises TypeError
b)你已經實現了你自己的操作,但沒有規定backward()
。在這種情況下,你會得到一個NotImplementedError
:
class my_function(Function): # forgot to define backward()
def forward(self, x):
return 2 * x
A = Variable(torch.randn(10,10))
B = my_function()(A)
C = torch.sum(B)
C.backward() # will raise NotImplementedError
是有道理的是「數學上不可微分的」第二個定義。顯然,數學上不可區分的操作應該沒有執行backward()
方法或者是合理的子梯度。例如,考慮torch.abs()
其backward()
方法在0返回梯度0:
A = Variable(torch.Tensor([-1,0,1]),requires_grad=True)
B = torch.abs(A)
B.backward(torch.Tensor([1,1,1]))
A.grad.data
對於這些情況,你應該參考PyTorch文檔直接,直接挖掘出各自的操作方法backward()
。
沒關係。使用requires_grad
是爲了避免不必要的子圖梯度計算。如果需要漸變的操作有單個輸入,則其輸出也需要漸變。相反,只有當所有輸入不需要漸變時,輸出也不需要它。反向計算從不在子圖中執行,其中所有變量不需要漸變。
因爲,最有可能的一些Variables
(例如nn.Module()
的子類的參數),您的loss
變量也將自動需要梯度。但是,您應該注意到requires_grad
的工作原理(請參閱上面的內容),無論如何,您只能更改圖表的葉變量requires_grad
。
所有自定義PyTorch丟失函數都是_Loss
的子類,它是nn.Module
的子類。See here.如果您想堅持這一慣例,則在定義自定義丟失函數時應劃分_Loss
。除了一致性之外,如果您尚未將目標變量標記爲volatile
或requires_grad = False
,則其中一個優點是您的子類將提高AssertionError
。另一個優點是,你可以將你的損失函數嵌套在nn.Sequential()
中,因爲它的一個nn.Module
我會推薦這種方法出於這些原因。
不客氣。不幸的是無法打開鏈接。 – mexmex
我之所以刪除這個問題,是因爲我解決了這個問題。但你能幫我在這個問題 - https://stackoverflow.com/questions/44580450/cuda-vs-dataparallel-why-the-difference? –