--- title: 學習筆記 - 神經網路概論與利用keras實現手寫字辨識 tags: 學習筆記 description: 學習筆記 - 神經網路概論與利用keras實現手寫字辨識 --- <!-- {%hackmd theme-dark %} --> <!-- use dark theme --> <style> .size{ width:30vw; height:40vh; } @media screen and (max-width:415px){ .size{ width:90vw; height:70vh; } } #area-wrap { width:960px; } #learnmore-l{ text-align:center; float:left; width:344px; } #learnmore-r{ text-align:center; float:right; width:344px; } </style> # 全連結神經網路 和 手寫字辨識問題 <br> ## 摘要 本文章將以手寫字辨識的問題為例,闡述神經網路的基本架構,以及輸入層、隱藏層、輸出層的運作原理。並且將手寫辨識的問題以圖解的方式介紹。 <br> ## 神經網路架構 * Multilayer Perceptron,縮寫MLP * MLP 中的每一個神經元 (neural) 都擁有屬於自己的「激勵值」 (activation) * 神經元和神經元的連接之間有「權重」(weigh) * MLP 是一個全連結的神經網路 --- ### What is neural (神經元)? 神經元我們可以把它想像成是一個容器,而各自容器中都會存放著一個溶液,像這樣: ![](https://i.imgur.com/5QM7W60.png =200x) <div style="padding-left:10px;margin-top:-20px;">圖一、神經元與激勵值</div><br> 而這樣的容器具有<span style="font-size:20px">影響神經網路</span>的功能。 <br> ### What is activation (激勵值)? activation 中文稱作激勵值也就是容器中的溶液,溶液是一個數值,而且是經過複雜運算所獲得。 一般來講 activation 即可以代表<span style="font-size:20px">該神經元對於整個模型的重要程度</span>,可以藉由種種權重計算而來。 觀察圖二,圖二為一張 28×28 像素的灰階數字圖,圖片中每一個像素點代表著一顆神經元,而每一顆神經元又代表著屬於自己的激勵值。在圖一中的激勵值愈大,則其顏色就愈亮,反之則愈暗。 <div style="text-align:center;"> <img style="width:500px;height:500px;" src="https://i.imgur.com/IV64xDR.jpg" > <img style="width:200px;height:200px;" src="https://i.imgur.com/ePHINXE.png" > </div>! <div style="text-align:center;padding-left:20px;">圖二、數字圖片與激勵值 [2]</div> <br> ### What is weigh (權重)? 權重跟激勵值的意義類似,但更像是比激勵值再少一個位階。若說激勵值能夠影響神經元的重要程度,那麼權重就扮演著影響激勵值的重要程度的角色。 ![](https://i.imgur.com/3y7bn2W.png =500x) <div style="text-align:center;padding-left:20px;margin-top:-25px;">圖三、權重與神經元</div> 1. 觀察圖三, w1 就是神經元 a0 與 b0 之間的權重,因此權重並沒有辦法單獨存在而是必須依賴神經元。 2. 權重有方向性。例如 w1 是「指向b0的權重」,可以想像成 b0 的其中一個 input 。 以圖三為例, b0 的溶液數值是需要藉由 a0與w1 、 a1與w2 、 a2與w3 計算而來。因此我們可以看看這張流程圖。 ![](https://i.imgur.com/mEO0fVt.png) <div style="text-align:center;padding-left:20px;margin-top:-20px;">圖四、神經網路各階層影響關係圖</div><br> 我們可以想像,權重足以影響激勵值,而激勵值又足以影響神經元的狀況,最後神經元能夠影響神經網路。 到了這邊,我們對神經網路內部的成員都該有了基本的認識了。 --- ## fully connected neural network (FCNN、全連結神經網路) Multilayer Perceptron手寫字辨識的網路其實使用到 FCNN 的概念,我們觀察圖五,其實就是把剛剛提到的 a0、a1、b0 的概念延伸成一個較大神經網路,並且為每一個神經網路層命名。而神經網路的其中一層就是把好多個神經元排列在一起所組成的結構,以下我們為它們提供了三個名詞: 1. 輸入層 2. 隱藏層 3. 輸出層 <br> ![](https://i.imgur.com/kAun7cP.jpg) <div style="text-align:center;padding-left:20px;margin-top:-15px;">圖五、神經網路架構圖</div> <br> ### 輸入層 我們觀察一下輸入層,輸入層共有 784 顆神經元,其實是因為在 MNIST 的手寫字資料集當中每筆資料都是一張 28×28 的灰階(1 channel)圖片,這意味著一張圖片共有 1×28×28 個像素(pixel)。我們可以假設每一個 pixel 上都擁有一顆神經元,再把這張圖片拉長成一條向量,即可構成一個輸入層。 ![](https://i.imgur.com/WP3tXPU.gif) <div style="text-align:center;padding-left:20px;margin-top:-15px;">圖六、輸入層設計圖 [2]</div> <br> ### 輸出層 我們先來看一下輸出層,輸出層共有 10 顆神經元,即代表<span style="font-size:20px">每一種數字的機率</span>。 跟前面提到的相同,激勵值越高的地方神經元就會越亮,以圖七為例,9 這個數字經過一連串的計算後,在輸出層神經元為 9 的位置就是最亮的。 ![](https://i.imgur.com/zyGyiN1.jpg) <div style="text-align:center;padding-left:20px;margin-top:-10px;">圖七、原圖與輸出層關係圖 [2]</div> <br> 特別說明一下,輸入層會這樣設計單純只是方便而已,事實上可以在輸入層僅添加 300 顆神經元就好,因此輸入層的神經元個數是以「方便、易處理」作為考量。 相反的,輸出層的 10 顆神經元在手寫字辨識的問題上是固定的,其原因就是為了辨識每一種數字的機率,若把題目改成辨識各個貓的品種,那輸出層的神經元可能會上百甚至上千顆。所以,輸出層的神經元個數是根據問題而定。 <br> ### 隱藏層 (前言) 隱藏層的運作原理以及學習方式在本章節將不會提及,之後的文章會再與大家解釋。 不過,我們仍然可以知道隱藏層之中大約是怎麼處理問題的。 我們不妨思考一下,輸出層為什麼會知道圖八中的數字為 9 ? ![](https://i.imgur.com/8526l7r.png) <div style="padding-left:60px;margin-top:-15px;">圖八、數字圖片「9」 [2]</div> <br><br> 有沒有可能輸入層的神經元就好像爬梯子一樣,經過一連串的計算後得出一個答案呢? ![](https://i.imgur.com/jZJ7WtS.png) <div style="text-align:center;padding-left:20px;margin-top:-30px;">圖九、爬梯子示意圖</div><br> 我們可以這個方向為基底,討論一下接下來的問題。 <br> ### 隱藏層 我們先有一個概念:<span style="font-size:20px">「隱藏層內部的部分神經元能夠對應到圖片的部分位置上」。</span> 圖十就是將部分的神經元疊到原圖上,如此一來,我們能利用比對後的相似度為依據知道一張圖片是否含有一個邊。 ![](https://i.imgur.com/BgIq7tP.gif) <div style="text-align:center;padding-right:160px;margin-top:-15px;">圖十、數字特徵關係圖 [2]</div><br> 若能辨識一個邊後,是否能辨識第二個、第三個...?最後,辨識一個數字「7」的所有特徵。 <br> ### 拆解 有了剛剛的概念後我們看圖十一,「9」被拆成了一個上方圓圈與一個下方直豎、「8」被拆成了一個上方圓圈與一個下方圓圈、「4」則被拆成了三個小線段。 ![](https://i.imgur.com/me0UTBR.png) <div style="text-align:center;margin-top:-15px;">圖十一、數字拆解零件圖之一 [2]</div> <br><br> 敏銳的讀者可能就會問了,「我們又該如何辨識一個圓圈呢?」 答案很簡單,我們就把他們做跟「9」一樣的拆解就好,只是從 9 變成一個圓圈,方法如圖十二 ![](https://i.imgur.com/hLRYVQj.png) <div style="text-align:center;margin-top:-15px;">圖十二、數字拆解零件圖之二 [2]</div> <br> 接著,我們只需要不停的把問題細分成更多個小問題,到最後零件會被細分為一兩個 pixel 之間的問題,如此一來一顆神經元就能夠負責一個小區域,也能夠點亮自己所負責的區域,而此作法類似演算法中的分治法(divide and conquer)。 ![](https://i.imgur.com/pm0nFSs.gif) <div style="text-align:center;margin-top:-15px;">圖十三、拆解與神經元關係圖 [2]</div> <br><br> ### 組合 既然一顆神經元能夠解決一部份邊的問題,就可以聯合好幾顆神經元一起解決長邊、圓圈問題,如圖十四。 ![](https://i.imgur.com/nwOUNbn.gif) <div style="text-align:center;margin-top:-15px;">圖十四、組合與神經元關係圖 [2]</div> <br> ### 小結 從拆解與組合的例子我們可以想像,若數字含有特定的迷你線段那麼特定的神經元就會亮起,而特定幾顆神經元亮起則代表輸入的原圖帶有「圓圈」、「橫線」、「直線」等特徵,最後若上方圓圈與下方直豎的神經元亮起則能推斷其為數字「9」。 雖然這樣過程看似合理,不過事實上對於電腦而言所謂的神經元、權重、拆解、組合 都只是一連串的數字計算,以上的推理都只是以人類的角度來評斷,電腦內部不見得是這樣運作的,希望大家能夠知曉這一個原則。 目前關於輸入層、隱藏層、輸出層 我們只是片面的瞭解他們的工作內容,實際上這三層都有相當深遠的學問堆疊而成,此文章只是為了刺激大家對神經網路的興趣,目前我們只需知道這樣就好。 <br> ## 激勵函數 (activation) 激勵函數為計算出激勵值的方法。這邊需要特別注意一下,一般來說激勵值是一個「數值」,例如:0.5、0.16 等等,而激勵函數則是一個「方程式」,例如我們接下來要說的 Sigmoid 。 ### 激勵函數的用途? 激勵函數的作用是<span style="font-size:20px;">限制激勵值的範圍</span>。 為了方便電腦運算以及資料的易讀性,我們會將激勵值限制在某個區間,靠的就是激勵函數 <span style="font-size:24px;"> $Sigmoid(x) = \dfrac{1}{1+e^{-x}}$ <span><br> ### 握有控制權的 Bias 有了激活函數後我們可以開始計算激勵值,但在這之前還有一個東西需要介紹給大家:「Bias」。 Bias類是一個閥值,他可以另我們能夠操控神經元的狀況,類似一個人工能夠操控的權重,請看圖十五。 ![](https://i.imgur.com/cJUKs8t.png) <div style="text-align:center;margin-top:-15px;">圖十五、激勵值算式圖 [2]</div><br> 例如現在模型訓練出了一些問題,每一條權重都相當重要,每顆神經元都亮的不得了,就可以透過調整Bias改善這類的問題。 另外,圖當中的 $a_0^{(1)}$ 指的是 第1層的第0顆神經元,所以 $a_6^{(0)}$ 指的是第0層的第6顆神經元。 <br> ### 整合 最後,將整個函數會變成圖十六的樣子,我們就可以計算出一顆神經元的激勵值。 ![](https://i.imgur.com/5s6JShI.png) <div style="text-align:center;margin-top:-15px;">圖十六、激勵值計算函數 [2]</div><br> 算出一顆神經元的激勵值後就可以不停地算下去,直到輸出層為止。 --- <br> ## 總整理 ### 神經網路的元素 1. 神經元 >激勵值的儲存裝置 2. 激勵值 >控制神經元的亮度與機率 3. 權重 >決定一顆神經元是否重要的關鍵 4. Bias >操控神經元的特殊變數 ### 全連結神經網路有什麼? 1. 輸入層 >輸入一張圖片,將其拉長成為一條向量。 2. 隱藏層 >主要計算的地方,在手寫字辨識問題中有兩個任務: 1. 拆解:將數字拆分成多個迷你線段。 2. 組合:將拆解的迷你線段結果反應到神經元上。 3. 輸出層 >顯示各項機率,以此題為言共有10顆神經元,每一顆分別代表一種數字的預測機率。 ### 激勵函數 1. 計算與限制激勵值 2. 是一條方程式而不是一個數值 --- <br> ## 利用keras實現手寫字辨識 我這邊用以上概念撰寫了手寫字辨識的程式碼,程式碼中含有非常多本篇未提到的知識,之後的文章應該會提及,若有興趣的人可以自行上網查閱! 程式碼裡面會有簡單的註解 colab file : https://drive.google.com/file/d/18M5DnjdjdHlh-Q1KLrN6cuUm0SViwYmA/view?usp=sharing python file: https://drive.google.com/file/d/1lOOMRcCciM_oUv_1UKf8sKSaNVdv0w1H/view?usp=sharing <br> ## 參考資料 [1] Yann LeCun, Corinna Cortes, Christopher J.C. Burges, THE MNIST DATABASE > http://yann.lecun.com/exdb/mnist/ [2] 3Blue1Brown, But what is a neural network? | Chapter 1, Deep learning > https://youtu.be/aircAruvnKk --- <br> ## 後記 此文章其實是想寫給未來的自己看的,因為大三修讀了類神經網路也跟教授討論了非常多神經網路的問題,想趁著記憶猶新的時候記自己的學習點滴,這篇文章所提到的概念都相當粗淺,未來會繼續撰寫有關類神經網路的學習心得!謝謝大家!