# 李宏毅_ML_Lecture_21-1 ###### tags: `Hung-yi Lee` `NTU` `Machine Learning` [課程撥放清單](https://www.youtube.com/channel/UC2ggjtuuWvxrHHHiaDH1dlQ/playlists) ## ML Lecture 21-1: Recurrent Neural Network (Part I) [課程連結](https://www.youtube.com/watch?v=xCGidAeyS4M&list=PLJV_el3uVTsPy9oCRY30oBPNLCo89yu49&index=30) ### Example Application ![](https://i.imgur.com/chPElpL.png) RNN應用範例,i.e. Slot Filling,使用者說了一句話,系統必需從語句中取得目的地<sub>(Destination)</sub>以及到達時間<sub>(time of arrival)</sub> ### Example Application ![](https://i.imgur.com/CwEAMqz.png) 對於Slot Filling的問題,也可以利用feedforward network來解,輸入則是一個詞彙,i.e Taipei,但在此之前需要將詞彙先以向量來表示<sub>(見下方兩小節說明)</sub>,輸出為詞彙屬Slots的機率,如Taipei屬Destination或time of arrival的機率。 ### 1-of-N encoding ![](https://i.imgur.com/lwFnLvF.png) 最簡單將詞彙以向量來表示的就是1-of-N encoding的方式, ### Beyond 1-of-N encoding ![](https://i.imgur.com/a0GZLMl.png) 利用1-of-N encoding會遇到的問題在於某一個詞彙可能從來沒有見過,這時候我們會在向量內加入一個『other』來表示沒見過的詞彙,又或者可以利用詞彙字母來表示向量,這樣就可以避免遇到沒見過的詞彙,i.e. Word hashing,apple對應到的三個字母為1,其餘為0。 ### Example Application ![](https://i.imgur.com/2M5uHZZ.png) 單純的利用feedforward network判斷詞彙是否為Slot可能不是那麼適用,因為不同的語句之間有不同的意函,但feedforward network無法判斷,以上圖例,一個為arrive,一個為leave,但feedforward network只會判斷Taipei與November 2nd,卻不會判斷arrive與leave的差異。 這時候我們希望NN可以擁有記憶力來記錄語句的上下文,根據不同的上下文來產生不同的輸出。 ### Recurrent Neural Network(RNN) ![](https://i.imgur.com/fLHBAmE.png) RNN中,每一層Hidden Layer的輸出都會被存到memory中,後續的過程中就不會僅是考慮輸出,還會考慮memory中的值。 ### Example ![](https://i.imgur.com/pbg4VDy.png) ![](https://i.imgur.com/WoMWMsx.png) ![](https://i.imgur.com/fg5SXoI.png) ![](https://i.imgur.com/HmCHZIK.png) 舉例來說,權重皆為1,沒有偏差單元(bias),activation function為線性,memory初始為0,輸入為Sequence(1,1,1,1,2,2)。 1. 第一次輸入 1. (1, 1) 2. memory(0, 0) 3. output(4, 4) 4. update memory(2, 2) 2. 第二次輸入 1. (1, 1) 2. memory(2, ) 3. output(12, 12) 4. update memory(6, 6) 2. 第三次輸入 1. (2, 2) 2. memory(6, 6) 3. output(32, 32) 4. update memory(16, 16) 輸入的序列有其順序性,從上面簡單的範例可以發現到,調換了順序會造成產生的結果不同。 ### RNN ![](https://i.imgur.com/2Zx6mAJ.png) 以『arrive Taipei on November 2nd』為例,模型首先輸入『arrive』,並計算『arrive』屬於每一個slot的機率$y^1$,接著輸入『Taipei』,這時候『Taipei』除了考慮自己之後也同時考慮了$a^1$<sub>『arrive』</sub>再輸出機率$y^2$,一直到所有的詞彙計算完畢。 注意到上圖中有三個輸入、輸出並不代表它是三個神經網路組成,它是一個神經網路在三個時間點上被使用了三次,並且相同的顏色代表著相同的權重 ### RNN ![](https://i.imgur.com/UwRWPnC.png) 加入了記憶單元之後,雖然第二個單字一樣是『Taipei』,但因為第一個單字的不同會造成記憶單元的不同,最後所得的輸出就不會相同。 ### Of course it can be deep ![](https://i.imgur.com/9d3H6Ck.png) RNN也可以很深,每一個Hidden Layer都保存它的memory,在下一個時步計算的時候再提出一起計算。 ### Elman Network & Jordan Network ![](https://i.imgur.com/0RLRiUK.png) * Elman Network: * 如前幾個單元所述即為Elman Network * Jordan Network: * 所記憶的並非每一個Hidden Layer的輸出,而是最後的輸出$y^t$,在下一個時步再讀入計算。 傳說,Jordan可以擁有較好的效能,這是因為Hidden Layer是沒有目標的輸出,較難控制學習到的資訊,而最後的output是有的。 ### Bidirectional RNN ![](https://i.imgur.com/UBAOntm.png) RNN不僅單向依時步向前執行,也可以逆向執行,兩個RNN共同將輸出給予Output layer來得到結果。 這可以讓RNN所讀的資訊較廣,一個句子讀完了來回完整的句子之後再決定詞彙的slot。 ### Long Short-term Memory(LSTM) ![](https://i.imgur.com/F1Q528G.png) 相較於稍早所提的RNN,LSTM的memory更為複雜,存在著3個gate,4個input,1個output。 * 3個Gate 1. Input Gate: 某個neruon的output想寫入Memory Cell之前,要先經過input gate,超過閥值才有辦法把值寫入Memory Cell 2. Output Gate: 決定是否允許其它neuron讀取Memory Cell的值 3. Forget Gate: 決定什麼時候Memory Cell清空 * 4個Input 1. 想寫入Memory Cell的input 2. 操控Input Gate的訊號 3. 操控Output Gate的訊號 4. 操控Forget Gate的訊號 其中3個Gate的寫入、讀取、忘記與否皆由神經網路自行學習。 ### Long Short-term Memory(LSTM) ![](https://i.imgur.com/rIhBCY7.png) 仔細觀察數學式如上圖: * 符號約定: 1. Input: $z$ 2. 操作Input Gate: $z_i$ 2. 操作Forget Gate: $z_f$ 2. 操作Output Gate: $z_o$ 3. Output: $a$ 4. Memory Cell: $C$ * 流程說明: 1. $Z$通過sigmoid function得到$g(z)$ 2. $Z_i$通過sigmoid function得到$g(z_i)$ 3. 1、2所得相乘得到$g(z)f(z_i)$ 4. $Z_f$通過sigmoid function得到$g(z_f)$ 5. Memory Cell乘上Forget Gat的值,得到$cf(z_f)$ * 當forget gate的輸入為0,那代表之前存在memory cell的值會變0 * 當forget gate的輸入為1,那代表之前存在memory cell的值會保留 7. 將5、3相加得到$c'$ * $c'=g(z)f(z_i)+cf(z_f)$ * 當input gate的輸入為0,那就相當於沒有更新 * 當input gate的輸入為1,那就相當於直接把$g(z)$當做輸入 8. Memory Cell $c$變為$c'$ 9. $c'$通過h function得到$h(c')$ 10. $z_o$通過sigmoid function得到$f(z_o)$ * 當output gate的輸入為1,代表可以通過 * 當output gate的輸入為0,則$f(z_o)$為0,代表無法通過 11. 9、10相乘得到$a=h(c')f(z_o)$ * activation function: * 通常選擇使用Sigmoid Function,因為輸出是介於0、1之間的值,用以代表gate被打開的程度 ### LSTM - Example ![](https://i.imgur.com/XTMBVVX.png) 範例說明: * input為三維的vector * output為一維的vector * 神經網路中只有一個LSTM的cell * $x_2$為1的時候,$x_1$的值就會被寫入memory * $x_2$為-1的時候,$x_1$的值就會被重置 * $x_3$為1的時候,output gate才會開啟,才看的到output * 初始memory為0 上排的值是代表每一個時步結果,在timestep為3的時候因為timestep2的$x_2$為1,因此記憶,以此類推。 ### LSTM - Example ![](https://i.imgur.com/6l0dHom.png) 上圖是實際執行一個過程,依之前所提,一個memory cell會有四個input,三個gate,一個output,權重與偏差單元都是學習過程中學習到的,範例中假設我們已經得到相關學習參數並且初始memory cell為0。 * input: * 僅第1個權重有值 * input_gate: * 僅第2個權重有值,並且偏差單元為-10,這代表$x_2$為0則輸出為-10,經過sigmoid之後是接近0,因此關閉 * forget_gate: * 僅第2個權重有值,並且偏差單元為10,這代表平常是開啟狀態<sub>(開啟代表記憶)</sub>,在$x_2$輸入是很大的負值時才會啟動重置。 * output_gate: * 僅第3個權重有值,並且偏差單元為-10,代表必需$x_3$有值並大於偏差單元情況下才會輸出。 * memory_cell: init 0 計算: 1. input: (3,1,0) * input: 3 * input_gate: open * forget_gate: open * memory_cell: 3 * output_gate: close * output: 0 1. input: (4,1,0) * input: 4 * input_gate: open * forget_gate: open * memory_cell: 7 * output_gate: close * output: 0 1. input: (2,0,0) * input: 2 * input_gate: close * forget_gate: open * memory_cell: 7 * output_gate: close * output: 0 1. input: (1,0,1) * input: 1 * input_gate: close * forget_gate: open * memory_cell: 7 * output_gate: open * output: 7 1. input: (3,-1,0) * input: 3 * input_gate: close * forget_gate: close * memory_cell: 0 * output_gate: close * output: 0 ### Original - Network ![](https://i.imgur.com/UUHmGm7.png) ![](https://i.imgur.com/eRRTy8e.png) 原始神經網路中存在著很多神經單元,將input乘上不同的weight之後做為不同神經單元的輸入,而每一個神經單元都是一個function,輸入一個scalar,輸出另一個scalar。 而LSTM在於,只要將神經單元想成是Memory Cell就可以了,並且一個輸入會影響Memory Cell中的三個gate,就是四個input,原始神經網路中很單純的就是一個input對應一個output,在LSTM是四個input對應一個output,也因此LSTM的參數量會是一般神經網路的四倍。 ### LSTM ![](https://i.imgur.com/Iq3VtqH.png) 假設目前有一排的LSTM的Memory Cell,每一個Cell都存著一組Scalar,將所有的Scalar接起來成為一個Vector,即$c^{t-1}$ 在時間點$t$輸入一個Vector,$x^t$,經過transform之後變為$z$,$z$中的每一個dimension代表操控一個相對應的Cell<sub>(即$z$的dimension會相等於Memory Cell)</sub> 接著$x^t$再乘上另一個transform得到$z^i$,它的dimension依然相等於Memory Cell,操控相對應的input gate。一樣的,會有$z^f, z^o$來操控forget gate與output gate。 這四個Vector就是操控Memory Cell的關鍵。 ### LSTM ![](https://i.imgur.com/qWFeRF9.png) 上圖是LSTM計算流程的說明: 1. 時步$t$輸入了$x^t$ 2. transform之後得到$z$,與input gate的$z^i$相乘<sub>(元素相乘)</sub> 3. $z^f$與上一個時步的Memory Cell,$c^{t-1}$相乘 4. output gate $z^o$與2、3相加結果相乘得到最後結果$y^t$ ### LSTM ![](https://i.imgur.com/DESfd1r.png) 上一小節中的步驟2、3相加得到的結果就是新的Memory Cell的值$c^t$,相同的計算方式進入下一個時步$t+1$,不斷循環。 注意到,真正的LSTM中的輸入會考慮上一個時步的output gate的值,如上圖中$x \rightarrow h^t$,也會考慮上一個時步的Memory Cell。 因此,操作LSTM的四個gate的同時你考慮這個時步的輸入、上一個時步的Memory Cell以及上一個時步的Hidden Layer的Output。 ### Multiple-layer LSTM ![](https://i.imgur.com/96ms9co.png) Keras中有LSTM的Module可以直接使用,不用過於擔心。(LSTM, GRU, SimpleRNN) GRU少了一個Gate,但少了1/3的參數,效能與LSTM差不了多少。