我有forward一個 PyTorch 損失的自定義實作。培訓效果很好。我檢查了loss.grad_fn它,它不是None。我試圖理解兩件事:
既然在從輸入到輸出的路徑上有一個
if-陳述句,這個函式如何是可區分的?else從(地面實況輸入)到損失(輸出)的路徑是否
gt需要可微分?pred還是只有來自(預測輸入)的路徑?
這是源代碼:
class FocalLoss(nn.Module):
def __init__(self):
super(FocalLoss, self).__init__()
def forward(self, pred, gt):
pos_inds = gt.eq(1).float()
neg_inds = gt.lt(1).float()
neg_weights = torch.pow(1 - gt, 4)
pos_loss = torch.log(pred) * torch.pow(1 - pred, 2) * pos_inds
neg_loss = torch.log(1 - pred) * torch.pow(pred, 2) * neg_weights * neg_inds
num_pos = pos_inds.float().sum()
pos_loss_s = pos_loss.sum()
neg_loss_s = neg_loss.sum()
if num_pos == 0:
loss = - neg_loss_s
else:
loss = - (pos_loss_s neg_loss_s) / num_pos
return loss
uj5u.com熱心網友回復:
該if陳述句不是計算圖的一部分。它是用于動態構建此圖(即forward函式)的代碼的一部分,但它本身并不是它的一部分。要遵循的原則是問自己是否使用每個節點的回呼,通過圖反向傳播回溯到圖的葉子(圖中沒有父級的張量,即輸入和引數) 。grad_fn答案是只有在每個運算子都是可微分的情況下才能這樣做:在編程術語中,它們實作了后向函式操作(又名 grad_fn)。
在您的示例中,是否
num_pos等于或不等于,由此產生的損失張量將單獨0取決于或取決于and 。然而,在任何一種情況下,生成的張量仍然附加到輸入:neg_loss_spos_loss_sneg_loss_slosspred- 通過一種方式:“
neg_loss_s”節點 - 或另一個:“
pos_loss_s”和“neg_loss_s”節點。
- 通過一種方式:“
在您的設定中,無論哪種方式,操作都是可區分的。
- 如果
gt是一個真實張量,那么它不需要梯度,并且從它到最終損失的操作不需要是可微的。在您的示例中就是這種情況,其中pos_inds, 和neg_inds都是非微分的,因為它們是布爾運算子。
uj5u.com熱心網友回復:
PyTorch 不計算損失函式本身的梯度。PyTorch 記錄在forward傳遞程序中執行的標準數學運算的序列,例如對數、求冪、乘法、加法等,并在呼叫時根據這些數學運算計算它們的梯度。backward()因此,if-else只要您僅使用標準數學運算來計算損失,條件的存在對 PyTorch 并不重要。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/479020.html
