1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        PyTorch的自動求導(dǎo)機制詳細解析,PyTorch的核心魔法

        共 4756字,需瀏覽 10分鐘

         ·

        2022-07-05 10:35

        點擊上方小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂

        重磅干貨,第一時間送達


        者:Vaibhav Kumar

        編譯:ronghuaiyang

        導(dǎo)讀

        這篇文章詳細解析了PyTorch的自動求導(dǎo)機制,讓你了解PyTorch的核心魔法。

        在這個過程中,它從不顯式地構(gòu)造整個雅可比矩陣。直接計算JVP通常更簡單、更有效。

        我們都同意,當(dāng)涉及到大型神經(jīng)網(wǎng)絡(luò)時,我們都不擅長微積分。通過顯式求解數(shù)學(xué)方程來計算這樣大的復(fù)合函數(shù)的梯度是不現(xiàn)實的,特別是這些曲線存在于大量的維數(shù)中,是無法理解的。

        要處理14維空間中的超平面,想象一個三維空間,大聲地對自己說“14”。每個人都這么做——Geoffrey Hinton

        這就是PyTorch的autograd發(fā)揮作用的地方。它抽象了復(fù)雜的數(shù)學(xué),幫助我們“神奇地”計算高維曲線的梯度,只需要幾行代碼。這篇文章試圖描述autograd的魔力。


        PyTorch基礎(chǔ)

        在進一步討論之前,我們需要了解一些基本的PyTorch概念。

        張量:簡單地說,它只是PyTorch中的一個n維數(shù)組。張量支持一些額外的增強,這使它們獨一無二:除了CPU,它們可以加載或GPU更快的計算。在設(shè)置.requires_grad = True的時候,他們開始形成一個反向圖,跟蹤應(yīng)用于他們的每個操作,使用所謂的動態(tài)計算圖(DCG)計算梯度(后面會進一步解釋)。

        在早期版本的PyTorch中,使用torch.autograd.Variable類用于創(chuàng)建支持梯度計算和操作跟蹤的張量,但截至PyTorch v0.4.0,Variable類已被禁用。torch.Tensortorch.autograd.Variable現(xiàn)在是同一個類。更準(zhǔn)確地說, torch.Tensor能夠跟蹤歷史并表現(xiàn)得像舊的Variable。

        import torch import numpy as np  x = torch.randn(2, 2, requires_grad = True)  # From numpy x = np.array([1., 2., 3.]) #Only Tensors of floating point dtype can require gradients x = torch.from_numpy(x) # Now enable gradient x.requires_grad_(True) # _ above makes the change in-place (its a common pytorch thing)

        創(chuàng)建啟用梯度的張量的各種方法的代碼

        注意:根據(jù)PyTorch的設(shè)計,梯度只能計算浮點張量,這就是為什么我創(chuàng)建了一個浮點類型的numpy數(shù)組,然后將它設(shè)置為啟用梯度的PyTorch張量。

        Autograd:這個類是一個計算導(dǎo)數(shù)的引擎(更精確地說是雅克比向量積)。它記錄了梯度張量上所有操作的一個圖,并創(chuàng)建了一個稱為動態(tài)計算圖的非循環(huán)圖。這個圖的葉節(jié)點是輸入張量,根節(jié)點是輸出張量。梯度是通過跟蹤從根到葉的圖形,并使用鏈?zhǔn)椒▌t將每個梯度相乘來計算的。


        神經(jīng)網(wǎng)絡(luò)和反向傳播

        神經(jīng)網(wǎng)絡(luò)只不過是經(jīng)過精心調(diào)整(訓(xùn)練)以輸出所需結(jié)果的復(fù)合數(shù)學(xué)函數(shù)。調(diào)整或訓(xùn)練是通過一種稱為反向傳播的出色算法完成的。反向傳播用來計算相對于輸入權(quán)值的損失梯度,以便以后更新權(quán)值,最終減少損失。

        在某種程度上,反向傳播只是鏈?zhǔn)椒▌t的一個花哨的名字—— Jeremy Howard

        創(chuàng)建和訓(xùn)練神經(jīng)網(wǎng)絡(luò)包括以下基本步驟:

        1. 定義體系結(jié)構(gòu)

        2. 使用輸入數(shù)據(jù)在體系結(jié)構(gòu)上向前傳播

        3. 計算損失

        4. 反向傳播,計算每個權(quán)重的梯度

        5. 使用學(xué)習(xí)率更新權(quán)重

        損失變化引起的輸入權(quán)值的微小變化稱為該權(quán)值的梯度,并使用反向傳播計算。然后使用梯度來更新權(quán)值,使用學(xué)習(xí)率來整體減少損失并訓(xùn)練神經(jīng)網(wǎng)絡(luò)。

        這是以迭代的方式完成的。對于每個迭代,都要計算幾個梯度,并為存儲這些梯度函數(shù)構(gòu)建一個稱為計算圖的東西。PyTorch通過構(gòu)建一個動態(tài)計算圖(DCG)來實現(xiàn)這一點。此圖在每次迭代中從頭構(gòu)建,為梯度計算提供了最大的靈活性。例如,對于前向操作(函數(shù))Mul ,向后操作函數(shù)MulBackward被動態(tài)集成到后向圖中以計算梯度。


        動態(tài)計算圖

         

        支持梯度的張量(變量)和函數(shù)(操作)結(jié)合起來創(chuàng)建動態(tài)計算圖。數(shù)據(jù)流和應(yīng)用于數(shù)據(jù)的操作在運行時定義,從而動態(tài)地構(gòu)造計算圖。這個圖是由底層的autograd類動態(tài)生成的。你不必在啟動訓(xùn)練之前對所有可能的路徑進行編碼——你運行的是你所區(qū)分的。

        一個簡單的DCG用于兩個張量的乘法會是這樣的:

        帶有requires_grad = False的DCG

        圖中的每個點輪廓框是一個變量,紫色矩形框是一個操作。

        每個變量對象都有幾個成員,其中一些成員是:

        Data:它是一個變量持有的數(shù)據(jù)。x持有一個1x1張量,其值等于1.0,而y持有2.0。z持有兩個的乘積,即2.0。

        requires_grad:這個成員(如果為true)開始跟蹤所有的操作歷史,并形成一個用于梯度計算的向后圖。對于任意張量a,可以按如下方式對其進行原地處理:a.requires_grad_(True)。

        grad: grad保存梯度值。如果requires_grad 為False,它將持有一個None值。即使requires_grad 為真,它也將持有一個None值,除非從其他節(jié)點調(diào)用.backward()函數(shù)。例如,如果你對out關(guān)于x計算梯度,調(diào)用out.backward(),則x.grad的值為?out/?x

        grad_fn:這是用來計算梯度的向后函數(shù)。

        is_leaf:如果:

        1. 它被一些函數(shù)顯式地初始化,比如x = torch.tensor(1.0)x = torch.randn(1, 1)(基本上是本文開頭討論的所有張量初始化方法)。

        2. 它是在張量的操作之后創(chuàng)建的,所有張量都有requires_grad = False。

        3. 它是通過對某個張量調(diào)用.detach()方法創(chuàng)建的。

        在調(diào)用backward()時,只計算requires_gradis_leaf同時為真的節(jié)點的梯度。

        當(dāng)打開 requires_grad = True時,PyTorch將開始跟蹤操作,并在每個步驟中存儲梯度函數(shù),如下所示:

        requires_grad = True的DCG

        在PyTorch下生成上圖的代碼是:


        Backward()函數(shù)


         

        Backward函數(shù)實際上是通過傳遞參數(shù)(默認情況下是1x1單位張量)來計算梯度的,它通過Backward圖一直到每個葉節(jié)點,每個葉節(jié)點都可以從調(diào)用的根張量追溯到葉節(jié)點。然后將計算出的梯度存儲在每個葉節(jié)點的.grad中。請記住,在正向傳遞過程中已經(jīng)動態(tài)生成了后向圖。backward函數(shù)僅使用已生成的圖形計算梯度,并將其存儲在葉節(jié)點中。

        讓我們分析以下代碼:

         import torch # Creating the graph x = torch.tensor(1.0, requires_grad = True) z = x ** 3 z.backward() #Computes the gradient print(x.grad.data) #Prints '3' which is dz/dx

        需要注意的一件重要事情是,當(dāng)調(diào)用z.backward()時,一個張量會自動傳遞為z.backward(torch.tensor(1.0))。torch.tensor(1.0)是用來終止鏈?zhǔn)椒▌t梯度乘法的外部梯度。這個外部梯度作為輸入傳遞給MulBackward函數(shù),以進一步計算x的梯度。傳遞到.backward()中的張量的維數(shù)必須與正在計算梯度的張量的維數(shù)相同。例如,如果梯度支持張量x和y如下:

        x = torch.tensor([0.0, 2.0, 8.0], requires_grad = True) y = torch.tensor([5.0 , 1.0 , 7.0], requires_grad = True) z = x * y

        然后,要計算z關(guān)于x或者y的梯度,需要將一個外部梯度傳遞給z.backward()函數(shù),如下所示:

         z.backward(torch.FloatTensor([1.0, 1.0, 1.0])

        z.backward() 會給出 RuntimeError: grad can be implicitly created only for scalar outputs

        反向函數(shù)傳遞的張量就像梯度加權(quán)輸出的權(quán)值。從數(shù)學(xué)上講,這是一個向量乘以非標(biāo)量張量的雅可比矩陣(本文將進一步討論),因此它幾乎總是一個維度的單位張量,與 backward張量相同,除非需要計算加權(quán)輸出。

        tldr :向后圖是由autograd類在向前傳遞過程中自動動態(tài)創(chuàng)建的。Backward()只是通過將其參數(shù)傳遞給已經(jīng)生成的反向圖來計算梯度。 


        數(shù)學(xué)—雅克比矩陣和向量

        從數(shù)學(xué)上講,autograd類只是一個雅可比向量積計算引擎。雅可比矩陣是一個非常簡單的單詞,它表示兩個向量所有可能的偏導(dǎo)數(shù)。它是一個向量相對于另一個向量的梯度。

        注意:在這個過程中,PyTorch從不顯式地構(gòu)造整個雅可比矩陣。直接計算JVP (Jacobian vector product)通常更簡單、更有效。

        如果一個向量X = [x1, x2,…xn]通過f(X) = [f1, f2,…fn]來計算其他向量,則雅可比矩陣(J)包含以下所有偏導(dǎo)組合:

        雅克比矩陣

        上面的矩陣表示f(X)相對于X的梯度。

        假設(shè)一個啟用PyTorch梯度的張量X

        X = [x1,x2,…,xn](假設(shè)這是某個機器學(xué)習(xí)模型的權(quán)值)

        X經(jīng)過一些運算形成一個向量Y

        Y = f(X) = [y1, y2,…,ym]

        然后使用Y計算標(biāo)量損失l。假設(shè)向量v恰好是標(biāo)量損失l關(guān)于向量Y的梯度,如下:

        向量v稱為grad_tensor,并作為參數(shù)傳遞給backward() 函數(shù)。

        為了得到損失的梯度l關(guān)于權(quán)重X的梯度,雅可比矩陣J是向量乘以向量v

        這種計算雅可比矩陣并將其與向量v相乘的方法使PyTorch能夠輕松地為非標(biāo)量輸出提供外部梯度。


        好消息!

        小白學(xué)視覺知識星球

        開始面向外開放啦??????




        下載1:OpenCV-Contrib擴展模塊中文版教程
        在「小白學(xué)視覺」公眾號后臺回復(fù):擴展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴展模塊教程中文版,涵蓋擴展模塊安裝、SFM算法、立體視覺、目標(biāo)跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

        下載2:Python視覺實戰(zhàn)項目52講
        小白學(xué)視覺公眾號后臺回復(fù):Python視覺實戰(zhàn)項目,即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實戰(zhàn)項目,助力快速學(xué)校計算機視覺。

        下載3:OpenCV實戰(zhàn)項目20講
        小白學(xué)視覺公眾號后臺回復(fù):OpenCV實戰(zhàn)項目20講,即可下載含有20個基于OpenCV實現(xiàn)20個實戰(zhàn)項目,實現(xiàn)OpenCV學(xué)習(xí)進階。

        交流群


        歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


        瀏覽 48
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            天堂中文在线视频 | 免费ps大片直播软件有哪些 | 蜜芽成人网站 | 日本无码中文字幕 | 天海翼在丈夫面前被侵犯 | 国产精品久久久久久久久午夜福利 | 申鹤被扒开腿做同人漫画 | 国精产品一区一区三区四区mba | 精品久久久久久久久久岛国gif | 日日夜夜国产 |