Python深度學(xué)習(xí)入門(mén)(從零構(gòu)建CNN和RNN)_第1頁(yè)
Python深度學(xué)習(xí)入門(mén)(從零構(gòu)建CNN和RNN)_第2頁(yè)
Python深度學(xué)習(xí)入門(mén)(從零構(gòu)建CNN和RNN)_第3頁(yè)
Python深度學(xué)習(xí)入門(mén)(從零構(gòu)建CNN和RNN)_第4頁(yè)
Python深度學(xué)習(xí)入門(mén)(從零構(gòu)建CNN和RNN)_第5頁(yè)
已閱讀5頁(yè),還剩176頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

\hPython深度學(xué)習(xí)入門(mén)從零構(gòu)建CNN和RNN目錄\h第1章基本概念\h1.1函數(shù)\h數(shù)學(xué)\h示意圖\h代碼\h1.2導(dǎo)數(shù)\h數(shù)學(xué)\h示意圖\h代碼\h1.3嵌套函數(shù)\h數(shù)學(xué)\h示意圖\h代碼\h1.4鏈?zhǔn)椒▌t\h數(shù)學(xué)\h示意圖\h代碼\h1.5示例介紹\h數(shù)學(xué)\h示意圖\h代碼\h1.6多輸入函數(shù)\h數(shù)學(xué)\h示意圖\h代碼\h1.7多輸入函數(shù)的導(dǎo)數(shù)\h數(shù)學(xué)\h示意圖\h代碼\h1.8多向量輸入函數(shù)\h數(shù)學(xué)\h1.9基于已有特征創(chuàng)建新特征\h數(shù)學(xué)\h示意圖\h代碼\h1.10多向量輸入函數(shù)的導(dǎo)數(shù)\h數(shù)學(xué)\h示意圖\h代碼\h1.11向量函數(shù)及其導(dǎo)數(shù):再進(jìn)一步\h數(shù)學(xué)\h示意圖\h代碼\h向量函數(shù)及其導(dǎo)數(shù):后向傳遞\h1.12包含兩個(gè)二維矩陣輸入的計(jì)算圖\h數(shù)學(xué)\h示意圖\h代碼\h1.13有趣的部分:后向傳遞\h數(shù)學(xué)\h示意圖\h代碼\h1.14小結(jié)\h第2章基本原理\h2.1監(jiān)督學(xué)習(xí)概述\h2.2監(jiān)督學(xué)習(xí)模型\h2.3線性回歸\h2.3.1線性回歸:示意圖\h2.3.2線性回歸:更有用的示意圖和數(shù)學(xué)\h2.3.3加入截距項(xiàng)\h2.3.4線性回歸:代碼\h2.4訓(xùn)練模型\h2.4.1計(jì)算梯度:示意圖\h2.4.2計(jì)算梯度:數(shù)學(xué)和一些代碼\h2.4.3計(jì)算梯度:完整的代碼\h2.4.4使用梯度訓(xùn)練模型\h2.5評(píng)估模型:訓(xùn)練集與測(cè)試集\h2.6評(píng)估模型:代碼\h分析最重要的特征\h2.7從零開(kāi)始構(gòu)建神經(jīng)網(wǎng)絡(luò)\h2.7.1步驟1:一系列線性回歸\h2.7.2步驟2:一個(gè)非線性函數(shù)\h2.7.3步驟3:另一個(gè)線性回歸\h2.7.4示意圖\h2.7.5代碼\h2.7.6神經(jīng)網(wǎng)絡(luò):后向傳遞\h2.8訓(xùn)練和評(píng)估第一個(gè)神經(jīng)網(wǎng)絡(luò)\h發(fā)生這種情況的兩個(gè)原因\h2.9小結(jié)\h第3章從零開(kāi)始深度學(xué)習(xí)\h3.1定義深度學(xué)習(xí)\h3.2神經(jīng)網(wǎng)絡(luò)的構(gòu)成要素:運(yùn)算\h3.2.1示意圖\h3.2.2代碼\h3.3神經(jīng)網(wǎng)絡(luò)的構(gòu)成要素:層\h示意圖\h3.4在構(gòu)成要素之上構(gòu)建新的要素\h3.4.1層的藍(lán)圖\h3.4.2稠密層\h3.5NeuralNetwork類和其他類\h3.5.1示意圖\h3.5.2代碼\h3.5.3Loss類\h3.6從零開(kāi)始構(gòu)建深度學(xué)習(xí)模型\h3.6.1實(shí)現(xiàn)批量訓(xùn)練\h3.6.2NeuralNetwork:代碼\h3.7優(yōu)化器和訓(xùn)練器\h3.7.1優(yōu)化器\h3.7.2訓(xùn)練器\h3.8整合\h第一個(gè)深度學(xué)習(xí)模型\h3.9小結(jié)與展望\h第4章擴(kuò)展\h4.1關(guān)于神經(jīng)網(wǎng)絡(luò)的一些直覺(jué)\h4.2softmax交叉熵?fù)p失函數(shù)\h4.2.1組件1:softmax函數(shù)\h4.2.2組件2:交叉熵?fù)p失\h4.2.3關(guān)于激活函數(shù)的注意事項(xiàng)\h4.3實(shí)驗(yàn)\h4.3.1數(shù)據(jù)預(yù)處理\h4.3.2模型\h4.3.3實(shí)驗(yàn):softmax交叉熵?fù)p失函數(shù)\h4.4動(dòng)量\h4.4.1理解動(dòng)量\h4.4.2在Optimizer類中實(shí)現(xiàn)動(dòng)量\h4.4.3實(shí)驗(yàn):帶有動(dòng)量的隨機(jī)梯度下降\h4.5學(xué)習(xí)率衰減\h4.5.1學(xué)習(xí)率衰減的類型\h4.5.2實(shí)驗(yàn):學(xué)習(xí)率衰減\h4.6權(quán)重初始化\h4.6.1數(shù)學(xué)和代碼\h4.6.2實(shí)驗(yàn):權(quán)重初始化\h4.7dropout\h4.7.1定義\h4.7.2實(shí)現(xiàn)\h4.7.3實(shí)驗(yàn):dropout\h4.8小結(jié)\h第5章CNN\h5.1神經(jīng)網(wǎng)絡(luò)與表征學(xué)習(xí)\h5.1.1針對(duì)圖像數(shù)據(jù)的不同架構(gòu)\h5.1.2卷積運(yùn)算\h5.1.3多通道卷積運(yùn)算\h5.2卷積層\h5.2.1實(shí)現(xiàn)意義\h5.2.2卷積層與全連接層的區(qū)別\h5.2.3利用卷積層進(jìn)行預(yù)測(cè):Flatten層\h5.2.4池化層\h5.3實(shí)現(xiàn)多通道卷積運(yùn)算\h5.3.1前向傳遞\h5.3.2后向傳遞\h5.3.3批處理\h5.3.4二維卷積\h5.3.5最后一個(gè)元素:通道\h5.4使用多通道卷積運(yùn)算訓(xùn)練CNN\h5.4.1Flatten運(yùn)算\h5.4.2完整的Conv2D層\h5.4.3實(shí)驗(yàn)\h5.5小結(jié)\h第6章RNN\h6.1關(guān)鍵限制:處理分支\h6.2自動(dòng)微分\h編碼梯度累積\h6.3RNN的動(dòng)機(jī)\h6.4RNN簡(jiǎn)介\h6.4.1RNN的第一個(gè)類:RNNLayer\h6.4.2RNN的第二個(gè)類:RNNNode\h6.4.3整合RNNNode類和RNNLayer類\h6.4.4后向傳遞\h6.5RNN:代碼\h6.5.1RNNLayer類\h6.5.2RNNNode類的基本元素\h6.5.3vanillaRNNNode類\h6.5.4vanillaRNNNode類的局限性\h6.5.5GRUNode類\h6.5.6LSTMNode類\h6.5.7基于字符級(jí)RNN語(yǔ)言模型的數(shù)據(jù)表示\h6.5.8其他語(yǔ)言建模任務(wù)\h6.5.9組合RNNLayer類的變體\h6.5.10將全部?jī)?nèi)容整合在一起\h6.6小結(jié)\h第7章PyTorch\h7.1PyTorchTensor\h7.2使用PyTorch進(jìn)行深度學(xué)習(xí)\h7.2.1PyTorch元素:Model類及其Layer類\h7.2.2使用PyTorch實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)基本要素:DenseLayer類\h7.2.3示例:基于PyTorch的波士頓房?jī)r(jià)模型\h7.2.4PyTorch元素:Optimizer類和Loss類\h7.2.5PyTorch元素:Trainer類\h7.2.6PyTorch優(yōu)化學(xué)習(xí)技術(shù)\h7.3PyTorch中的CNN\hDataLoader類和transforms模塊\h7.4PyTorch中的LSTM\h7.5后記:通過(guò)自編碼器進(jìn)行無(wú)監(jiān)督學(xué)習(xí)\h7.5.1表征學(xué)習(xí)\h7.5.2應(yīng)對(duì)無(wú)標(biāo)簽場(chǎng)景的方法\h7.5.3在PyTorch中實(shí)現(xiàn)自編碼器\h7.5.4更強(qiáng)大的無(wú)監(jiān)督學(xué)習(xí)測(cè)試及解決方案\h7.6小結(jié)\h附錄深入探討\h矩陣鏈?zhǔn)椒▌t\h關(guān)于偏差項(xiàng)的損失梯度\h通過(guò)矩陣乘法進(jìn)行卷積第1章基本概念不要記住這些公式。如果能理解這些概念,那么你就可以自己發(fā)明符號(hào)?!狫ohnCochrane,InvestmentsNotes本章旨在解釋一些基本的思維模型,這些模型對(duì)于理解神經(jīng)網(wǎng)絡(luò)的工作原理至關(guān)重要。具體地說(shuō),本章將介紹嵌套數(shù)學(xué)函數(shù)(nestedmathematicalfunction)及其導(dǎo)數(shù)(derivative)。我們將從最簡(jiǎn)單的構(gòu)成要素開(kāi)始逐步研究,證明可以構(gòu)建由函數(shù)鏈組成的復(fù)雜函數(shù)。即使其中一個(gè)函數(shù)是接受多個(gè)輸入的矩陣乘法,也可以計(jì)算函數(shù)輸出相對(duì)于其輸入的導(dǎo)數(shù)。另外,理解該過(guò)程對(duì)于理解神經(jīng)網(wǎng)絡(luò)至關(guān)重要,從第2章開(kāi)始將涉及神經(jīng)網(wǎng)絡(luò)的內(nèi)容。當(dāng)圍繞神經(jīng)網(wǎng)絡(luò)的基本構(gòu)成要素進(jìn)行研究時(shí),我們將從3個(gè)維度系統(tǒng)地描述所引入的每個(gè)概念。以一個(gè)或多個(gè)方程式的形式所表示的數(shù)學(xué)。解釋過(guò)程的示意圖,類似于在參加編碼面試時(shí)畫(huà)在白板上的圖表。包含盡可能少的特殊語(yǔ)法的代碼(Python是一個(gè)理想選擇)。如前言所述,理解神經(jīng)網(wǎng)絡(luò)的一大挑戰(zhàn)是它需要多個(gè)思維模型。你在本章中就可以體會(huì)到這一點(diǎn):對(duì)將討論的概念來(lái)說(shuō),以上3個(gè)維度分別代表不同的基本特征,只有把它們結(jié)合在一起,才能對(duì)一些概念形成完整的認(rèn)識(shí),比如嵌套數(shù)學(xué)函數(shù)如何以及為何起作用。注意,要完整地解釋神經(jīng)網(wǎng)絡(luò)的構(gòu)成要素,以上3個(gè)維度缺一不可。明白了這一點(diǎn),接下來(lái)就可以開(kāi)始本書(shū)的學(xué)習(xí)了。我將從一些非常簡(jiǎn)單的構(gòu)成要素開(kāi)始講解,介紹如何基于這3個(gè)維度來(lái)理解不同的概念。第一個(gè)構(gòu)成要素是一個(gè)簡(jiǎn)單但又至關(guān)重要的概念:函數(shù)。1.1函數(shù)什么是函數(shù)?如何描述函數(shù)?與神經(jīng)網(wǎng)絡(luò)一樣,函數(shù)也可以用多種方法描述,但沒(méi)有一種方法能完整地描繪它。與其嘗試給出簡(jiǎn)單的一句話描述,不如像盲人摸象那樣,依次根據(jù)每個(gè)維度來(lái)了解函數(shù)。數(shù)學(xué)下面是兩個(gè)用數(shù)學(xué)符號(hào)描述的函數(shù)示例。以上有兩個(gè)函數(shù),分別為和,當(dāng)輸入數(shù)字時(shí),第一個(gè)函數(shù)將其轉(zhuǎn)換為,第二個(gè)函數(shù)則將其轉(zhuǎn)換為。示意圖下面是一種描繪函數(shù)的方法。繪制一個(gè)平面(其中表示橫軸,表示縱軸)。繪制一些點(diǎn),其中,點(diǎn)的坐標(biāo)是函數(shù)在某個(gè)范圍內(nèi)的輸入(通常是等距的),坐標(biāo)則是該范圍內(nèi)函數(shù)的輸出。連接所繪制的點(diǎn)。這種利用坐標(biāo)的方法是法國(guó)哲學(xué)家勒內(nèi)?笛卡兒發(fā)明的,它在許多數(shù)學(xué)領(lǐng)域非常有用,特別是微積分領(lǐng)域。圖1-1展示了以上兩個(gè)函數(shù)的示意圖。圖1-1:兩個(gè)連續(xù)、基本可微的函數(shù)然而,還有另一種描繪函數(shù)的方法,這種方法在學(xué)習(xí)微積分時(shí)并沒(méi)有那么有用,但是對(duì)于思考深度學(xué)習(xí)模型非常有幫助。可以把函數(shù)看作接收數(shù)字(輸入)并生成數(shù)字(輸出)的盒子,就像小型工廠一樣,它們對(duì)輸入的處理有自己的內(nèi)部規(guī)則。圖1-2通過(guò)一般規(guī)則和具體的輸入描繪了以上兩個(gè)函數(shù)。圖1-2:另一種描繪函數(shù)的方法代碼最后,可以使用代碼描述這兩個(gè)函數(shù)。在開(kāi)始之前,先介紹一下NumPy這個(gè)Python庫(kù),下面會(huì)基于該庫(kù)編寫(xiě)函數(shù)。NumPy庫(kù)NumPy是一個(gè)廣泛使用的Python庫(kù),用于快速數(shù)值計(jì)算,其內(nèi)部大部分使用C語(yǔ)言編寫(xiě)。簡(jiǎn)單地說(shuō),在神經(jīng)網(wǎng)絡(luò)中處理的數(shù)據(jù)將始終保存在一個(gè)多維數(shù)組中,主要是一維數(shù)組、二維數(shù)組、三維數(shù)組或四維數(shù)組,尤其以二維數(shù)組或三維數(shù)組居多。NumPy庫(kù)中的ndarray類能夠讓我們以直觀且快速的方式計(jì)算這些數(shù)組。舉一個(gè)最簡(jiǎn)單的例子,如果將數(shù)據(jù)存儲(chǔ)在Python列表或列表的嵌套列表中,則無(wú)法使用常規(guī)語(yǔ)法實(shí)現(xiàn)數(shù)據(jù)對(duì)位相加或相乘,但ndarray類可以實(shí)現(xiàn):print("Pythonlistoperations:")a=[1,2,3]b=[4,5,6]print("a+b:",a+b)try:print(a*b)exceptTypeError:print("a*bhasnomeaningforPythonlists")print()print("numpyarrayoperations:")a=np.array([1,2,3])b=np.array([4,5,6])print("a+b:",a+b)print("a*b:",a*b)Pythonlistoperations:a+b:[1,2,3,4,5,6]a*bhasnomeaningforPythonlistsnumpyarrayoperations:a+b:[579]a*b:[41018]ndarray還具備維數(shù)組所具有的多個(gè)特性:每個(gè)ndarray都具有個(gè)軸(從0開(kāi)始索引),第一個(gè)軸為軸0,第二個(gè)軸為軸1,以此類推。另外,由于二維ndarray較為常見(jiàn),因此可以將軸0視為行,將軸1視為列,如圖1-3所示。圖1-3:一個(gè)二維ndarray,其中軸0為行,軸1為列NumPy庫(kù)的ndarray類還支持以直觀的方式對(duì)這些軸應(yīng)用函數(shù)。例如,沿軸0(二維數(shù)組的行)求和本質(zhì)上就是沿該軸“折疊數(shù)組”,返回的數(shù)組比原始數(shù)組少一個(gè)維度。對(duì)二維數(shù)組來(lái)說(shuō),這相當(dāng)于對(duì)每一列進(jìn)行求和:print('a:')print(a)print('a.sum(axis=0):',a.sum(axis=0))print('a.sum(axis=1):',a.sum(axis=1))a:[[12][34]]a.sum(axis=0):[46]a.sum(axis=1):[37]ndarray類支持將一維數(shù)組添加到最后一個(gè)軸上。對(duì)一個(gè)行列的二維數(shù)組a而言,這意味著可以添加長(zhǎng)度為的一維數(shù)組b。NumPy將以直觀的方式進(jìn)行加法運(yùn)算,并將元素添加到a的每一行中1。a=np.array([[1,2,3],[4,5,6]])b=np.array([10,20,30])print("a+b:\n",a+b)a+b:[[112233][142536]]類型檢查函數(shù)如前所述,本書(shū)代碼的主要目標(biāo)是確保概念描述的準(zhǔn)確性和清晰性。隨著本書(shū)內(nèi)容的展開(kāi),這將變得更具挑戰(zhàn)性,后文涉及編寫(xiě)帶有許多參數(shù)的函數(shù),這些參數(shù)是復(fù)雜類的一部分。為了解決這個(gè)問(wèn)題,本書(shū)將在整個(gè)過(guò)程中使用帶有類型簽名的函數(shù)。例如,在第3章中,我們將使用如下方式初始化神經(jīng)網(wǎng)絡(luò):def__init__(self,layers:List[Layer],loss:Loss,learning_rate:float=0.01)->None:僅通過(guò)類型簽名,就能了解該類的用途。與此相對(duì),考慮以下可用于定義運(yùn)算的類型簽名:defoperation(x1,x2):這個(gè)類型簽名本身并沒(méi)有給出任何提示。只有打印出每個(gè)對(duì)象的類型,查看對(duì)每個(gè)對(duì)象執(zhí)行的運(yùn)算,或者根據(jù)名稱x1和x2進(jìn)行猜測(cè),才能夠理解該函數(shù)的功能。這里可以改為定義具有類型簽名的函數(shù),如下所示:defoperation(x1:ndarray,x2:ndarray)->ndarray:很明顯,這是接受兩個(gè)ndarray的函數(shù),可以用某種方式將它們組合在一起,并輸出該組合的結(jié)果。由于它們讀起來(lái)更為清楚,因此本書(shū)將使用經(jīng)過(guò)類型檢查的函數(shù)。NumPy庫(kù)中的基礎(chǔ)函數(shù)了解前面的內(nèi)容后,現(xiàn)在來(lái)編寫(xiě)之前通過(guò)NumPy庫(kù)定義的函數(shù):defsquare(x:ndarray)->ndarray:'''將輸入ndarray中的每個(gè)元素進(jìn)行平方運(yùn)算。'''returnnp.power(x,2)defleaky_relu(x:ndarray)->ndarray:'''將LeakyReLU函數(shù)應(yīng)用于ndarray中的每個(gè)元素。'''returnnp.maximum(0.2*x,x)NumPy庫(kù)有一個(gè)奇怪的地方,那就是可以通過(guò)使用np.function_name(ndarray)或ndarray.function_name將許多函數(shù)應(yīng)用于ndarray。例如,前面的ReLU函數(shù)可以編寫(xiě)成x.clip(min=0)。本書(shū)將盡量保持一致,在整個(gè)過(guò)程中遵循np.function_name(ndarray)約定,尤其會(huì)避免使用ndarray.T之類的技巧來(lái)轉(zhuǎn)置二維ndarray,而會(huì)使用np.transpose(ndarray,(1,0))。如果能通過(guò)數(shù)學(xué)、示意圖和代碼這3個(gè)維度來(lái)表達(dá)相同的基本概念,就說(shuō)明你已經(jīng)初步擁有了真正理解深度學(xué)習(xí)所需的靈活思維。1這樣一來(lái),后續(xù)便可以輕松地向矩陣乘法添加偏差。1.2導(dǎo)數(shù)像函數(shù)一樣,導(dǎo)數(shù)也是深度學(xué)習(xí)的一個(gè)非常重要的概念,大多數(shù)人可能很熟悉。同樣,導(dǎo)數(shù)也可以用多種方式進(jìn)行描述??傮w來(lái)說(shuō),函數(shù)在某一點(diǎn)上的導(dǎo)數(shù),可以簡(jiǎn)單地看作函數(shù)輸出相對(duì)于該點(diǎn)輸入的“變化率”。接下來(lái)基于前面介紹的3個(gè)維度來(lái)了解導(dǎo)數(shù),從而更好地理解導(dǎo)數(shù)的原理。數(shù)學(xué)首先來(lái)從數(shù)學(xué)角度精確地定義導(dǎo)數(shù):可以使用一個(gè)數(shù)字來(lái)描述極限,即當(dāng)改變某個(gè)特定的輸入值時(shí),函數(shù)輸出的變化:通過(guò)為設(shè)置非常小的值(例如0.001),可以在數(shù)值上近似此極限。因此,可以將導(dǎo)數(shù)計(jì)算為:雖然近似準(zhǔn)確,但這只是完整導(dǎo)數(shù)思維模型的一部分,下面來(lái)從示意圖的維度認(rèn)識(shí)導(dǎo)數(shù)。示意圖采用一種熟悉的方式:在含有函數(shù)圖像的笛卡兒坐標(biāo)系上,簡(jiǎn)單地畫(huà)出該函數(shù)的一條切線,則函數(shù)在點(diǎn)處的導(dǎo)數(shù)就是該線在點(diǎn)處的斜率。正如本節(jié)中的數(shù)學(xué)描述一樣,這里也可以通過(guò)兩種方式實(shí)際計(jì)算這條線的斜率。第一種方式是使用微積分來(lái)實(shí)際計(jì)算極限,第二種方式是在處和處取連線的斜率。后者如圖1-4所示,如果學(xué)過(guò)微積分,應(yīng)該會(huì)很熟悉。圖1-4:導(dǎo)數(shù)即為斜率正如1.1節(jié)所述,可以把函數(shù)想象成小型工廠?,F(xiàn)在想象那些工廠的輸入通過(guò)一根線連接到輸出。求解導(dǎo)數(shù)相當(dāng)于回答這樣一個(gè)問(wèn)題:如果將函數(shù)的輸入拉高一點(diǎn),或者如果函數(shù)在處可能不對(duì)稱,因此把拉低一點(diǎn),那么根據(jù)工廠的內(nèi)部運(yùn)作機(jī)制,輸出量將以這個(gè)小數(shù)值的多少倍進(jìn)行變化呢?如圖1-5所示。圖1-5:導(dǎo)數(shù)可視化的另一種方法對(duì)理解深度學(xué)習(xí)而言,第二種表示形式比第一種更為重要。代碼可以通過(guò)編碼來(lái)求解前面看到的導(dǎo)數(shù)的近似值:fromtypingimportCallabledefderiv(func:Callable[[ndarray],ndarray],input_:ndarray,delta:float=0.001)->ndarray:'''計(jì)算函數(shù)func在input_數(shù)組中每個(gè)元素處的導(dǎo)數(shù)。'''return(func(input_+delta)-func(input_-delta))/(2*delta)當(dāng)說(shuō)是(隨機(jī)選的字母)的函數(shù)時(shí),其實(shí)是指存在某個(gè)函數(shù),使得?;蛘哒f(shuō),有一個(gè)函數(shù),它接受對(duì)象并產(chǎn)生對(duì)象。也可以說(shuō),是函數(shù)應(yīng)用于時(shí)產(chǎn)生的任意函數(shù)值:可以將其編碼為下面這種形式。deff(input_:ndarray)->ndarray:#一些轉(zhuǎn)換returnoutputP=f(E)1.3嵌套函數(shù)現(xiàn)在來(lái)介紹一個(gè)概念,該概念將成為理解神經(jīng)網(wǎng)絡(luò)的基礎(chǔ):函數(shù)可以被“嵌套”,從而形成“復(fù)合”函數(shù)?!扒短住钡降资鞘裁匆馑寄??假設(shè)有兩個(gè)函數(shù),按照數(shù)學(xué)慣例,它們分別為和,其中一個(gè)函數(shù)的輸出將成為另一個(gè)函數(shù)的輸入,這樣就可以“把它們串在一起”。數(shù)學(xué)嵌套函數(shù)在數(shù)學(xué)上表示為:這不太直觀,因?yàn)橛袀€(gè)奇怪的地方:嵌套函數(shù)是“從外而內(nèi)”讀取的,而而運(yùn)算實(shí)際上是“從內(nèi)而外”執(zhí)行的。例如,盡管讀作“接受接受對(duì)象而產(chǎn)生對(duì)象”,但其真正含義是“首先將應(yīng)用于,然后將應(yīng)用于該結(jié)果,最終得到對(duì)象”。示意圖要表示嵌套函數(shù),最直觀的方法是使用小型工廠表示法,又稱盒子表示法。如圖1-6所示,輸入進(jìn)入第一個(gè)函數(shù),轉(zhuǎn)換之后進(jìn)行輸出。然后,這個(gè)輸出進(jìn)入第二個(gè)函數(shù)并再次轉(zhuǎn)換,得到最終輸出。圖1-6:直觀地表示嵌套函數(shù)代碼前面已經(jīng)介紹了兩個(gè)維度,接下來(lái)從代碼維度來(lái)認(rèn)識(shí)嵌套函數(shù)。首先,為嵌套函數(shù)定義一個(gè)數(shù)據(jù)類型:fromtypingimportList#函數(shù)接受一個(gè)ndarray作為參數(shù)并生成一個(gè)ndarrayArray_Function=Callable[[ndarray],ndarray]#鏈?zhǔn)且粋€(gè)函數(shù)列表Chain=List[Array_Function]然后,定義數(shù)據(jù)如何經(jīng)過(guò)特定長(zhǎng)度的鏈,以長(zhǎng)度等于2為例,代碼如下所示。defchain_length_2(chain:Chain,a:ndarray)->ndarray:'''在一行代碼中計(jì)算“鏈”中的兩個(gè)函數(shù)。'''assertlen(chain)==2,\"Lengthofinput'chain'shouldbe2"f1=chain[0]f2=chain[1]returnf2(f1(x))另一種示意圖使用盒子表示法描述嵌套函數(shù)表明,該復(fù)合函數(shù)實(shí)際上就只是一個(gè)函數(shù)。因此,可以將該函數(shù)簡(jiǎn)單地表示為,如圖1-7所示。圖1-7:嵌套函數(shù)的另一種表示法此外,在微積分中有一個(gè)定理,那就是由“基本可微”的函數(shù)組成的復(fù)合函數(shù)本身就是基本可微的!因此,可以將視為另一個(gè)可計(jì)算導(dǎo)數(shù)的函數(shù)。計(jì)算復(fù)合函數(shù)的導(dǎo)數(shù)對(duì)于訓(xùn)練深度學(xué)習(xí)模型至關(guān)重要。但是,現(xiàn)在需要一個(gè)公式,以便根據(jù)各個(gè)組成函數(shù)的導(dǎo)數(shù)來(lái)計(jì)算此復(fù)合函數(shù)的導(dǎo)數(shù)。這就是接下來(lái)要介紹的內(nèi)容。1.4鏈?zhǔn)椒▌t鏈?zhǔn)椒▌t是一個(gè)數(shù)學(xué)定理,用于計(jì)算復(fù)合函數(shù)的導(dǎo)數(shù)。從數(shù)學(xué)上講,深度學(xué)習(xí)模型就是復(fù)合函數(shù)。因此,理解其導(dǎo)數(shù)的計(jì)算過(guò)程對(duì)于訓(xùn)練它們非常重要,接下來(lái)的幾章將詳述這一點(diǎn)。數(shù)學(xué)在數(shù)學(xué)上,這個(gè)定理看起來(lái)較為復(fù)雜,對(duì)于給定的值,我們有:其中只是一個(gè)偽變量,代表函數(shù)的輸入。當(dāng)描述具有一個(gè)輸入和一個(gè)輸出的函數(shù)的導(dǎo)數(shù)時(shí),可以將代表該函數(shù)導(dǎo)數(shù)的函數(shù)表示為。可以用其他偽變量替代,這樣做并不會(huì)對(duì)結(jié)果造成影響,就像和表示同一個(gè)意思一樣。稍后,我們將處理包含多個(gè)輸入(例如和)的函數(shù)。一旦碰到這種情況,區(qū)分和之間的不同含義就是有意義的。這就是為什么在前面的公式中,我們?cè)谒械膶?dǎo)數(shù)中將放在了底部:和都是接受一個(gè)輸入并產(chǎn)生一個(gè)輸出的函數(shù),在這些情況下(有一個(gè)輸入和一個(gè)輸出的函數(shù)),我們將在導(dǎo)數(shù)符號(hào)中使用。示意圖對(duì)理解鏈?zhǔn)椒▌t而言,本節(jié)中的數(shù)學(xué)公式不太直觀。對(duì)此,盒子表示法會(huì)更有幫助。下面通過(guò)簡(jiǎn)單的示例來(lái)解釋導(dǎo)數(shù)“應(yīng)該”是什么,如圖1-8所示。圖1-8:鏈?zhǔn)椒▌t示意圖直觀地說(shuō),使用圖1-8中的示意圖,復(fù)合函數(shù)的導(dǎo)數(shù)應(yīng)該是其組成函數(shù)的導(dǎo)數(shù)的乘積。假設(shè)在第一個(gè)函數(shù)中輸入5,并且當(dāng)時(shí),第一個(gè)函數(shù)的導(dǎo)數(shù)是3,那么用公式表示就是。然后取第一個(gè)盒子中的函數(shù)值,假設(shè)它是1,即,再計(jì)算第二個(gè)函數(shù)在這個(gè)值上的導(dǎo)數(shù),即計(jì)算。如圖1-8所示,這個(gè)值是-2。想象這些函數(shù)實(shí)際上是串在一起的,如果將盒子2對(duì)應(yīng)的輸入更改1單位會(huì)導(dǎo)致盒子2的輸出產(chǎn)生-2單位的變化,將盒子2對(duì)應(yīng)的輸入更改3單位則會(huì)導(dǎo)致盒子2的輸出變化-6(-2×3)單位。這就是為什么在鏈?zhǔn)椒▌t的公式中,最終結(jié)果是一個(gè)乘積:。利用數(shù)學(xué)和示意圖這兩個(gè)維度,我們可以通過(guò)使用鏈?zhǔn)椒▌t來(lái)推斷嵌套函數(shù)的輸出相對(duì)于其輸入的導(dǎo)數(shù)值。那么計(jì)算這個(gè)導(dǎo)數(shù)的代碼如何編寫(xiě)呢?代碼下面對(duì)此進(jìn)行編碼,并證明按照這種方式計(jì)算的導(dǎo)數(shù)會(huì)產(chǎn)生“看起來(lái)正確”的結(jié)果。這里將使用square函數(shù)2以及sigmoid函數(shù),后者在深度學(xué)習(xí)中非常重要:2參見(jiàn)1.1節(jié)的“NumPy庫(kù)中的基礎(chǔ)函數(shù)”部分。defsigmoid(x:ndarray)->ndarray:'''將sigmoid函數(shù)應(yīng)用于輸入ndarray中的每個(gè)元素。'''return1/(1+np.exp(-x))現(xiàn)在編寫(xiě)鏈?zhǔn)椒▌t:defchain_deriv_2(chain:Chain,input_range:ndarray)->ndarray:'''使用鏈?zhǔn)椒▌t計(jì)算兩個(gè)嵌套函數(shù)的導(dǎo)數(shù):(f2f1(x))′=f2′(f1(x))*f1′(x)。'''assertlen(chain)==2,\"Thisfunctionrequires'Chain'objectsoflength2"assertinput_range.ndim==1,\"Functionrequiresa1dimensionalndarrayasinput_range"f1=chain[0]f2=chain[1]#df1/dxf1_of_x=f1(input_range)#df1/dudf1dx=deriv(f1,input_range)#df2/du(f1(x))df2du=deriv(f2,f1(input_range))#在每一點(diǎn)上將這些量相乘returndf1dx*df2du圖1-9繪制了結(jié)果,并展示了鏈?zhǔn)椒▌t的有效性:PLOT_RANGE=np.arange(-3,3,0.01)chain_1=[square,sigmoid]chain_2=[sigmoid,square]plot_chain(chain_1,PLOT_RANGE)plot_chain_deriv(chain_1,PLOT_RANGE)plot_chain(chain_2,PLOT_RANGE)plot_chain_deriv(chain_2,PLOT_RANGE)圖1-9:鏈?zhǔn)椒▌t的有效性33請(qǐng)?jiān)趫D靈社區(qū)本書(shū)主頁(yè)上查看該圖的彩色版本。——編者注鏈?zhǔn)椒▌t似乎起作用了。當(dāng)函數(shù)向上傾斜時(shí),導(dǎo)數(shù)為正;當(dāng)函數(shù)向下傾斜時(shí),導(dǎo)數(shù)為負(fù);當(dāng)函數(shù)未發(fā)生傾斜時(shí),導(dǎo)數(shù)為零。因此,實(shí)際上只要各個(gè)函數(shù)本身是基本可微的,就可以通過(guò)數(shù)學(xué)公式和代碼計(jì)算嵌套函數(shù)(或復(fù)合函數(shù))的導(dǎo)數(shù),例如。從數(shù)學(xué)上講,深度學(xué)習(xí)模型是這些基本可微函數(shù)的長(zhǎng)鏈。建議花時(shí)間手動(dòng)執(zhí)行稍長(zhǎng)一點(diǎn)的詳細(xì)示例(參見(jiàn)1.5節(jié)),這樣有助于直觀地理解鏈?zhǔn)椒▌t,包括其運(yùn)行方式以及在更復(fù)雜的模型中的應(yīng)用。1.5示例介紹仔細(xì)研究一條稍長(zhǎng)的鏈,假設(shè)有3個(gè)基本可微的函數(shù),分別是、和,如何計(jì)算它們的導(dǎo)數(shù)呢?從前面提到的微積分定理可以知道,由任意有限個(gè)“基本可微”函數(shù)組成的復(fù)合函數(shù)都是基本可微的。因此,計(jì)算導(dǎo)數(shù)應(yīng)該不難實(shí)現(xiàn)。數(shù)學(xué)從數(shù)學(xué)上講,對(duì)于包含3個(gè)基本可微的函數(shù)的復(fù)合函數(shù),其導(dǎo)數(shù)的計(jì)算公式如下:僅僅看公式不是很直觀,但相比1.4節(jié)介紹的適用于長(zhǎng)度為2的鏈,兩者的基本邏輯是一樣的。示意圖要理解以上公式,最為直觀的方法就是通過(guò)盒子示意圖,如圖1-10所示。圖1-10:通過(guò)盒子表示法理解如何計(jì)算3個(gè)嵌套函數(shù)的導(dǎo)數(shù)使用與1.4節(jié)中類似的邏輯:假設(shè)的輸入(稱為)通過(guò)一根線連接到輸出(稱為),則將改變較小量Δ,將導(dǎo)致變化Δ的倍,進(jìn)而導(dǎo)致鏈中的下一步變化Δ的倍,以此類推,直到最終表示變化的完整公式等于前一個(gè)鏈?zhǔn)椒▌t乘以Δ。請(qǐng)仔細(xì)思考上述解釋和圖1-10中的示意圖,無(wú)須花費(fèi)太長(zhǎng)時(shí)間。在編寫(xiě)代碼時(shí),這一點(diǎn)會(huì)更容易理解。代碼在給定組合函數(shù)的情況下,如何將本節(jié)中的公式轉(zhuǎn)換為計(jì)算導(dǎo)數(shù)的代碼呢?我們可以在這個(gè)簡(jiǎn)單的示例中看到神經(jīng)網(wǎng)絡(luò)前向傳遞和后向傳遞的雛形:defchain_deriv_3(chain:Chain,input_range:ndarray)->ndarray:'''使用鏈?zhǔn)椒▌t來(lái)計(jì)算3個(gè)嵌套函數(shù)的導(dǎo)數(shù):(f3(f2(f1)))'=f3'(f2(f1(x)))*f2'(f1(x))*f1'(x)。'''assertlen(chain)==3,\"Thisfunctionrequires'Chain'objectstohavelength3"f1=chain[0]f2=chain[1]f3=chain[2]#f1(x)f1_of_x=f1(input_range)#f2(f1(x))f2_of_x=f2(f1_of_x)#df3dudf3du=deriv(f3,f2_of_x)#df2dudf2du=deriv(f2,f1_of_x)#df1dxdf1dx=deriv(f1,input_range)#在每一點(diǎn)上將這些量相乘returndf1dx*df2du*df3du注意,在計(jì)算這個(gè)嵌套函數(shù)的鏈?zhǔn)椒▌t時(shí),這里對(duì)它進(jìn)行了兩次“傳遞”?!跋蚯啊眰鬟f它,計(jì)算出f1_of_x和f2_of_x,這個(gè)過(guò)程可以稱作(或視作)“前向傳遞”?!跋蚝蟆蓖ㄟ^(guò)函數(shù),使用在前向傳遞中計(jì)算出的量來(lái)計(jì)算構(gòu)成導(dǎo)數(shù)的量。最后,將這3個(gè)量相乘,得到導(dǎo)數(shù)。接下來(lái)使用前面定義的3個(gè)簡(jiǎn)單函數(shù)來(lái)說(shuō)明上面的方法是可行的,這3個(gè)函數(shù)分別為sigmoid、square和leaky_relu。PLOT_RANGE=np.range(-3,3,0.01)plot_chain([leaky_relu,sigmoid,square],PLOT_RANGE)plot_chain_deriv([leaky_relu,sigmoid,square],PLOT_RANGE)圖1-11顯示了結(jié)果。圖1-11:即使使用三重嵌套函數(shù),鏈?zhǔn)椒▌t也有效44請(qǐng)?jiān)趫D靈社區(qū)本書(shū)主頁(yè)上查看該圖的彩色版本。——編者注再次將導(dǎo)數(shù)圖與原始函數(shù)的斜率進(jìn)行比較,可以看到鏈?zhǔn)椒▌t確實(shí)正確地計(jì)算了導(dǎo)數(shù)?;谝陨侠斫?,現(xiàn)在再來(lái)看一下具有多個(gè)輸入的復(fù)合函數(shù),這類函數(shù)遵循已經(jīng)建立的相同原理,最終將更適用于深度學(xué)習(xí)。1.6多輸入函數(shù)至此,我們已經(jīng)從概念上理解了如何將函數(shù)串在一起形成復(fù)合函數(shù),并且知道了如何將這些函數(shù)表示為一系列輸入或輸出的盒子,以及如何計(jì)算這些函數(shù)的導(dǎo)數(shù)。一方面通過(guò)數(shù)學(xué)公式理解了導(dǎo)數(shù),另一方面通過(guò)“向前”組件和“向后”組件,根據(jù)傳遞過(guò)程中計(jì)算出的量理解了導(dǎo)數(shù)。在深度學(xué)習(xí)中處理的函數(shù)往往并非只有一個(gè)輸入。相反,它們有多個(gè)輸入,在某些步驟中,這些輸入以相加、相乘或其他方式組合在一起。正如下面介紹的,我們同樣可以計(jì)算這些函數(shù)的輸出相對(duì)于其輸入的導(dǎo)數(shù)?,F(xiàn)在假設(shè)存在一個(gè)有多個(gè)輸入的簡(jiǎn)單場(chǎng)景,其中兩個(gè)輸入相加,然后再輸入給另一個(gè)函數(shù)。數(shù)學(xué)在這個(gè)例子中,從數(shù)學(xué)意義上開(kāi)始討論實(shí)際上很有幫助。如果輸入是和,那么可以認(rèn)為函數(shù)分兩步進(jìn)行。在步驟1中,和傳到了將它們相加的函數(shù)。將該函數(shù)表示為(整個(gè)過(guò)程使用希臘字母表示函數(shù)名),然后將函數(shù)的輸出表示為。從形式上看,這樣很容易表示:步驟2是將傳給某個(gè)函數(shù)(可以是任意連續(xù)函數(shù),例如sigmoid函數(shù)或square函數(shù),甚至是名稱不以開(kāi)頭的函數(shù))。將此函數(shù)的輸出表示為,也就是:將整個(gè)函數(shù)用表示,可以寫(xiě)作:從數(shù)學(xué)意義上理解,這樣更為簡(jiǎn)潔,但這實(shí)際上是兩個(gè)按順序執(zhí)行的運(yùn)算,這一點(diǎn)在表達(dá)式中較為模糊。為了說(shuō)明這一點(diǎn),來(lái)看示意圖。示意圖既然談到了多輸入函數(shù),現(xiàn)在來(lái)定義我們一直在討論的一個(gè)概念:用箭頭表示數(shù)學(xué)運(yùn)算順序的示意圖叫作計(jì)算圖(computationalgraph)。例如,圖1-12展示了上述函數(shù)的計(jì)算圖。圖1-12:多輸入函數(shù)可以看到,兩個(gè)輸入進(jìn)入輸出,然后再被傳遞給了。代碼對(duì)此進(jìn)行編碼非常簡(jiǎn)單。但是要注意,必須添加一條額外的斷言:defmultiple_inputs_add(x:ndarray,y:ndarray,sigma:Array_Function)->float:'''具有多個(gè)輸入和加法的函數(shù),前向傳遞。'''assertx.shape==y.shapea=x+yreturnsigma(a)與本章前面提到的函數(shù)不同,對(duì)于輸入ndarray的每個(gè)元素,這個(gè)函數(shù)不只是簡(jiǎn)單地進(jìn)行“逐元素”運(yùn)算。每當(dāng)處理將多個(gè)ndarray作為輸入的運(yùn)算時(shí),都必須檢查它們的形狀,從而確保滿足該運(yùn)算所需的所有條件。在這里,對(duì)于像加法這樣的簡(jiǎn)單運(yùn)算,只需要檢查形狀是否相同,以便逐元素進(jìn)行加法運(yùn)算。1.7多輸入函數(shù)的導(dǎo)數(shù)可以根據(jù)函數(shù)的兩個(gè)輸入來(lái)計(jì)算其輸出的導(dǎo)數(shù),這一點(diǎn)很容易理解。數(shù)學(xué)鏈?zhǔn)椒▌t在這些函數(shù)中的應(yīng)用方式與前面各節(jié)介紹的方式相同。由于是嵌套函數(shù),因此可以這樣計(jì)算導(dǎo)數(shù):當(dāng)然,的計(jì)算公式與此相同。現(xiàn)在要注意:無(wú)論(或)的值如何,x(或)每增加一單位,都會(huì)增加一單位。基于這一點(diǎn),稍后可以通過(guò)編寫(xiě)代碼來(lái)計(jì)算這樣一個(gè)函數(shù)的導(dǎo)數(shù)。示意圖從概念上講,計(jì)算多輸入函數(shù)的導(dǎo)數(shù)與計(jì)算單輸入函數(shù)的導(dǎo)數(shù)所用的方法是相同的:計(jì)算每個(gè)組成函數(shù)“后向”通過(guò)計(jì)算圖的導(dǎo)數(shù),然后將結(jié)果相乘即可得出總導(dǎo)數(shù),如圖1-13所示。圖1-13:多輸入函數(shù)后向通過(guò)計(jì)算圖代碼defmultiple_inputs_add_backward(x:ndarray,y:ndarray,sigma:Array_Function)->float:'''計(jì)算這個(gè)簡(jiǎn)單函數(shù)對(duì)兩個(gè)輸入的導(dǎo)數(shù)。'''#計(jì)算前向傳遞結(jié)果a=x+y#計(jì)算導(dǎo)數(shù)dsda=deriv(sigma,a)dadx,dady=1,1returndsda*dadx,dsda*dady當(dāng)然,你可以修改以上代碼,比如讓x和y相乘,而不是相加。接下來(lái)將研究一個(gè)更復(fù)雜的示例,該示例更接近于深度學(xué)習(xí)的工作原理:一個(gè)與前一示例類似的函數(shù),但包含兩個(gè)向量輸入。1.8多向量輸入函數(shù)深度學(xué)習(xí)涉及處理輸入為向量(vector)或矩陣(matrix)的函數(shù)。這些對(duì)象不僅可以進(jìn)行加法、乘法等運(yùn)算,還可以通過(guò)點(diǎn)積或矩陣乘法進(jìn)行組合。前面提到的鏈?zhǔn)椒▌t的數(shù)學(xué)原理,以及使用前向傳遞和后向傳遞計(jì)算函數(shù)導(dǎo)數(shù)的邏輯在這里仍然適用,本章剩余部分將對(duì)此展開(kāi)介紹。這些技術(shù)將最終成為理解深度學(xué)習(xí)有效性的關(guān)鍵。深度學(xué)習(xí)的目標(biāo)是使模型擬合某些數(shù)據(jù)。更準(zhǔn)確地說(shuō),這意味著要找到一個(gè)數(shù)學(xué)函數(shù),以盡可能最優(yōu)的方式將對(duì)數(shù)據(jù)的觀測(cè)(將作為函數(shù)的輸入)映射到對(duì)數(shù)據(jù)的目標(biāo)預(yù)測(cè)(將作為函數(shù)的輸出)。這些觀測(cè)值將被編碼為矩陣,通常以行作為觀測(cè)值,每列則作為該觀測(cè)值的數(shù)字特征。第2章將對(duì)此進(jìn)行更詳細(xì)的介紹,現(xiàn)階段必須能夠計(jì)算涉及點(diǎn)積和矩陣乘法的復(fù)雜函數(shù)的導(dǎo)數(shù)。下面從數(shù)學(xué)維度精確定義上述概念。數(shù)學(xué)在神經(jīng)網(wǎng)絡(luò)中,表示單個(gè)數(shù)據(jù)點(diǎn)的典型方法是將個(gè)特征列為一行,其中每個(gè)特征都只是一個(gè)數(shù)字,如、等表示如下:這里要記住的一個(gè)典型示例是預(yù)測(cè)房?jī)r(jià),第2章將從零開(kāi)始針對(duì)這個(gè)示例構(gòu)建神經(jīng)網(wǎng)絡(luò)。在該示例中,、等是房屋的數(shù)字特征,例如房屋的占地面積或到學(xué)校的距離。1.9基于已有特征創(chuàng)建新特征神經(jīng)網(wǎng)絡(luò)中最常見(jiàn)的運(yùn)算也許就是計(jì)算已有特征的加權(quán)和,加權(quán)和可以強(qiáng)化某些特征而弱化其他特征,從而形成一種新特征,但它本身僅僅是舊特征的組合。用數(shù)學(xué)上的一種簡(jiǎn)潔的方式表達(dá)就是使用該觀測(cè)值的點(diǎn)積(dotproduct),包含與特征等長(zhǎng)的一組權(quán)重。下面分別從數(shù)學(xué)、示意圖、代碼等維度來(lái)探討這個(gè)概念。數(shù)學(xué)如果存在如下情況:那么可以將此運(yùn)算的輸出定義為:注意,這個(gè)運(yùn)算是矩陣乘法的一個(gè)特例,它恰好是一個(gè)點(diǎn)積,因?yàn)橹挥幸恍校挥幸涣?。接下?lái)介紹用示意圖描繪它的幾種方法。示意圖可以通過(guò)一種簡(jiǎn)單的方法來(lái)描繪這種運(yùn)算,如圖1-14所示。圖1-14:矩陣乘法(向量點(diǎn)積)示意圖(一)圖1-14中的運(yùn)算接受兩個(gè)輸入(都可以是ndarray),并生成一個(gè)輸出ndarray。對(duì)涉及多個(gè)輸入的大量運(yùn)算而言,這確實(shí)做了很大的簡(jiǎn)化。但是我們也可以突出顯示各個(gè)運(yùn)算和輸入,如圖1-15和圖1-16所示。圖1-15:矩陣乘法示意圖(二)圖1-16:矩陣乘法示意圖(三)注意,矩陣乘法(向量點(diǎn)積)是表示許多獨(dú)立運(yùn)算的一種簡(jiǎn)潔方法。這種運(yùn)算會(huì)讓后向傳遞的導(dǎo)數(shù)計(jì)算起來(lái)非常簡(jiǎn)潔,下一節(jié)將介紹這一點(diǎn)。代碼對(duì)矩陣乘法進(jìn)行編碼很簡(jiǎn)單:defmatmul_forward(X:ndarray,W:ndarray)->ndarray:'''計(jì)算矩陣乘法的前向傳遞結(jié)果。'''assertX.shape[1]==W.shape[0],\'''對(duì)于矩陣乘法,第一個(gè)數(shù)組中的列數(shù)應(yīng)與第二個(gè)數(shù)組中的行數(shù)相匹配。而這里,第一個(gè)數(shù)組中的列數(shù)為{0},第二個(gè)數(shù)組中的行數(shù)為{1}。'''.format(X.shape[1],W.shape[0])#矩陣乘法N=np.dot(X,W)returnN這里有一個(gè)新的斷言,它確保了矩陣乘法的有效性。(這是第一個(gè)運(yùn)算,它不僅處理相同大小的ndarray,還逐元素執(zhí)行運(yùn)算,而現(xiàn)在的輸出與輸入實(shí)際上并不匹配。因此,這個(gè)斷言很重要。)1.10多向量輸入函數(shù)的導(dǎo)數(shù)對(duì)于僅以一個(gè)數(shù)字作為輸入并生成一個(gè)輸出的函數(shù),例如或,計(jì)算導(dǎo)數(shù)很簡(jiǎn)單,只需應(yīng)用微積分中的規(guī)則即可。然而,對(duì)于向量函數(shù),其導(dǎo)數(shù)就沒(méi)有那么簡(jiǎn)單了:如果將點(diǎn)積寫(xiě)為這種形式,那么自然會(huì)產(chǎn)生一個(gè)問(wèn)題:和分別是什么?數(shù)學(xué)如何定義“矩陣的導(dǎo)數(shù)”?回顧一下,矩陣語(yǔ)法只是對(duì)一堆以特定形式排列的數(shù)字的簡(jiǎn)寫(xiě),“矩陣的導(dǎo)數(shù)”實(shí)際上是指“矩陣中每個(gè)元素的導(dǎo)數(shù)”。由于有一行,因此它可以這樣定義:然而,的輸出只是一個(gè)數(shù)字:??梢钥吹?,如果改變了單位,那么將改變單位。同理,其他的元素也滿足這種情況。因此可以得出下面的公式:這個(gè)結(jié)果出乎意料地簡(jiǎn)練,掌握這一點(diǎn)極為關(guān)鍵,既可以理解深度學(xué)習(xí)的有效性,又可以知道如何清晰地實(shí)現(xiàn)深度學(xué)習(xí)。以此類推,可以得到如下公式。示意圖從概念上講,我們只想執(zhí)行圖1-17所示的操作。圖1-17:矩陣乘法的后向傳遞如前面的例子所示,當(dāng)只處理加法和乘法時(shí),計(jì)算這些導(dǎo)數(shù)很容易。但是如何利用矩陣乘法實(shí)現(xiàn)類似的操作呢?圖1-17中的示意圖并不直觀,要準(zhǔn)確地定義它,必須求助于本節(jié)中的數(shù)學(xué)公式。代碼從數(shù)學(xué)上推算答案應(yīng)該是最困難的部分,對(duì)結(jié)果進(jìn)行編碼則比較簡(jiǎn)單:defmatmul_backward_first(X:ndarray,W:ndarray)->ndarray:'''計(jì)算矩陣乘法相對(duì)于第一個(gè)參數(shù)的后向傳遞結(jié)果。'''#后向傳遞dNdX=np.transpose(W,(1,0))returndNdX這里計(jì)算的dNdX表示的每個(gè)元素相對(duì)于輸出的和的偏導(dǎo)數(shù)。在本書(shū)中,這個(gè)量有一個(gè)特殊的名稱,即的梯度(gradient)。這個(gè)概念是指,對(duì)于的單個(gè)元素(例如),dNdX中的對(duì)應(yīng)元素(具體來(lái)說(shuō)是dNdX[2])是向量點(diǎn)積的輸出相對(duì)于的偏導(dǎo)數(shù)。在本書(shū)中,梯度僅指偏導(dǎo)數(shù)的多維對(duì)應(yīng)物。具體來(lái)說(shuō),它是函數(shù)輸出相對(duì)于該函數(shù)輸入的每個(gè)元素的偏導(dǎo)數(shù)數(shù)組。1.11向量函數(shù)及其導(dǎo)數(shù):再進(jìn)一步當(dāng)然,深度學(xué)習(xí)模型不止涉及一個(gè)運(yùn)算,它們包括長(zhǎng)鏈?zhǔn)竭\(yùn)算,其中一些是1.10節(jié)介紹的向量函數(shù),另一些則只是將函數(shù)逐元素地應(yīng)用于它們接受的ndarray(輸入)中?,F(xiàn)在來(lái)計(jì)算包含這兩種函數(shù)的復(fù)合函數(shù)的導(dǎo)數(shù)。假設(shè)函數(shù)接受向量和向量,執(zhí)行1.10節(jié)描述的點(diǎn)積(將其表示為),然后將向量輸入到函數(shù)中。這里將用新的語(yǔ)言來(lái)表達(dá)同樣的目標(biāo):計(jì)算這個(gè)新函數(shù)的輸出相對(duì)于向量和向量的梯度。從第2章開(kāi)始,本書(shū)將詳細(xì)介紹它如何與神經(jīng)網(wǎng)絡(luò)相關(guān)聯(lián)?,F(xiàn)在只需大致了解這個(gè)概念,也就是可以為任意復(fù)雜度的計(jì)算圖計(jì)算梯度。數(shù)學(xué)公式很簡(jiǎn)單,如下所示。示意圖圖1-18與圖1-17類似,只不過(guò)在最后添加了函數(shù)。圖1-18:與圖1-17類似,但在最后添加了另一個(gè)函數(shù)代碼可以像下面這樣編寫(xiě)本例中的函數(shù)。defmatrix_forward_extra(X:ndarray,W:ndarray,sigma:Array_Function)->ndarray:'''計(jì)算涉及矩陣乘法的函數(shù)(一個(gè)額外的函數(shù))的前向傳遞結(jié)果。'''assertX.shape[1]==W.shape[0]#矩陣乘法N=np.dot(X,W)#通過(guò)sigma傳遞矩陣乘法的輸出S=sigma(N)returnS向量函數(shù)及其導(dǎo)數(shù):后向傳遞類似地,后向傳遞只是前述示例的直接擴(kuò)展。數(shù)學(xué)由于是嵌套函數(shù),具體來(lái)說(shuō)就是,因此該函數(shù)在處的導(dǎo)數(shù)可以這樣表示:第一部分很簡(jiǎn)單:這是一個(gè)很好的定義,是連續(xù)函數(shù),可以在任意點(diǎn)求導(dǎo)。在這里,只在處對(duì)其求值。此外,我們?cè)?.10節(jié)的示例中已經(jīng)推斷出。因此,可以這樣表達(dá):與前面的示例一樣,由于最終答案是數(shù)字乘以中的與形狀相同的向量,因此這個(gè)公式會(huì)得出一個(gè)與形狀相同的向量。示意圖圖1-19所示的這個(gè)函數(shù)的后向傳遞示意圖與前面的例子類似,甚至不需要在數(shù)學(xué)上做過(guò)多解釋。矩陣乘法的結(jié)果包含所計(jì)算的函數(shù)的導(dǎo)數(shù),只需要在這個(gè)導(dǎo)數(shù)的基礎(chǔ)上再添加一個(gè)乘法。圖1-19:帶有矩陣乘法的圖:后向傳遞代碼對(duì)后向傳遞進(jìn)行編碼也很簡(jiǎn)單:defmatrix_function_backward_1(X:ndarray,W:ndarray,sigma:Array_Function)->ndarray:'''計(jì)算矩陣函數(shù)相對(duì)于第一個(gè)元素的導(dǎo)數(shù)。'''assertX.shape[1]==W.shape[0]#矩陣乘法N=np.dot(X,W)#通過(guò)sigma傳遞矩陣乘法的輸出S=sigma(N)#后向計(jì)算dSdN=deriv(sigma,N)#dNdXdNdX=np.transpose(W,(1,0))#將它們相乘。因?yàn)檫@里的dNdX是1×1,所以順序無(wú)關(guān)緊要returnnp.dot(dSdN,dNdX)注意,這里顯示的動(dòng)態(tài)效果與1.5節(jié)中3個(gè)嵌套函數(shù)示例顯示的動(dòng)態(tài)效果相同:計(jì)算前向傳遞(這里指N)上的量,然后在后向傳遞期間進(jìn)行使用。這是對(duì)的嗎?如何判斷正在計(jì)算的這些導(dǎo)數(shù)是否正確?測(cè)試起來(lái)很簡(jiǎn)單,就是稍微擾動(dòng)輸入并觀察輸出結(jié)果的變化。例如,在這種情況下,為:print(X)[[0.47230.6151-1.7262]]如果將增加0.01,即從-1.7262增加到-1.7162,那么應(yīng)該可以看到由輸出梯度相對(duì)于的前向函數(shù)生成的值有所增加,如圖1-20所示。圖1-20:梯度檢查示意圖利用matrix_function_backward_1函數(shù),可以看到梯度是-0.1121:print(matrix_function_backward_1(X,W,sigmoid))[[0.0852-0.0557-0.1121]]可以看到,在將遞增0.01之后,函數(shù)的輸出相應(yīng)減少了約0.01×-0.1121=-0.001121,這可以幫助測(cè)試該梯度是否正確。如果減幅(或增幅)大于或小于此量,那么關(guān)于鏈?zhǔn)椒▌t的計(jì)算就是錯(cuò)誤的。然而,當(dāng)執(zhí)行計(jì)算時(shí),少量增加確實(shí)會(huì)使函數(shù)的輸出值減小0.01×-0.1121,這意味著計(jì)算的導(dǎo)數(shù)是正確的!1.12節(jié)介紹的示例涉及前面介紹的所有運(yùn)算,并且可以直接用于第2章將構(gòu)建的模型。1.12包含兩個(gè)二維矩陣輸入的計(jì)算圖在深度學(xué)習(xí)和更通用的機(jī)器學(xué)習(xí)中,需要處理輸入為兩個(gè)二維數(shù)組的運(yùn)算,其中一個(gè)數(shù)組表示一批數(shù)據(jù),另一個(gè)表示權(quán)重。這對(duì)建模上下文很有幫助,第2章將對(duì)此展開(kāi)介紹。本章僅關(guān)注此運(yùn)算背后的原理和數(shù)學(xué)意義,具體來(lái)說(shuō),就是通過(guò)一個(gè)簡(jiǎn)單的示例詳細(xì)說(shuō)明,我們不再以一維向量的點(diǎn)積為例,而是介紹二維矩陣的乘法。即便如此,本章介紹的推算過(guò)程仍然具有數(shù)學(xué)意義,并且實(shí)際上非常容易編碼。和以前一樣,從數(shù)學(xué)上看,得出這些結(jié)果并不困難,但過(guò)程看起來(lái)有點(diǎn)復(fù)雜。不管怎樣,結(jié)果還是相當(dāng)清晰的。當(dāng)然,我們會(huì)對(duì)其按步驟進(jìn)行分解,并將其與代碼和示意圖聯(lián)系起來(lái)。數(shù)學(xué)假設(shè)和如下所示:這可能對(duì)應(yīng)一個(gè)數(shù)據(jù)集,其中每個(gè)觀測(cè)值都具有3個(gè)特征,3行可能對(duì)應(yīng)要對(duì)其進(jìn)行預(yù)測(cè)的3個(gè)觀測(cè)值?,F(xiàn)在將為這些矩陣定義以下簡(jiǎn)單的運(yùn)算。將這些矩陣相乘。和以前一樣,將把執(zhí)行此運(yùn)算的函數(shù)表示為,將輸出表示為。因此,可以這樣表示:。將結(jié)果傳遞給可微函數(shù),并定義。和以前一樣,現(xiàn)在的問(wèn)題是:輸出相對(duì)于和的梯度是多少?可以簡(jiǎn)單地再次使用鏈?zhǔn)椒▌t嗎?為什么?注意,本例與之前的示例有所不同:不是數(shù)字,而是矩陣。那么,一個(gè)矩陣相對(duì)于另一矩陣的梯度意味著什么呢?這就引出了一個(gè)微妙但十分重要的概念:可以在目標(biāo)多維數(shù)組上執(zhí)行任何一系列運(yùn)算,但是要對(duì)某些輸出定義好梯度,這需要對(duì)序列中的最后一個(gè)數(shù)組求和(或以其他方式聚合成單個(gè)數(shù)字),這樣“中每個(gè)元素的變化會(huì)在多大程度上影響輸出”這一問(wèn)題才有意義。因此,在最后添加第3個(gè)函數(shù),該函數(shù)獲取中的元素并將其求和。通過(guò)數(shù)學(xué)把它具體化。首先,把和相乘:為了便于書(shū)寫(xiě)結(jié)果矩陣,這里將第行的第列表示為。接下來(lái),將該結(jié)果輸入到中,這意味著將應(yīng)用于矩陣中的每個(gè)元素:最后,對(duì)這些元素求和:現(xiàn)在回到了純微積分的場(chǎng)景中:存在一個(gè)數(shù)字,想計(jì)算出相對(duì)于和的梯度,也就是明確這些輸入矩陣中每個(gè)元素(、等)的變化對(duì)的影響??梢赃@樣寫(xiě):至此,我們已經(jīng)從數(shù)學(xué)上理解了所面臨的問(wèn)題,接下來(lái)討論示意圖層面和代碼層面。示意圖從概念上講,與前面介紹的多輸入函數(shù)的計(jì)算圖相比,包含兩個(gè)二維矩陣輸入的運(yùn)算所做的工作其實(shí)是類似的,如圖1-21所示。圖1-21:具有復(fù)雜前向傳遞函數(shù)的計(jì)算圖這里只是像以前一樣向前發(fā)送輸入。有一點(diǎn)需要明確:即使在這個(gè)更復(fù)雜的場(chǎng)景中,也應(yīng)該能夠使用鏈?zhǔn)椒▌t計(jì)算所需的梯度。代碼對(duì)于輸入為兩個(gè)二維數(shù)組的運(yùn)算,可以像下面這樣編碼。defmatrix_function_forward_sum(X:ndarray,W:ndarray,sigma:Array_Function)->float:'''輸入ndarray(X、W)以及函數(shù)sigma,計(jì)算該函數(shù)的前向傳遞結(jié)果。'''assertX.shape[1]==W.shape[0]#矩陣乘法N=np.dot(X,W)#通過(guò)sigma傳遞矩陣乘法的輸出S=sigma(N)#將所有元素相加L=np.sum(S)returnL1.13有趣的部分:后向傳遞現(xiàn)在,要對(duì)函數(shù)“執(zhí)行后向傳遞”,這樣一來(lái),即使涉及矩陣乘法,也可以最終計(jì)算出相對(duì)于輸入ndarray的每個(gè)元素的梯度5。在學(xué)完本章之后,就能輕松地在第2章中開(kāi)始訓(xùn)練真正的機(jī)器學(xué)習(xí)模型。下面先從概念上明確要學(xué)習(xí)的內(nèi)容。5接下來(lái)重點(diǎn)計(jì)算相對(duì)于的梯度,但的梯度可以通過(guò)類似的方法來(lái)計(jì)算。數(shù)學(xué)注意,可以直接計(jì)算。值實(shí)際上是從、直到的一個(gè)函數(shù)。但是,這似乎很復(fù)雜。鏈?zhǔn)椒▌t的全部要點(diǎn)就是將復(fù)雜函數(shù)的導(dǎo)數(shù)分解成簡(jiǎn)單的部分,對(duì)每個(gè)部分執(zhí)行計(jì)算,然后把結(jié)果相乘。如此一來(lái),對(duì)這些操作進(jìn)行編碼就變得很容易:只需要逐步進(jìn)行前向傳遞,保存?zhèn)鬟f過(guò)程中的結(jié)果,然后使用這些結(jié)果來(lái)計(jì)算后向傳遞所需的所有導(dǎo)數(shù)。下面展示這種方法僅適用于涉及矩陣的情況。開(kāi)始深入討論吧??梢詫?xiě)成。如果這是一個(gè)常規(guī)函數(shù),就可以這樣編寫(xiě)鏈?zhǔn)椒▌t:然后依次計(jì)算3個(gè)偏導(dǎo)數(shù)。前面在計(jì)算包含3個(gè)嵌套函數(shù)的復(fù)合函數(shù)的導(dǎo)數(shù)時(shí),我們使用鏈?zhǔn)椒▌t分別對(duì)每個(gè)函數(shù)進(jìn)行了求導(dǎo),這里要執(zhí)行同樣的操作。圖1-22(參見(jiàn)下一頁(yè))表明,該方法同樣適用于這種函數(shù)。由于一階導(dǎo)數(shù)最直接,因此這里從一階導(dǎo)數(shù)開(kāi)始計(jì)算,主要是確定當(dāng)中每個(gè)元素值增加時(shí),Λ的輸出的增長(zhǎng)情況。由于是中所有元素的總和,因此這個(gè)導(dǎo)數(shù)很簡(jiǎn)單:只要中的任何元素有所增加,比如增加0.46個(gè)單位,就會(huì)增加0.46單位。接下來(lái)得到。這只是對(duì)中元素進(jìn)行求值的任一函數(shù)的導(dǎo)數(shù)。在前面使用的語(yǔ)法中,這同樣很容易計(jì)算:注意,我們現(xiàn)在可以肯定地說(shuō),能夠?qū)⑦@兩個(gè)導(dǎo)數(shù)按元素逐個(gè)相乘并計(jì)算:然而,現(xiàn)在陷入了困境?;趫D1-22并應(yīng)用鏈?zhǔn)椒▌t,接下來(lái)要做的是獲取。但是,回想一下,的輸出只是與矩陣相乘的結(jié)果。因此,這里要知道(3×2矩陣)中每個(gè)元素隨著中每個(gè)元素(3×3矩陣)的增加而增加的量。如果上面的表述難以理解,只要明確一點(diǎn)就可以了,那就是現(xiàn)在根本不清楚如何定義它,或者無(wú)法確定這樣做真的有效。為什么會(huì)出現(xiàn)這個(gè)問(wèn)題呢?以前,我們很幸運(yùn),由于和在形狀上可以相互轉(zhuǎn)換,因此可以證明和?,F(xiàn)在可以得出類似的結(jié)論嗎?“?”的值更具體地說(shuō),現(xiàn)在需要弄清楚以下公式中的“?”到底是什么。答案事實(shí)證明,根據(jù)乘法的計(jì)算方式,“?”處的內(nèi)容就是,這和剛才看到的向量點(diǎn)積的簡(jiǎn)單示例是一樣的。有一種方法可以驗(yàn)證這一點(diǎn),那就是直接針對(duì)中的每個(gè)元素計(jì)算的偏導(dǎo)數(shù)。這樣一來(lái)6,得到的矩陣確實(shí)顯著地分解成:6更多介紹參見(jiàn)附錄的“矩陣鏈?zhǔn)椒▌t”。其中第一個(gè)乘法是逐個(gè)元素執(zhí)行的,第二個(gè)則是矩陣乘法。這意味著,即使計(jì)算圖中的運(yùn)算涉及將矩陣與多行和多列相乘,并且即使這些運(yùn)算的輸出形狀與輸入的形狀不同,仍然可以將這些運(yùn)算包含在計(jì)算圖中,并且使用“鏈?zhǔn)椒▌t”邏輯對(duì)它們進(jìn)行反向傳播。這個(gè)結(jié)果非常重要,如果沒(méi)有這個(gè)結(jié)果,那么訓(xùn)練深度學(xué)習(xí)模型將變得更加煩瑣,后文會(huì)進(jìn)一步介紹這一點(diǎn)。示意圖本例的示意圖與1.12節(jié)中的類似,如圖1-22所示。圖1-22:復(fù)雜函數(shù)中的后向傳遞只需要計(jì)算每個(gè)組成函數(shù)的偏導(dǎo)數(shù),在其輸入處進(jìn)行求值,并將結(jié)果相乘,就可以得到最終的導(dǎo)數(shù)。要依次計(jì)算這些偏導(dǎo)數(shù),唯一的方法就是從上述數(shù)學(xué)層面計(jì)算。代碼現(xiàn)在通過(guò)代碼封裝前面推導(dǎo)出的內(nèi)容,此過(guò)程有助于加深對(duì)內(nèi)容的理解:defmatrix_function_backward_sum_1(X:ndarray,W:ndarray,sigma:Array_Function)->ndarray:'''計(jì)算矩陣函數(shù)相對(duì)于第一個(gè)矩陣輸入的和的導(dǎo)數(shù)。'''assertX.shape[1]==W.shape[0]#矩陣乘法N=np.dot(X,W)#通過(guò)sigma傳遞矩陣乘法的輸出S=sigma(N)#將所有元素相加L=np.sum(S)#注意,這里按數(shù)量指代導(dǎo)數(shù),這點(diǎn)與數(shù)學(xué)不同,在數(shù)學(xué)中使用的是它們的函數(shù)名#dLdS——都是1dLdS=np.ones_like(S)#dSdNdSdN=deriv(sigma,N)#dLdNdLdN=dLdS*dSdN#dNdXdNdX=np.transpose(W,(1,0))#dLdXdLdX=np.dot(dSdN,dNdX)returndLdX現(xiàn)在,確認(rèn)一切正常:np.random.seed(190204)X=np.random.randn(3,3)W=np.random.randn(3,2)print("X:")print(X)print("L:")print(round(matrix_function_forward_sum(X,W,sigmoid),4))print()print("dLdX:")print(matrix_function_backward_sum_1(X,W,sigmoid))X:[[-1.5775-0.66640.6391][-0.56150.7373-1.4231][-1.4435-0.39130.1539]]L:2.3755dLdX:[[0.2489-0.37480.0112][0.126-0.2781-0.1395][0.2299-0.3662-0.0225]]和前面的示例一樣,由于dLdX表示相對(duì)于的梯度,因此這意味著,左上角的元素表示。如果這個(gè)示例的矩陣數(shù)學(xué)是正確的,則將增加0.001會(huì)導(dǎo)致增加0.01×0.2489。事實(shí)上,代碼的運(yùn)行情況是這樣的:X1=X.copy()X1[0,0]+=0.001print(round((matrix_function_forward_sum(X1,W,sigmoid)-\matrix_function_forward_sum(X,W,sigmoid))/0.001,4))0.2489看起來(lái)梯度的計(jì)算是正確的!直觀地描述梯度回到前面提到的內(nèi)容,將元素傳遞給具有多重運(yùn)算的函數(shù),包括矩陣乘法、sigmoid函數(shù)、求和運(yùn)算。其中的矩陣乘法實(shí)際上是由矩陣中的9個(gè)輸入與矩陣中的6個(gè)輸入相結(jié)合,從而創(chuàng)建出的6個(gè)輸出的簡(jiǎn)寫(xiě)。然而,也可以將其視為單獨(dú)的函數(shù)WNSL,如圖1-23所示。圖1-23:用單個(gè)函數(shù)WNSL來(lái)描述嵌套函數(shù)由于每個(gè)函數(shù)都是可微的,因此整個(gè)函數(shù)就是一個(gè)以為輸入的可微函數(shù)。另外,梯度就是。為了使其可視化,可以簡(jiǎn)單地繪制隨著的變化而變化的情況。的初始值是-1.5775:print("X:")print(X)X:[[-1.5775-0.66640.6391][-0.56150.7373-1.4231][-1.4435-0.39130.1539]]對(duì)于將和輸入到前面定義的計(jì)算圖中,或者說(shuō)將和輸入到前面代碼調(diào)用的函數(shù)中,如果繪制整個(gè)過(guò)程中所得到的值的圖像,并且除了(X[0,0])外不做任何變動(dòng),可以得到圖1-24所示的結(jié)果7。7這里展示的只是matrix_function_backward_sum函數(shù)的子集。完整函數(shù)可以從圖靈社區(qū)本書(shū)主頁(yè)下載。——編者注圖1-24:在保持和的值為常數(shù)的情況下,與的對(duì)應(yīng)關(guān)系確實(shí),在只變動(dòng)的情況下,這種關(guān)系看起來(lái)很明顯??梢钥吹?,此函數(shù)在縱軸上大約增加了0.5(從剛好超過(guò)2.1到剛好超過(guò)2.6),并且在橫軸上大約增加了2。因此,斜率大約為,這正是剛剛計(jì)算的結(jié)果!復(fù)雜的矩陣數(shù)學(xué)事實(shí)上正確地計(jì)算了相對(duì)于中所有元素的偏導(dǎo)數(shù)。此外,可以用類似的方法計(jì)算相對(duì)于的梯度。相對(duì)于的梯度的表達(dá)式為。但是,表達(dá)式中的因子是從的導(dǎo)數(shù)中導(dǎo)出的,考慮到它們的順序,將位于相對(duì)于的梯度的表達(dá)式的左側(cè):因此,盡管代碼中出現(xiàn)了dNdX=np.transpose(X,(1,0)),但下一步將是:dLdW=np.dot(dNdX,dSdN)而不是之前的dLdX=np.dot(dSdN,dNdX)。1.14小結(jié)學(xué)完本章之后,你應(yīng)該有信心理解復(fù)雜的嵌套數(shù)學(xué)函數(shù),并通過(guò)將它們概念化為一系列盒子來(lái)解釋它們的工作原理,每個(gè)盒子代表一個(gè)由線連接的單一組成函數(shù)。尤其需要注意的是,即使存在涉及二維ndarray的矩陣乘法,也可以編寫(xiě)代碼來(lái)計(jì)算這些函數(shù)的輸出相對(duì)于任何輸入的導(dǎo)數(shù),理解正確計(jì)算這些導(dǎo)數(shù)背后的數(shù)學(xué)原理。掌握這些基本概念,有助于接下來(lái)構(gòu)建和訓(xùn)練神經(jīng)網(wǎng)絡(luò)。加油!第2章基本原理第1章介紹了深度學(xué)習(xí)主要的構(gòu)成要素,包括嵌套、連續(xù)和可微的函數(shù),展示了如何將這些函數(shù)表示為計(jì)算圖(圖中的每個(gè)節(jié)點(diǎn)代表一個(gè)簡(jiǎn)單函數(shù)),特別論證了在計(jì)算嵌套函數(shù)的輸出相對(duì)于其輸入的導(dǎo)數(shù)時(shí),計(jì)算圖很容易展示計(jì)算過(guò)程,即只需提取所有組成函數(shù)的導(dǎo)數(shù),在這些函數(shù)接收輸入時(shí)計(jì)算這些導(dǎo)數(shù),并將所有結(jié)果相乘1。論證過(guò)程涉及一些示例,這些示例中的函數(shù)以NumPy庫(kù)的ndarray作為輸入,并將生成的ndarray作為輸出。當(dāng)然,還有一些其他示例,它們說(shuō)明即使函數(shù)將多個(gè)ndarray作為輸入并通過(guò)矩陣乘法將它們組合在一起,這種計(jì)算導(dǎo)數(shù)的方法仍然有效。矩陣乘法與其他運(yùn)算不同,它可以改變其輸入的形狀。具體地說(shuō),如果此運(yùn)算的一個(gè)輸入是(的ndarray),另一個(gè)輸入是(的ndarray),其輸出就是一個(gè)的ndarray2。雖然該運(yùn)算的導(dǎo)數(shù)尚不明確,但可以看到,當(dāng)矩陣乘法作為一種“組合運(yùn)算”包含在嵌套函數(shù)中時(shí),仍然可以使用一種簡(jiǎn)單的表達(dá)式代替導(dǎo)數(shù)來(lái)計(jì)算其輸入的導(dǎo)數(shù):確切地講,就是可以代替,則可以代替。1基于鏈?zhǔn)椒▌t,通過(guò)這種方式生成的嵌套函數(shù)的導(dǎo)數(shù)是正確的。2這里的、、分別是不同的自然數(shù)。本章將開(kāi)始把這些概念轉(zhuǎn)換為真實(shí)的應(yīng)用程序,具體涉及以下幾項(xiàng)操作。根據(jù)第1章介紹的構(gòu)成要素解釋線性回歸。證明在第1章中所做的關(guān)于導(dǎo)數(shù)的計(jì)算能夠訓(xùn)練這種線性回歸模型。運(yùn)用同樣的構(gòu)成要素將此模型擴(kuò)展為單層神經(jīng)網(wǎng)絡(luò)。當(dāng)完成以上操作后,就能輕松地在第3章中運(yùn)用相同的構(gòu)成要素來(lái)構(gòu)建深度學(xué)習(xí)模型。不過(guò),在深入探討這些內(nèi)容之前,先簡(jiǎn)要描述一下監(jiān)督學(xué)習(xí)。監(jiān)督學(xué)習(xí)(supervisedlearning)是機(jī)器學(xué)習(xí)的子集,下面將在研究如何使用神經(jīng)網(wǎng)絡(luò)解決問(wèn)題時(shí)對(duì)其著重研究。2.1監(jiān)督學(xué)習(xí)概述概括地講,可以將機(jī)器學(xué)習(xí)描述為構(gòu)建一些算法,這些算法可以發(fā)掘或“學(xué)習(xí)”數(shù)據(jù)中的關(guān)系(relationship)。監(jiān)督學(xué)習(xí)是機(jī)器學(xué)習(xí)的子集,專用于發(fā)現(xiàn)已測(cè)量的數(shù)據(jù)屬性之間的關(guān)系3。3無(wú)監(jiān)督學(xué)習(xí)(unsupervisedlearning)是另一種機(jī)器學(xué)習(xí),可以認(rèn)為它是在已測(cè)量的事物和尚未測(cè)量的事物之間尋找關(guān)系。本章將解決實(shí)際可能遇到的一個(gè)典型的監(jiān)督學(xué)習(xí)問(wèn)題:找到房屋的屬性與價(jià)值之間的關(guān)系。顯然,像房間數(shù)量、占地面積、是否靠近學(xué)校以及對(duì)居住或擁有房屋的渴望程度等,這些屬性之間存在一定的關(guān)系??傮w來(lái)說(shuō),鑒于已經(jīng)測(cè)量了這些屬性,監(jiān)督學(xué)習(xí)的目的就是發(fā)掘這些屬性之間的關(guān)系。所謂“測(cè)量”,指的是每個(gè)屬性均已被精確地定義并表示為一個(gè)數(shù)字。房屋的許多屬性,比如房間數(shù)量、占地面積等,自然適合用數(shù)字進(jìn)行表示,但是對(duì)于其他不同類型的屬性,比如TripAdvisor4網(wǎng)站上對(duì)某地周邊環(huán)境的整體評(píng)價(jià),就不容易用數(shù)字表示了。而且,如果以一種合理的方式將這些不太結(jié)構(gòu)化的數(shù)據(jù)轉(zhuǎn)換成數(shù)字,那么可能會(huì)影響發(fā)掘關(guān)系的進(jìn)程。另外,針對(duì)任何類似房屋價(jià)值這種非具象的概念,如果必須選擇一個(gè)數(shù)字來(lái)描述它,可以選擇使用房屋的價(jià)格5。4TripAdvisor是一個(gè)旅行平臺(tái),中文名為“貓途鷹”?!g者注5即使是在實(shí)際問(wèn)題中,如何選擇價(jià)格也不容易:選擇最近一次出售房屋的價(jià)格嗎?如果是一套很久沒(méi)有出售過(guò)的房子,該如何選擇呢?在本書(shū)的示例中,數(shù)據(jù)可以明確用數(shù)字表示或已經(jīng)提前確定了,但是在許多實(shí)際問(wèn)題中,正確地做到這一點(diǎn)并不簡(jiǎn)單。一旦把“屬性”轉(zhuǎn)換成數(shù)字,就必須決定使用哪種結(jié)構(gòu)來(lái)表示這些數(shù)字。在機(jī)器學(xué)習(xí)中,有一個(gè)通用的方法能簡(jiǎn)化計(jì)算過(guò)程,那就是將單個(gè)觀測(cè)值(例如一所房屋)的每組數(shù)字表示成一行數(shù)據(jù),然后將這些行堆疊在一起形成數(shù)據(jù)的“批次”,這些數(shù)據(jù)將以二維ndarray的形式輸入到模型中。模型將輸出ndarray,也就是返回預(yù)測(cè)結(jié)果(每一行代表一個(gè)預(yù)測(cè)結(jié)果),這些預(yù)測(cè)結(jié)果也彼此疊加,批次中的每個(gè)觀測(cè)值對(duì)應(yīng)一個(gè)預(yù)測(cè)結(jié)果。現(xiàn)在做一些定義:ndarray中每一行的長(zhǎng)度是數(shù)據(jù)的特征數(shù)。一般來(lái)說(shuō),單個(gè)屬性可以映射到多個(gè)特征,典型的示例是一個(gè)屬性將數(shù)據(jù)描述為某幾種類別中的一種6,例如紅磚房、棕磚房或石板房。在這個(gè)特定的示例中,可以用3個(gè)特征來(lái)描述這個(gè)屬性。將主觀層面的(非正式的)觀測(cè)結(jié)果的屬性映射到特征的過(guò)程稱為特征工程(featureengineering),但本書(shū)不會(huì)過(guò)多討論這個(gè)過(guò)程。本章將解決一個(gè)問(wèn)題,其中每個(gè)觀測(cè)結(jié)果都有13個(gè)屬性,每個(gè)屬性都僅用一個(gè)數(shù)值特征來(lái)表示。6大多數(shù)人可能知道,這些叫作“分類特征”。前面說(shuō)過(guò),監(jiān)督學(xué)習(xí)的最終目標(biāo)是發(fā)掘數(shù)據(jù)屬性之間的關(guān)系。在實(shí)踐中,為了做到這一點(diǎn),需要選擇一個(gè)希望基于其他屬性而進(jìn)行預(yù)測(cè)的屬性,這個(gè)屬性稱作目標(biāo)(target)。任意屬性都可以用作目標(biāo),具體取決于要解決的問(wèn)題。如果目標(biāo)只描述房屋價(jià)格和房間數(shù)量之間的關(guān)系,則可以訓(xùn)練一個(gè)模型,讓其以房屋價(jià)格為目標(biāo),然后把房間數(shù)量作為一個(gè)特征,反之亦然。無(wú)論哪種方式,生成的模型實(shí)際上都包含對(duì)這兩個(gè)屬性之間關(guān)系的描述,例如可以說(shuō),房間的數(shù)量越多,房屋的價(jià)格就越高。但是,如果目標(biāo)是預(yù)測(cè)房屋的價(jià)格,但又沒(méi)有可用的價(jià)格信息,則必須選擇價(jià)格作為目標(biāo),這樣經(jīng)過(guò)訓(xùn)練最終就可以將其他信息輸入到模型中。圖2-1展示了描述監(jiān)督學(xué)習(xí)的層次結(jié)構(gòu),從發(fā)現(xiàn)數(shù)據(jù)關(guān)系的最高層次描述,到最低層次的通過(guò)訓(xùn)練模型來(lái)量化這些關(guān)系,旨在揭示特征和目標(biāo)之間的數(shù)值表示。圖2-1:監(jiān)督學(xué)習(xí)概述如圖2-1所示,本書(shū)側(cè)重于介紹底部突出顯示的層次。但是,在很多問(wèn)題中,保證最上面的部分準(zhǔn)確無(wú)誤,涉及收集正確的數(shù)據(jù)、定義試圖要解決的問(wèn)題以及開(kāi)展特征工程,這比實(shí)際建模要困難得多。不過(guò),由于本書(shū)側(cè)重建模,尤其側(cè)重于介紹深度學(xué)習(xí)模型的工作原理,因此接下來(lái)繼續(xù)討論該主題。2.2監(jiān)督學(xué)習(xí)模型我們已經(jīng)大致了解了監(jiān)督學(xué)習(xí)模型的目標(biāo),正如本章已經(jīng)提到的,這些模型只是嵌套的數(shù)學(xué)函數(shù),第1章討論了如何用數(shù)學(xué)、示意圖和代碼來(lái)表示這些函數(shù)。因此,本章可以更精確地用數(shù)學(xué)和代碼(稍后將展示大量示意圖)來(lái)解釋監(jiān)督學(xué)習(xí)的目標(biāo):找到以ndarray為輸入和輸出的數(shù)學(xué)函數(shù),該函數(shù)可以將觀測(cè)值的屬性映射到目標(biāo),即給定包含所創(chuàng)建特征的輸入ndarray,生成輸出ndarray,其值“貼近”包含目標(biāo)的ndarray。具體而言,就是用一個(gè)矩陣表示數(shù)據(jù),該矩陣有行,每行代表一個(gè)具有個(gè)特征的觀測(cè)值,所有這些特征都是數(shù)字。每一行的觀測(cè)值將是以表示的向量,這些觀測(cè)值將相互堆疊在一起形成一個(gè)批次。例如,下面是一個(gè)大小為3的批次:每一批觀測(cè)值都會(huì)有相應(yīng)的一批目標(biāo),其中的每個(gè)元素都是對(duì)應(yīng)觀測(cè)值的目標(biāo)數(shù)字??梢詫⑺鼈儽硎緸橐痪S向量:就這些數(shù)組而言,監(jiān)督學(xué)習(xí)的目標(biāo)是使用第1章介紹的工具來(lái)構(gòu)建一個(gè)函數(shù),該函數(shù)可以將基于結(jié)構(gòu)的觀測(cè)值作為輸入批次,然后生成值為的向量,這個(gè)過(guò)程稱為預(yù)測(cè)。至少對(duì)于特定數(shù)據(jù)集中的數(shù)據(jù)而言,基于某種合理的貼近度(closeness)度量方法,這些預(yù)測(cè)在一定程度上“貼近”目標(biāo)值。最后將所有這些具體化,并開(kāi)始為真實(shí)的數(shù)據(jù)集構(gòu)建第一個(gè)模型。接下來(lái)將從一個(gè)簡(jiǎn)單的線性回歸模型入手,并展示如何用第1章介紹的構(gòu)成要素來(lái)表達(dá)它。2.3線性回歸線性回歸(linearregression)通常表示為如下形式:該表示法從數(shù)學(xué)上描述了這樣一個(gè)觀點(diǎn):每個(gè)目

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論