聲明1)該文章整理自網(wǎng)上的大牛和機器學(xué)習(xí)專家無私奉獻的資料,具體引用的資料請看參考文獻。 2)本文僅供學(xué)術(shù)交流,非商用。所以每一部分具體的參考資料并沒有詳細對應(yīng)。如果某部分不小心侵犯了大家的利益,還望海涵,并聯(lián)系博主刪除。 3)博主才疏學(xué)淺,文中如有不當之處,請各位指出,共同進步,謝謝。 4)此屬于第一版本,若有錯誤,還需繼續(xù)修正與增刪。還望大家多多指點。大家都共享一點點,一起為祖國科研的推進添磚加瓦。 深度學(xué)習(xí)入門筆記(五):神經(jīng)網(wǎng)絡(luò)的編程基礎(chǔ)1、Jupyter/iPython Notebooks快速入門學(xué)到現(xiàn)在,你需要知道常用的python的編譯器,推薦使用anaconda而不是官方的python,這樣的話更容易安裝各種第三方庫,如何安裝可以看一下這個博客——Windows10 下 Anaconda和 PyCharm 的詳細的安裝教程(圖文并茂)。 至于IDE的話,pycharm 適合于大型項目的編寫和調(diào)試,Jupyter Notebook 適合于學(xué)習(xí)和數(shù)據(jù)挖掘探索,這里我們就快速地學(xué)習(xí)一下 Jupyter Notebook 工具。
 這就是 Jupyter Notebook 的界面,讓我快速地講解下它的一些特性。
 這里有一些空白區(qū)域的代碼塊,可以編寫代碼,而較長的灰色區(qū)域就是代碼塊。
 比如,編寫打印輸出著名的程序員入門語句——Hello World 的代碼,然后執(zhí)行這一代碼塊,最終,它就會輸出我們想要的 Hello World。
 在運行一個單元格 cell 時,你也可以選擇運行其中的一塊代碼區(qū)域。通過點擊 Cell 菜單的 Run Cells 執(zhí)行這部分代碼。 在你的計算機上,運行 cell 的鍵盤快捷方式是 Ctrl + enter。但是也可以使用 shift + enter 來運行 cell,不過這樣會默認跳轉(zhuǎn)到下一個代碼區(qū)域。
 當閱讀指南時,如果不小心雙擊了它,點中的區(qū)域就會變成 markdown 語言形式。如果不小心使其變成了這樣的文本框,只要運行下單元格 cell,就可以回到原來的形式。所以,點擊 cell 菜單的 Run Cells 或者使用 Ctrl + enter,就可以使得它變回原樣。markdown 格式可以用來寫筆記,以免自己忘記了代碼中的知識。
 這里還有一些其他的小技巧。比如當執(zhí)行上面所使用的代碼時,它實際上會使用一個內(nèi)核在服務(wù)器上運行這段代碼。如果你正在運行超負荷的進程,或者電腦運行了很長一段時間,或者在運行中出了錯,又或者網(wǎng)絡(luò)連接失敗,這里依然有機會讓 Kernel 重新工作。你只要點擊 Kernel,選擇 Restart,它會重新運行 Kernel 使程序繼續(xù)工作。 所以,如果只是運行相對較小的工作并且才剛剛啟動你的臺式電腦或筆記本電腦,這種情況應(yīng)該是不會發(fā)生的。但是,如果你看見錯誤信息,比如 Kernel 已經(jīng)中斷或者其他信息,你可以試著重啟 Kernel,這樣就簡單地重啟程序了。
 當使用 Notebook 時會有多個代碼區(qū)域塊。盡管并沒有在前面的代碼塊中添加自己的代碼,但還是要確保先執(zhí)行這塊代碼。因為在這個例子,它導(dǎo)入了 numpy 包并另命名為 np 等,并聲明了一些可能需要的變量。為了能順利地執(zhí)行下面的代碼,就必須確保先執(zhí)行上面的代碼,即使不要求寫其他的代碼,這樣其他程序就可以默認是在這些庫的調(diào)用下運行了。
 最后就是編譯環(huán)境的選擇,正常情況下 Notebook 的編譯環(huán)境是默認的,但是你也可以自己新建一個環(huán)境,這個具體操作在這個博客中——Windows10 下 Anaconda和 PyCharm 的詳細的安裝教程(圖文并茂),比如我這里新建的環(huán)境 Pytorch for Deeplearning,就是專門為 pytorch 的學(xué)習(xí)而建立的,可以通過 Kernel 下的 Change kernel,選擇 Pytorch for Deeplearning,就ok了。
 這個就是默認的 kernel。
 這個是我自己建的 kernel。 你會發(fā)現(xiàn)這種交互式的 shell 命令,在 Notebooks 是非常有用的,能使你快速地實現(xiàn)代碼并且查看輸出結(jié)果,便于學(xué)習(xí),同時還可以記錄在這個過程中的想法。好好學(xué)習(xí)它的使用,你會發(fā)現(xiàn)更多的驚喜。 2、Python 中的廣播 這是一個不同食物(每100g)中不同營養(yǎng)成分的卡路里含量表格,表格為3行4列,列表示不同的食物種類,從左至右依次為蘋果(Apples),牛肉(Beef),雞蛋(Eggs),土豆(Potatoes)。行表示不同的營養(yǎng)成分,從上到下依次為碳水化合物,蛋白質(zhì),脂肪。
