從零實(shí)現(xiàn)深度學(xué)習(xí)框架(一)自動(dòng)求導(dǎo)神器計(jì)算圖

引言
本著“凡我不能創(chuàng)造的,我就不能理解”的思想,本系列文章會(huì)基于純Python以及NumPy從零創(chuàng)建自己的深度學(xué)習(xí)框架,該框架類似PyTorch能實(shí)現(xiàn)自動(dòng)求導(dǎo)。
要深入理解深度學(xué)習(xí),從零開始創(chuàng)建的經(jīng)驗(yàn)非常重要,從自己可以理解的角度出發(fā),盡量不適用外部完備的框架前提下,實(shí)現(xiàn)我們想要的模型。本系列文章的宗旨就是通過這樣的過程,讓大家切實(shí)掌握深度學(xué)習(xí)底層實(shí)現(xiàn),而不是僅做一個(gè)調(diào)包俠。
本系列文章首發(fā)于微信公眾號(hào):JAVA&NLP
本文介紹自動(dòng)求導(dǎo)的基礎(chǔ)知識(shí)——計(jì)算圖。
計(jì)算圖
我們知道,反向傳播是模型訓(xùn)練的途徑。而反向傳播是基于求導(dǎo)的,有沒有想過像Keras和PyTorch這種工具是如何做到自動(dòng)求導(dǎo)的。答案就是計(jì)算圖,只要掌握了計(jì)算圖的知識(shí),我們就能自己開發(fā)一個(gè)自動(dòng)求導(dǎo)工具。
計(jì)算圖是一種描述函數(shù)的工具,可以可視化為有向圖結(jié)構(gòu)。其中節(jié)點(diǎn)為Tensor(向量/張量),有向邊為操作。
在深度學(xué)習(xí)中比較常見的例子是類似

x可以看成是輸入,y可以看成是輸出,中間經(jīng)過了3次變換。
有時(shí)我們的函數(shù)有多個(gè)參數(shù)(比如乘法就有兩個(gè)參數(shù)),假設(shè)我們要計(jì)算,它的計(jì)算圖如下:

這里令,為了完整性,也畫出了常量。
有了這個(gè)計(jì)算圖,我們就就可以很容易的計(jì)算出的值。比如令

當(dāng)然,我們這么辛苦的畫出這個(gè)圖,主要不是為了沿著箭頭方向進(jìn)行計(jì)算的。而是為了求導(dǎo),也就是計(jì)算梯度。
計(jì)算圖上的梯度
回顧一下鏈?zhǔn)椒▌t


我們重點(diǎn)來看下多路徑的鏈?zhǔn)椒▌t,即上面說的全導(dǎo)數(shù)。
我們要計(jì)算中。
。
類似上圖中的,也影響了兩個(gè)因子。因此有
要計(jì)算偏導(dǎo)數(shù),我們先把每個(gè)箭頭的偏導(dǎo)數(shù)計(jì)算出來。

我們先填入計(jì)算出來的式子:

根據(jù)以及求導(dǎo)公式不難得到上面的結(jié)果。
此時(shí),要計(jì)算,只需要找出所有從到到路徑,然后把相同路徑上的值相乘,不同路徑上的值相加(連線相乘,分線相加)。
就可以得到:
此時(shí),代入。
先計(jì)算出,再計(jì)算,所以
反向模式
如果要同時(shí)計(jì)算對(duì)和的偏導(dǎo)數(shù),我們需要反向模式(Reverse mode)來同時(shí)計(jì)算它們。

反向就是從頂點(diǎn)開始,這里從開始,也從梯度等于開始。
從頂點(diǎn)到,通過有兩條路徑,如山古同橙色箭頭所示。達(dá)到時(shí)的梯度為;到達(dá)時(shí)的梯度為。
和到的梯度都是。根據(jù)相同路徑相乘,不同路徑相加。到到梯度為。

此時(shí),計(jì)算到的就簡(jiǎn)單了,我們已經(jīng)知道了到到梯度為,由于到只有一條路徑,因此直接相乘得。
如果你的函數(shù)只有一個(gè)輸出,由需要同時(shí)計(jì)算大量的不同值的偏導(dǎo)數(shù)時(shí),用反向模式就比較快。
而這恰恰非常適合于我們計(jì)算損失函數(shù)的梯度,因?yàn)閾p失函數(shù)的輸出就是一個(gè)標(biāo)量。
最后一句:BUG,走你!


Markdown筆記神器Typora配置Gitee圖床
不會(huì)真有人覺得聊天機(jī)器人難吧(一)
Spring Cloud學(xué)習(xí)筆記(一)
沒有人比我更懂Spring Boot(一)
入門人工智能必備的線性代數(shù)基礎(chǔ)
1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的在看是我創(chuàng)作的動(dòng)力。
2.關(guān)注公眾號(hào),每天為您分享原創(chuàng)或精選文章!
3.特殊階段,帶好口罩,做好個(gè)人防護(hù)。
