# 深度學習 ###### 2021 陽明交大資訊人才培訓 by Ivor Chu ###### tags: `機器學習` 神經網路 --- **何謂神經網路** 神經網路是受到生物的神經網路啟發,人工神經網路是模擬生物神經網路的一種計算模型,也就是模擬神經元的輸入輸出與傳遞訊號。神經網路演算法透過模擬神經元組成一個人工的神經網路來做到一些類似大腦學習的機制。 > 人工神經網路並非全然都在探究大腦,只是受到他的啟發的一種計算模式。 神經網路可以被比擬為一個DJ盤,上面有很多不同的旋鈕分別代表不同的功能,像是音量、回音、等化器、效果器等等。而在訓練神經網路時就像是在調整這些旋鈕,環境會給你回饋而你要依據去調整,若聲音太大就調整音量的旋鈕、若回音不夠就調整回音的旋鈕,直到達到理想的結果為止。今天若將一隻貓的影像丟入神經網路模型中,假設一剛開始的輸出是狗,這時演算法就會去調整神經網路裡的旋鈕,調了很多次之後輸出變成了貓,就知道每個旋鈕正確的位置了。 神經元 --- **線性模型** 線性模型是個最簡單的線性神經元,可以視為每一個x會對應一個位子,並經過一個函數來得到輸出。 ![](https://i.imgur.com/D6arCYr.png) ![](https://i.imgur.com/AYUI5OW.png) 若把線性模型加上一個激活函數,就會成為一個非線性的神經元,例如下圖所示的階梯狀激活函數,會把小於0的數變-1、大於0的數變1,所以當資訊進入神經元,會被夾起來並丟入激活函數,此例中將輸出1或-1,這個g(x)有非常多選擇,也稱為激活函數。 ![](https://i.imgur.com/uJgvVHK.png) ![](https://i.imgur.com/UwN8KUo.png) **激活函數** 下圖為一些常用的激活函數: Sign: 當輸入的所有資訊加總小於0則輸出-1、大於0則輸出1 Sigmoid: 輸入的所有資訊加總只輸出介於0到1 (大於小於則視為0或1) Relu: 當輸入的所有資訊加總小於0則輸出0、大於0則輸出加總 ![](https://i.imgur.com/sfYbrYj.png) **神經元能做到什麼** 以下圖為例,若在二維平面上來看,此神經元可以視為一條直線,將一個平面切一刀成-1與1,若你希望可以將兩筆資料分開,這個神經元恰好可以做到這件事情,也就是一個二元分類的問題。 ![](https://i.imgur.com/18SRMyu.png) ![](https://i.imgur.com/UysF0Hj.png) **神經元不能做到什麼** 以下圖為例,神經元會對若輸入的資料不對的進行調整,尋找可以切一刀的地方,但在此例中神經元怎麼切都無法將資料切成兩半,達到一個神經元的能耐,這時就要用到更多神經元組成一個神經網路來分類此類資料。 ![](https://i.imgur.com/qQo0807.png) 多層神經網路 --- **多層神經網路** 若今天把神經元當作一個基本單位,透過層次結構便可以組成神經網路。定義神經網路結構時要先選定層數、每層有多少神經元、每個神經元用的激活函數等等問題,最後選定完結構後會生成一個假設集合,並用訓練資料來挑選出最好的模型。以下圖為例,左邊的神經元在左邊切一刀,右邊的神經元在右邊切一刀,匯集這兩個神經元便可以分類此筆資料 ![](https://i.imgur.com/6lXSnjh.jpg) **層計算過程** 每一個神經元會有輸入和參數(權重),每一個神經元會傳遞給下一層的所有神經元(預設),這時就可以用一個矩陣來儲存並計算這些數值,所以神經元計算本質上就是個矩陣的乘法,前一層的輸出會傳遞給下一層當輸入。 ![](https://i.imgur.com/AQTfKag.png) * 回歸問題:希望輸出是實數,最後一層就不要加上激活函數 ![](https://i.imgur.com/BkOZxqd.png) * 分類問題:希望庶出是判別類別,則在最後一層加入激活函數Softmax來把實數資料轉換為機率分佈,輸出則取機率最大的類別。 ![](https://i.imgur.com/CSaK7sg.png) **影像識別範例** 首先先將28x28貓的照片每一像素當作輸入丟入第一層的784個神經元中,接著每一個神經元的輸入成上神經元自己的權重,經過激活函數後傳遞至下一層的每一個神經元中,在最後一層時以Softmax激活函數將資料轉換為機率分佈,最後機率較大的類別當作輸出並與真實答案來比較、調整每個神經元的參數。 ![](https://i.imgur.com/Y83nxsi.jpg) 計算流程圖與梯度 --- **計算流程圖** 所有計算過程都能用一個流程圖來表示,在下圖中每一個方塊都代表著一個數學計算的運算單元,把數值帶入時,經過流程圖的邏輯與運算單元,便可以得到與原始計算過程相同的解。 ![](https://i.imgur.com/UuKrSFr.png) **神經網路計算圖** 神經網路計算本質上就是一個矩陣運算,層和層之間做維度轉換,把上一層的輸出與下一層的輸入成上一個矩陣(權重)來進行轉換。 ![](https://i.imgur.com/uL44FEC.jpg) **梯度** 梯度可以被視為在函數上的一個點做些微的改變,那他輸出改變的幅度會是多少?也就是說若今天在一個DJ盤上我稍微轉動旋鈕,那他的聲音會增加多少?將梯度套用到計算流程圖中可以計算輸入的資料進入某運算單元後的輸出變量會是多少。每個運算單元都包含著兩種運算能力,向前與向後。向前計算是指當我把輸入塞進運算單元中,他的輸出結果會是多少,而向後計算則是從輸出端輸入資料,並計算輸出與輸入的直相差多少,也就是梯度。 ![](https://i.imgur.com/T0aidT7.png) **梯度計算流程圖** 計算過程都能用流程圖來表示,並且向後運算可以求梯度,所以激活函數都要是可微分函數。對整個計算過程做偏微分可得每一個運算單元在改變一點點的輸入時,輸出會改變多少,進而可得整個計算過程的梯度,也就是輸入直改變一點點時輸出直會改變多少。這些算出來運算單元的導函數可以透過向後傳遞來決定每一個神經元參數調整的幅度。 ![](https://i.imgur.com/tMfLcx3.png) 損失函數 --- **損失函數** 損失函數是一個衡量訓練好壞的方法,並且可以當作調整神經元參數的依據,像是在旋鈕的案例中,太大聲或太小聲就是個衡量的標準。 * 回歸問題 * L2/L1 Loss * Logistic Loss * Hinge Loss * 分類問題 * 0/1 Loss * Negative Log-likelihood(NLL) 回歸問題中標籤與輸出都是實數,因此可以計算他們彼此之間的差異,具體來說計算預測值與標籤值相減平方的和,此稱為損失。 ![](https://i.imgur.com/8Pd8xvv.png) 分類問題中標籤是以One-hot Encoding的方式表現是哪一種類別,輸出則是一個機率分佈,因此要計算他們的交叉熵。具體來說要先將最後一層的所有神經元輸出的機率取log後成上他在One-hot Encoding上代表的數值加總,但因為One-hot Encoding上只有0和1,所以只需要把目前計算的神經元的機率乘上1即可,而把機率取log後加上負號,機率較小的數會被放大,所以我們會看到這個損失函數下降,自此也可以看出機率和標籤的距離差多少。 ![](https://i.imgur.com/US36LB1.png) 梯度下降演算法 --- **最佳化問題** 最佳化問題包含一個目標函數與多個限制條件所組成,在符合限制條件下,最大或最小化目標函數,像是你有1萬元,要怎麼投資這1萬元才能獲得最大收益,又或著你只有100元,要怎麼兼顧營養均衡的條件下吃最飽。機器學習中很多都是最佳化的問題,在數學上已經有很多現成的工具,針對不同的問題有相對應的目標函數來最佳化他。在機器學習中我們的目標函數是最小化訓練誤差,因此我們要在假設集合中挑出一個訓練誤差最小、或是與真實情況最接近的模型。 **梯度下降演算法** 梯度下降演算法可用於大部分的最佳化問題,也是訓練神經網路最核心的方法。假設今天有一個函數fθ,這個函數帶入不同的θ值會有不同的輸出值,而今天想要最小化這個函數,同時也想要知道他最小能小到多小,以及他的θ長什麼樣子。梯度下降演算法會隨便選一個θ開始並求出梯度,加上負號來讓他往低的地方走,就像滾下山坡的意思,每次都往最低的、可以滾最快的方像滾下去,同樣的θ變化量,梯度越抖就可以走越遠,反之可以走越近,以此為依據重複這樣的次數,將可以找到一個最低的點,或是接近於最低的點。梯度下降核心的公式為先取一個θ並決定往哪個方向滾,α為學習率,決定要滾多遠來更新出下一個θ,而下一個θ則當作下一次運算中的起始θ,重複很多次此步驟後,起始點就會接近fθ的最低點。若今天換到一個二維的函數,由多個θ所組成,也可以想像是一個機器由多個旋鈕所組成,這時就要一個一個調。對每一個θ單獨做偏微分後,就可以求出要往哪個方向滾,而這個梯度也就變成了一個由很多θ合成出的向量。二維函數做梯度下降可以想像成一個二維的平面上有一個凹槽,有一顆球沿著他的邊緣滾到最忠心的洞中。 ![](https://i.imgur.com/TcFNVfn.png) 梯度下降演算法是由梯度和學習律所組成的,梯度指引正確的方向,學習率決定往前走多遠。梯度下降時有可能會卡在局部最優而走不到全局最優,這時就要加入隨機噪音(隨機干擾)來將目前的θ有機率推出局部最優並到全局最優。梯度下降時學習率也扮演重要關鍵,學習率必須依據梯度來決定θ的變量,避免θ走太慢以至於要訓練太多次或θ走太快以至於θ超越最優值而要不斷地往回走。 隨機與批次梯度下降演算法 --- 一次把所有資料都丟進去學習會導致要算太多次梯度,雖然最準但是會花太多時間與資源,這時就要用到隨機梯度下降或批次梯度下降。隨機梯度下降演算法會隨機抽一筆資料並往用它來計算出的梯度去做移動,但這有可能會導致一下走東一下走西,甚至會原地打轉,因此隨機梯度很快但誤差很大。批次梯度下降演算法可以想像成一個擇中方案,一次取部分的資料來做訓練,不但誤差不會太大,計算量又可以被接受。 ![](https://i.imgur.com/0FJ4Pzf.png) 計算梯度 --- **損失函數對輸出層梯度** 損失函數在計算上可以看作是一個節點,當神經網路的最後一層把輸出丟給這個節點時,這個節點會套用真實標籤來計算出損失,接著再以向後傳遞計算,也就是損失對輸出的微分(當輸出曾改變一點點時對損失的改變)。回歸問題可以直接輸出減去標籤,而分類問題則是將輸出的機率分佈減去標籤的One-hot Encoding矩陣,算出來後就可以當作往後計算(向後計算)的起點。 ![](https://i.imgur.com/bLyAFPu.png) **損失函數對隱藏層梯度** 層跟層之間傳遞時,要把l層的微分傳到l-1層,也就是往回推的前一層。從數學式來看,用連鎖律把公式拆開,中間會經過一個激活函數g(z),在數學上可以直接把激活函數做微分,微分後的激活函數再用連鎖律把再往下推後的層全部乘起來,dloss/dLl是這一層,乘上激活函數的微分dLl/dZl後,再乘上和現在這一層有關的W(參數)矩陣的轉置(逆著算裡面的值),就可以得到層對損失的梯度。 ![](https://i.imgur.com/yxRp2Wl.png) **計算隱藏層的梯度** 每次計算隱藏層會有兩個參數,分別是W權重和b偏差。從計算圖來看,上一層傳遞下來的損失會傳到W,數學式上把這一層乘上激活函數的微分再乘上下一層的轉置,就可以得到權重對損失的梯度。層與權重是偶合的,求層對損失的梯度就乘上權重,求權重對損失的梯度就乘上層。對於偏差也是一樣,只要將這一層乘上激活函數的位分就可以得到偏差對損失的梯度。 ![](https://i.imgur.com/MxNfwzN.png) ![](https://i.imgur.com/SQmJ7ui.png) **更新參數** 當訊號傳入每一層時,會接連傳入權重和偏差中,這時就會產生一個要計算的θ參數所組成的矩陣,每個θ參數減去預先設定好的α學習率後,再用新的θ參數與訓練資料來跑一遍神經網路來取得損失,如此下來重複步驟,便可以達到自動更新神經元參數。 ![](https://i.imgur.com/Zx7dRTL.png) 訓練神經網路時的困難 --- **區域最小值** 梯度下降演算法不一定保證能找到最小值,這跟你想要優化的函數有關,如果函數本身比較崎嶇,擁有很多區間最小值而非全局最小值,就會有數值卡在區間最小值的問題。但當你的神經網路變得比較大、比較深時,就會出現很多接近於全局最小值的局部最小值,這時就可以不用擔心區域最小值的問題,因為他們的表現都差不多。 ![](https://i.imgur.com/pwVNdft.png) **鞍點** 鞍點並不是最大值也不是最小值,但他的梯度偏偏是0,就像一個馬鞍的鞍點,若你在鞍點上放一顆球他並不會滾動,這時就要加入一些有噪音(干擾)的梯度來讓這顆球擾動,並且順利滾下鞍點。 ![](https://i.imgur.com/Cl1CtCn.png) **梯度消失** 層和層傳遞時訊號會衰減,因為會經過激活函數,在反向傳遞時乘上激活函數的微分有可能為變成0,就如下圖Sigmoid和Relu的微分後,在某些點的值為0。Sigmoid在反向傳遞時會把訊號越乘越小,只有在某些點才會被順利傳遞,反之Relu卻可以保留原來的訊號並順利傳遞,因為他的值都是常數。 ![](https://i.imgur.com/BXOL57R.png) 拋棄層與批次正規化 --- **拋棄層** 拋棄層是用來增加神經網路的一般性,我們希望假設模型能在任何時候表現都跟真實模型一樣好,這時模型就不能太過複雜,拋棄層會對神經網路做一些限制。每一個神經元不一定隨時都有工作,因此可以想像成在參與計算時,此神經元不存在,下圖中的P表示有一定的機率神經網路在參與計算時會呈現的模式,每個神經網路都有一個出現的機率,而最後的神經網路是依據某一些機率所組合成,因為每個子網路對於某些特定的資料會有很好的表現,最後的神經網路的表現理論上是所有子網路表現的機率分佈算出來的平均。加入拋棄層來砍掉一些神經元(通常是表現較差)可以降低模型的複雜度,最後可以得到一群比較剪得的神經網路所組合成的神經網路。 ![](https://i.imgur.com/CVPynu7.png) **批次正規化** 當資料很複雜時,每一個批資料和下一個批資料的差異可能很大,所以他的梯度修正會變來變去,對整體的訓練是很不好的,而且神經元的激活狀態會變異很大,看起來就像是不同資料餵進來的樣子,這時就要用到批次正規化的演算法。當批次資料進來時,把資料正規化,限制神經元活躍的程度和資料的影響力,這樣子求出來的梯度才不會差異太大,模型也不會因為資料差異太大而被破壞掉,以至於前面的訓練都白費掉。 ![](https://i.imgur.com/OiUKm1J.png) 其他筆記 --- * [人工智慧與機器學習](https://hackmd.io/@ivorchu/BkCeyJydd) * [深度學習](https://hackmd.io/@ivorchu/rJ3DPsgud) * [卷積神經網路](https://hackmd.io/@ivorchu/SkIIoLkOu) * [遞迴神經網路](https://hackmd.io/@ivorchu/Hkoaoildu) * [最新深度學習研究進展](https://hackmd.io/@ivorchu/SJLdGwPuO)