深度學習小筆記05-擴展autograd-摘抄自《深度學習框架PyTorch:入門與實踐》陳雲-附個人書評

爲什麼摘抄這一段,因爲我認爲這裏是一個非常有用的部分,看完autograd就想去問答區提問:
訓練指定層
然後發現沒有c幣,於是乎暫時作罷,結果發現答案就在下一小節(先看完再想問題,不然浪費了一個好問題),沒辦法我就是這麼熱愛思考的一個人,看完立刻就有問題,等不到再看一段書。


— 我是分界線—
p94:目前,絕大多數函數都可以使用autograd實現反向求導,但如果需要自己寫一個複雜的函數,不支持自動反向求導怎麼辦?答案是寫一個Function,實現它的前向傳播和反向傳播代碼,Function對應於計算圖中的矩形,它接收參數,計算並返回結果。下面給出一個例子:

class Mul(Function):
    @staticmethod
    def forward(ctx, w, x, b, x_requires_grad = True):
        ctx.x_requires_grad = x_requires_grad
        ctx.save_for_backward(w,x)
        output = w*x+b
        return output
    @staticmethod
    def backward(ctx, grad_output):
        w,x = ctx.saved_variables
        grad_w = grad_output * x
        if ctx.x_requires_grad:
            grad_x = grad_output * w
        else:
            grad_x = None
        grad_b = grad_output * 1
        return grad_w, grad_x, grad_b, None
    

對以上代碼的分析如下。

  • 自定義的Function需要繼承autograd.Function,沒有構造函數__init__,forward和backward函數都是靜態方法
  • forward函數的輸入和輸出都是tensor,backward函數的輸入和輸出都是variable
  • backward函數的輸出和forward函數的輸入一一對應,backward函數的輸入和forward函數的輸出一一對應
  • backward函數的grad_output參數即t.autograd.backward中的grad_variables
  • 如果某一個輸入不需要求導,直接返回None
  • 反向傳播可能需要利用前向傳播的某些中間結果,在前向傳播過程中,需要保存中間結果,否則前向傳播結束後這些對象即被釋放

使用Function.apply(variable)即可調用實現的Function

from torch.autograd import Function

class MultiplyAdd(Function):
    
    @staticmethod
    def forward(ctx, w, x, b):
        print('type in forward', type(x))
        ctx.save_for_backward()
        output = w*x+b
        return output
    
    @staticmethod
    def backward(ctx, grad_output):
        w,x = ctx.saved_variables
        print('type in backward', type(x))
        grad_w = grad_output * x
        grad_x = grad_output * w
        grad_b = grad_output * 1
        return grad_w, grad_x, grad_b
    
x = V(t.ones(1))
w = V(t.rand(1), requires_grad = True)
b = V(t.rand(1), requires_grad = True)
print('forward')
z = MultiplyAdd.apply(w,x,b)
print('backward')
z.backward()
x.grad, w.grad, b.grad

forward函數的輸入是tensor,而backward函數的輸入是variable,這是爲了實現高階求導,backward函數的輸入值是variable,但是在實際使用時autograd.Function會將輸入variable提取爲tensor,並將計算結果的tensor封裝成variable返回,在backward函數中要對variable進行操作,是爲了能夠計算梯度的梯度。

書評

這本書不適合完全沒有基礎的人看,更像是介紹如何使用PyTorch框架的一本書,但是各大框架正在飛速發展,這本書用的版本和接口,很多在PyTorch1.0裏面甚至0.4裏面就已經deprecated(棄用)了。在看過PyTorch的官方Tutorials之後,這本書可以不看的,我看完也沒有太大的收穫,當然還是有的,最大的收穫就是對整個框架的設計邏輯和思路設計有了整體的認識,知識更有體系,想要深入認真玩好這個框架還是看官方的Doc更直接些,只不過作爲第一個入門框架直接上官方Doc可能難度較大。(其實也還好,理解起來也沒有太大問題,系統學一遍只是讓自己更踏實)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章