那么,現(xiàn)在假設(shè)我們想要計算不同食物中不同營養(yǎng)成分中的卡路里百分比,應(yīng)該怎么做? 以計算蘋果中的碳水化合物卡路里百分比含量為例,首先計算蘋果(Apples)(100g)中三種營養(yǎng)成分卡路里總和 56+1.2+1.8 = 59 ,然后用 56 / 59 = 94.9% 算出結(jié)果??梢悦黠@地看出蘋果(Apples)中的卡路里大部分來自于碳水化合物(Carb),而牛肉(Beef)則不同。對于其他食物,計算方法類似。首先,按列求和,計算每種食物中(100g)三種營養(yǎng)成分總和,然后分別用不用營養(yǎng)成分的卡路里數(shù)量除以總和,計算百分比。 那么,能否在向量化(深度學(xué)習(xí)入門筆記(四):向量化)的基礎(chǔ)上用代碼完成這樣的一個計算過程呢? 當然是可以的,假設(shè)上圖的表格是一個4行3列的矩陣 AA,記為 A3×4A3×4,接下來使用 Python 的 numpy 庫完成這樣的計算。使用兩行代碼就可以完成整個過程,第一行代碼對每一列進行求和,第二行代碼分別計算每種食物每種營養(yǎng)成分的百分比。 在 jupyter notebook 中輸入如下代碼,按 Ctrl + Enter 運行,輸出如下:
 下面再計算每列的和,可以看到輸出是每種食物(100g)的卡路里總和。
 其中 sum 的參數(shù) axis=0 表示求和運算按列執(zhí)行,之后會詳細解釋。 接下來計算百分比,這條指令將 3×43×4 的矩陣 AA 除以一個 1×41×4 的矩陣,得到了一個 3×43×4 的結(jié)果矩陣,這個結(jié)果矩陣就是要求的百分比含量。
 到這里問題就解決了,現(xiàn)在來解釋一下 A.sum(axis = 0) 中的參數(shù) axis 。axis用來指明將要進行的運算是沿著哪個軸執(zhí)行,在numpy中,0軸是垂直的,也就是列,而1軸是水平的,也就是行。 而第二個 A / cal.reshape(1, 4) 指令則調(diào)用了 numpy 中的廣播機制。這里使用 3×43×4 的矩陣 AA 除以 1×41×4 的矩陣 calcal。技術(shù)上來講,其實并不需要再將矩陣 calcal reshape (重塑)成 1×41×4,因為矩陣 calcal 本身已經(jīng)是 1×41×4 了。但是當我們寫代碼的過程中出現(xiàn)不確定矩陣維度的時候,通常會對矩陣進行重塑來確保得到想要的列向量或行向量。重塑操作 reshape 是一個常量時間的操作,時間復(fù)雜度是 O(1)O(1),它的調(diào)用代價極低,所以使用是沒問題的,也推薦大家使用。 那么一個 3×43×4 的矩陣是怎么和 1×41×4 的矩陣做除法的呢?來看一些廣播的例子:
 在 numpy 中,當一個 4×14×1 的列向量與一個常數(shù)做加法時,實際上會將常數(shù)擴展為一個 4×14×1 的列向量,然后兩者做逐元素加法。結(jié)果就是右邊的這個向量。這種廣播機制對于行向量和列向量均可以使用。 再看下一個例子。
 用一個 2×32×3 的矩陣和一個 1×31×3 的矩陣相加,其泛化形式是 m×nm×n 的矩陣和 1×n1×n 的矩陣相加。在執(zhí)行加法操作時,其實是將 1×n1×n 的矩陣復(fù)制成為 m×nm×n 的矩陣,然后兩者做逐元素加法得到結(jié)果。針對這個具體例子,相當于在矩陣的第一列全部加100,第二列全部加200,第三列全部加300。這就是在前面例子中計算卡路里百分比的廣播機制,只不過那里是除法操作,這里是加法操作(廣播機制與執(zhí)行的運算種類無關(guān))。 下面是最后一個例子。
 這里相當于是一個 m×nm×n 的矩陣加上一個 m×1m×1 的矩陣。在進行運算時,會先將 m×1m×1 矩陣水平復(fù)制 nn 次,變成一個 m×nm×n 的矩陣,然后再執(zhí)行逐元素加法。 廣播機制的一般原則如下: 這里的廣播和播音廣播是完全不同的,它的要求是什么呢?什么樣的條件下可以使用廣播? 要求:如果兩個數(shù)組的后緣維度的軸長度相符或其中一方的軸長度為1,則認為它們是廣播兼容的。廣播會在缺失維度和軸長度為1的維度上進行。 如何計算后緣維度的軸長度?可以使用代碼 A.shape[-1] 即矩陣維度元組中的最后一個位置的值,就是矩陣維度的最后一個維度,比如卡路里計算的例子中,矩陣 A3,4A3,4 后緣維度的軸長度是4,而矩陣 cal1,4cal1,4 的后緣維度也是4,故滿足了后緣維度軸長度相符的條件,可以進行廣播。廣播會在軸長度為1的維度上進行,軸長度為1的維度對應(yīng) axis=0 ,即垂直方向,矩陣 cal1,4cal1,4 沿 axis=0 (垂直方向)復(fù)制成為 calTemp3,4calTemp3,4 ,之后兩者進行逐元素除法運算。 簡單概括總結(jié)就是,先變成一樣大,再逐元素除法。 然后解釋圖中的例子

矩陣 Am,nAm,n 和矩陣 B1,nB1,n 進行四則運算,后緣維度軸長度相符,符合條件,可以廣播,廣播沿著軸長度為1的軸進行,即 B1,nB1,n 廣播成為 Bm,n′Bm,n′ ,之后做逐元素四則運算。 矩陣 Am,nAm,n 和矩陣 Bm,1Bm,1 進行四則運算,后緣維度軸長度不相符,但其中一方軸長度為1,符合條件,可以廣播,廣播沿著軸長度為1的軸進行,即 Bm,1Bm,1 廣播成為 Bm,n′Bm,n′ ,之后做逐元素四則運算。 矩陣 Am,1Am,1 和常數(shù) RR 進行四則運算,后緣維度軸長度不相符,但其中一方軸長度為1,符合條件,可以廣播,廣播沿著缺失維度的軸進行,缺失維度就是 axis=0 ,軸長度為1的軸是 axis=1 ,即 RR 廣播成為 Bm,1′Bm,1′ ,之后做逐元素四則運算。 最后總結(jié)一下 broadcasting ,可以看看下面的圖:
 3、關(guān)于numpy向量的說明Python 的特性允許你使用 廣播(broadcasting) 功能,這是 Python 的 numpy 程序語言庫中最靈活的地方,但這是程序語言的優(yōu)點,也是缺點。 為了演示 Python-numpy 的一個容易被忽略的效果,特別是怎樣在 Python-numpy 中構(gòu)造向量,來做一個快速示范。 首先設(shè)置 a=np.random.randn(5)a=np.random.randn(5),這樣會生成存儲在數(shù)組 aa 中的5個高斯隨機數(shù)變量;然后輸出 aa,從屏幕上可以得知,此時 aa 的 shape(形狀) 是一個 (5,)(5,) 的結(jié)構(gòu)同樣地,a.Ta.T 的 shape 也是這樣的。這在 Python 中被稱作 一個一維數(shù)組。它既不是一個行向量也不是一個列向量,這也導(dǎo)致它有一些不是很直觀的效果。 比如 aa 和 aa 的轉(zhuǎn)置陣最終結(jié)果看起來一樣,shape 也是一樣的。但是輸出 aa 和 aa 的轉(zhuǎn)置陣的內(nèi)積,你可能會想,aa 乘以 aa 的轉(zhuǎn)置,返回的可能會是一個矩陣。但如果這樣做,你只會得到一個數(shù)。
 所以在編寫神經(jīng)網(wǎng)絡(luò)時,不要使用 shape 為 (5,) 、(n,) 或者其他一維數(shù)組的數(shù)據(jù)結(jié)構(gòu)。相反,設(shè)置 aa 為 (5,1)(5,1),這樣就是一個5行1列的向量。在先前的操作里 aa 和 aa 的轉(zhuǎn)置看起來一樣,而現(xiàn)在這樣的 aa 變成一個新的 aa 的轉(zhuǎn)置,并且它是一個行向量。當輸出 aa 的轉(zhuǎn)置時有兩對方括號,而之前只有一對方括號,所以這就是 1行5列的矩陣和一維數(shù)組的差別。
 如果這次再輸出 aa 和 aa 的轉(zhuǎn)置的乘積,會返回一個向量的外積,也就是一個矩陣。這就符合我們的預(yù)期了,也就是在可控范圍內(nèi)了,因為你知道自己的代碼輸出是什么了。 除了,輸入確定維度的矩陣或向量之外,還有一件事,就是如果你不能完全確定一個向量的維度,建議你扔一個 斷言語句(assertion statement) 進去。這樣,就可以確保在這種情況下是否是一個 (5,1)(5,1) 向量了,或者說是一個列向量。
 如果不對的話,就會報一個叫做 AssertionError 的錯誤?。?! 4、編程框架的選擇問題這個我在 大話卷積神經(jīng)網(wǎng)絡(luò)CNN(干貨滿滿) 中講過,目前主流的是 Google的TensorFlow、Facebook的pytorch 還有 百度的paddlepaddle,如果是研究的話,我建議使用TensorFlow,因為它更好理解一下基礎(chǔ)原理,而不是單純的調(diào)包俠。大話卷積神經(jīng)網(wǎng)絡(luò)CNN(干貨滿滿) 博客中也寫了相關(guān)的資源推薦,這里就不詳細說了。
|