RNN訓練過程詳解

轉自:https://blog.csdn.net/yywan1314520/article/details/50483071

Hinton 第七課 。這裏先說下RNN有recurrent neural network 和 recursive neural network兩種,是不一樣的,前者指的是一種人工神經網絡,後者指的是一種深度神經網絡這裏指的是前者,這部分翻譯的不好,因爲之前沒怎麼接觸過RNN,不過就當理解意境吧,所以附上所有的ppt,看得懂的就看PPt,下面的是附帶說明,有些語句沒有那麼通順,所以就當意境了。

而且百科上居然有這麼多分類:

  1. 完全遞歸網絡(Fully recurrent network)
  2. Hopfield網絡(Hopfield network)
  3. Elman networks and Jordan networks
  4. 回聲狀態網絡(Echo state network)
  5. 長短記憶網絡(Long short term memery network)
  6. 雙向網絡(Bi-directional RNN)
  7. 持續型網絡(Continuous-time RNN)
  8. 分層RNN(Hierarchical RNN)
  9. 複發性多層感知器(Recurrent multilayer perceptron)
  10. 二階遞歸神經網絡(Second Order Recurrent Neural Network)
  11. 波拉克的連續的級聯網絡(Pollack’s sequential cascaded networks)

這一課中有個附帶的論文《A novel approach to on-line handwriting recognition based on bidirectional long short-term memory networks》,是07年的,還沒怎麼看。

一、序列建模:簡要概述

        這部分簡要介紹一些在序列上建模的模型,首先介紹最簡單那的模型,這也是迴歸的模型,就是試圖從之前的項中得到的序列來預測下一個項;然後介紹一些擁有隱藏單元且精心設計的變量;然後介紹一些不但有着隱藏狀態而且有着隱藏動態的有趣的模型,這些都包括線性動態系統和隱馬爾可夫模型。這些模型中大部分都是很複雜的,所以不期望一次就懂,提到這些模型的意圖是爲了展示如何將我們的模型也按照那樣的模型進行遞歸。


當我們想要使用ML來對序列進行建模時,通常希望能夠從一個序列轉到另一個序列,例如:在語音識別中,我們希望從英語單詞轉到法語單詞或者從聲壓序列轉移到單詞序列。

有時候我們沒有獨立的目標序列,這時候我們可以通過嘗試預測輸入序列中的下一項來得到一個teaching信號(應該是標籤吧),所以這個目標輸出序列可以是簡單的輸入序列中的下一步;這看上去比試圖在基於圖像中所有其他的像素來預測一個像素或者基於圖像其他塊來預測下一個塊要更自然;而其中的一個原因在於對於時間序列來說,很自然的去想預測下一個時間步上是什麼,然而對於圖像,就不清楚從那些地方來預測什麼,但是實際上在圖像上也有相似的方法,而且效果還不錯。

當我們預測序列中的下一項時,它就會模糊有監督和無監督之間的區別。我們使用給有監督學習設計的方法去預測下一項,但是我們不需要獨立的teaching信號,所以他其實是無監督的。


這裏在使用RNN去對序列建模前,先快速簡單的介紹下其他序列模型。對於一個簡單的序列模型而且沒有記憶的來說,就是一個自迴歸模型:先得到許多序列中之前的項,然後嘗試去預測下一個項,就像是在基於之前項的權重均值一樣,之前項可能是獨立的值或者是一整個向量。在線性自迴歸模型中,只是將之前項進行權重均值操作然後去預測下一項。

在通過加上隱藏單元就能將模型變得複雜起來。所以在前饋網絡中,我們會先得到之前的輸入項,將它們饋送到隱藏單元,然後預測下一項。


記憶列表模型只是在序列上用來分類的一種模型,我們能夠通過其他方法來生成序列。一種非常自然的生成序列的方法是建立一個有着自己內部動態的多隱狀態模型。隱狀態的進化是依據它內部動態而定的,而且同時也可以生成觀測值(就是預測值),從而可以得到很多不同的模型:1、信息可以在他的隱狀態中存儲很長一段時間,不像之前的那些無記憶模型,它沒有簡單的標準去判別回頭看多遠才能不影響後面的預測;2、如果隱狀態的動態是有噪音的,而且從隱狀態中生成輸出也是有噪音的,那麼通過觀察一個這樣的生成模型的輸入,是沒法知道他的隱狀態是什麼樣子;3、我們所能做的最好的就是在基於所有可能的隱狀態向量的空間上推測概率分佈,可以知道他在空間中的某些位置,而不在空間中的其他位置,但是也沒法獲得準確的信息。

所以在這樣的生成模型中,如果想通過觀察他的生成的觀測值然後去試圖推測它的隱狀態是什麼,那通常是很難的,但是這裏有兩種類型的模型,他們的隱狀態是比較容易計算的,也就是有着一個相對簡單的計算去允許我們從可能影響數據的隱狀態向量上推測概率分佈,當然如果的確這麼幹了,而且應用到了真實數據上,那麼就假定這些真實數據都是由模型生成的。所以這就是我們在建模的時候所做的事情,我們假設數據是由模型生成的,然後在基於這些數據的基礎上推測這些模型的內部狀態。接下來的三個ppt是基於那些已經知道這兩類隱狀態模型的人來介紹的:1、介紹RNN與其他標準模型的不同,如果不明白這兩種標準模型,那麼沒關係,這裏不是重點。


上圖就是其中的一個標準模型:線性動態模型。它廣泛的應用於工程中,這是一個有着實值隱狀態的生成模型,這些隱狀態是有着線性動態的,如上圖中紅色箭頭指示的,這些動態是有着高斯噪音的所以隱狀態可以進化概率(evolves probabilistically)(就是隱狀態的概念可以變化的意思吧);如上圖中驅動輸入部分是直接影響着隱狀態的,而隱狀態又可以決定輸出層並去預測系統的下一個輸出(應用:追蹤導彈),所以我們需要去推導出它的隱狀態。

實際上,最早使用高斯分佈的例子是從有噪音的觀測值中追蹤行星。高斯(人)指出,如果加入了高斯噪音,那麼就能得到一個很好的結果,因爲如果將高斯進行線性轉換,得到的還是高斯,因爲線性動態系統中所有的噪音都是高斯,所以到目前爲止,基於給定觀測值上的隱狀態的分佈(在給定輸出的情況下)還是高斯,因爲協方差也是全高斯,所以計算上比較複雜,但是卻能高效的計算,有一個技術就叫做“卡爾曼濾波”(當年卡爾曼在nasa上和那誰說了下,結果就被應用了,可以用來捕捉飛船軌跡)。這是一個高效的遞歸方法去在給定一個新的觀測值的情況下更新隱狀態的表徵。

總結:給定系統輸出的觀測值,我們不能確定隱狀態是什麼,但是我們能通過估算一個高斯分佈來假設可能的隱狀態是什麼。當然,這裏的前提條件是我們的模型是在基於觀測的真實數據上正確的模型。

另一種不同的隱狀態模型是使用離散分佈而不是高斯分佈,叫隱馬爾可夫模型(HMM).。因爲他基於離散數學,所以計算機科學家才更加喜歡這種。在HMM中,隱狀態包含了N種選擇,也就是狀態的數量,而系統一般只處在其中一個狀態上,狀態之間的轉換叫做概率,是通過一個轉換矩陣(元素就是概率,這裏可以參考網易 Ng的機器學習課程中HMM的章節)控制的,也就是如果處在時刻 1 ,狀態1,想要知道時刻 2 下狀態 3 的概率。這個輸出模型通常是隨機的。所以系統內的狀態不能完全決定輸出,在輸出上有許多的變量,能表示每個狀態,所以我們不能確定基於給定的輸出得到的狀態是什麼。因爲這個狀態是隱藏的,所以叫隱狀態。因爲歷史原因,一個NN中的不可見的單元都叫做隱藏單元,這裏是借鑑於NN中的叫法。

因爲在n個狀態用n個數字來表示不同的概率分佈是比較容易的,所以HMM中可以用離散狀態來表示概率分佈,所以即使不知道他是什麼,他內部確切的狀態是什麼,還是能夠輕鬆的表示概率分佈。從HMM中預測下一個輸出需要知道他的內部可能的隱狀態,所以還是需要在概率分佈上下手。基於動態規劃上的一個簡單的方法可以讓我們在處理這些我們得到的觀測值的基礎上計算隱狀態的概率分佈。一旦我們知道了分佈,那麼就得到了一個優美的HMM學習算法,這也是爲什麼它適合語音的原因。在1970年代,它們就被用在語音識別上。


在HMM上有個根本的侷限性,當我們考慮在HMM生成數據的時候到底發生什麼,就能理解侷限性到底在哪。在每個生成的時刻,它選擇隱狀態中的一個狀態,所以如果有n個隱狀態,那麼存儲在隱狀態上的時間信息就差不多有log(n)位,這些就是它目前乾的所有已知的事情。

現在讓我們考慮一個HMM能夠從前一半得到的utterance中傳達多少信息到後一半。假設已經生成了前一半的utterance。現在去生成後一半(它的前一半的記憶存儲在包含的n個狀態中,所以他的記憶只有log(n)位信息):爲了對比前一半去生成後一半,我們必須要句法匹配(所以數量和時態需要一致);同樣也需要語義匹配(不可能句子的後半部分的語義完全不同於前半部分),同樣語調也是需要匹配,不然前面和後面的語調看上去完全不一樣就顯得很怪異了;還有其他東西需要匹配:說話人的口音,速率,聲響,聲道揚聲器的特點等。所有的這些都必須讓前半部分的句子和後半部分的句子搭上。所以如果想用HMM去生成一個句子,這些隱狀態需要將前半部分的信息都傳達到後半部分。

現在的問題就是所有的這些方面需要100位來表示信息,所以將前半部分的這100位信息傳達到後半部分,這也意味着HMM需要2 ^100個狀態(一個輸出表示兩個狀態,開,關),這太大了。


所以,這裏就考慮到了遞歸的方法了,它們有着更高效的方法來記憶信息。它們的強大在於通過將分佈式隱狀態的兩種屬性很好的結合了起來,也就是說,一次可以激活好幾個不同的單元,所以能夠一次同時記憶好幾個不同的事情;它們不但不止擁有一個激活單元,而且還是非線性的,一個線性動態系統有着整個隱狀態向量,所以在一個時刻可以得到不止一個值,但是這些值都包含着線性的行爲,所以推理起來容易,在RNN中通過將動態變得更加複雜,就能允許用更復雜的方法來更新隱狀態。

在有足夠的神經元和時間下,一個RNN可以計算計算機允許計算範圍內的任何事情。


所以線性動態系統和HMM都是隨機模型。因爲這些動態和由潛在狀態得到的觀測值的結果都是包含着內在的噪音的。所以建模的時候就需要注意一些問題了:在基於隱狀態上的後驗概率分佈(不論是在線性動態系統還是HMM中)是目前爲止看到的數據的一個決定性函數,也就是說這些系統的推導算法還是概率分佈,而這些概率分佈都只是一羣數字,而且這些數字決定着目前爲止數據的結果。

在RNN中,這些數字構成了RNN的隱狀態,而且它們也非常像這些簡單隨機模型的概率分佈。


所以問題就是什麼樣的行爲會出現在RNN中:它們可以是振盪的,這對於行爲控制是明顯的好事情,例如:當你在走路的時候想要知道你的步伐的週期性振盪;可以設置點吸引子,這可以用來檢索記憶(後面會介紹到的hopfield網絡是通過設置點吸引子來存儲記憶),所以在是有着一些粗略 的想法去進行檢索,然後通過讓系統穩定到一個狀態點上,並將這些狀態點對應於所知道的事情,通過設置到這些狀態點上,就能檢索一個記憶了;如果在合適的制度(regimes這裏估計是字幕錯誤,不過個人覺得想成規則應該還好)下設置權重的話,它們還可以是混亂的,通常來說,混亂的行爲不利於信息處理,因爲在信息處理中,希望行爲是可靠的。但是在某些情況下這是個好想法,如果在面對一個更聰明切覺得不可能戰勝的對手的時候,隨機可能是一個好主意,也就是混亂(這不就是看天命?);另一個關於RNN的好處在於,很久以前,Hinton想讓RNN更強大,通過使用它的隱狀態的不同的子集來執行許多不同的小程序,而這些小程序的每一個都能抓取一塊知識,而且所有的這些都能並行運行並以更復雜的方式交互。

可惜的是,RNN的計算能力使它很難被訓練。許多年來,我們不能利用RNN的計算能力。但是它卻有很多英雄式的影響,例如:Tony Robinson通過使用一個RNN來做語音識別器,他做了許多工作,在晶片機上進行並行計算,但是也只有最近,纔有人通過RNN作出了比他好的結果。

二、用BP來訓練RNN

        這部分介紹在基於時間上用BP來訓練。這也是在RNN上使用的標準訓練方法。而且如果觀察在RNN和一個一個時間步前進一層的前饋NN之間的對比發現這個等式還是相當簡單的,這部分還會談論提供輸入和理想輸出給RNN的方法。


上圖中顯示的是一個簡單的有着三個相互連接的神經元的RNN,並假設在連接上有1 的時間延時,而且這個網絡是在離散時間上運行的,所以時鐘是整數。理解如何訓練RNN的關鍵在於將RNN與一個前饋網絡(RNN擴展到時間上的前饋網絡)等同起來。RNN以許多初始狀態作爲開始,在上圖中底部是時刻爲0 的時候,通過使用許多連接得到一個新的狀態 爲時刻 1,然後使用相同的權重得到另一個新的狀態,以此反覆,所以這很像一個權重在每一層一直是一樣的前饋網絡。


BP是很擅長當權重都是受限的時候來進行學習的,在CNN上有介紹。我們可以在BP中很容易的合併任何的線性約束,所以如果權重沒有受限的話,我們可以嚮往常一樣計算梯度,然後通過修改梯度使得能夠迎合這個約束(意思就是如上圖一樣,簡單的修改以前介紹的BP來在RNN上使用修改後的BP)。如果開始的時候W1 =W2,那麼只需要確保W1修改的值等於W2修改的值,首先通過求W1的導數,然後求W2的導數,然後將它們相加或者求平均值,然後將這個值應用到更新W1和W2的過程中,所以如果權重開始就滿足約束,那麼他們還是會持續的滿足約束。


通過時間的BP算法只是在將RNN視爲一個層次化、有着共享權重的前饋網絡上用BP訓練的稱呼,只是讓我們記起這是在時間領域內使用BP罷了。前饋傳播在每個時間步上構建一層所有單元的激活層;然後迴向傳播計算在每個時間步上的誤差導數,這就是他爲什麼稱之爲BP through time。經過後向傳播後,將每個權重上所有不同時刻的導數進行相加,然後通過同樣的數值(和或者是所有導數的均值)來更新所有的權重。


上圖是一個刺激性的額外問題(就是關於神經元激活狀態的),如果我們沒有指定所有單元的初始化狀態,那麼對於一些隱藏或者輸出單元,我們就需要指定具體的初始化狀態。我們只是將這些初始狀態設置一個默認值例如0.5,但是這個值也許不是更合理的初始值。所以我們可以通過學習來得到更合理的初始值,將它們視爲參數而不是激活值,並用與學習權重一樣的方法來學習它們。可以通過隨機猜測一個初始值作爲所有非輸入層單元的初始狀態,在每個訓練序列(每個樣本)的最後,在基於所有方法上通過BP throuth time 算法回到初始狀態,這就給出了基於初始狀態上誤差函數的梯度,然後通過這些梯度來調整初始狀態,然後得到新的初始狀態,得到的新的初始狀態與之前的初始狀態略有不同。


有很多種方法來給RNN提供輸入:1、指定所有單元的初始狀態(例子:上圖中所有的單元),這也是我們考慮RNN的時候最自然的想法,就像一個受限權重的前饋網絡一樣;2、可以對所有單元的子集進行初始化指定(例子:上圖中輸入層);3、在所有單元的子集的每個時間步上指定狀態(例子:上圖中一列框出來的),這也可能是對於輸入序列數據來說最自然的方法了。


同樣的,也有許多方法去對RNN的目標進行指定。當我們將他視爲一個有着受限權重的前饋網絡時,自然的想法就是對所有的單元指定最合適的終極狀態(上圖最頂層部分,也就是輸出層)。如果試圖訓練它去學習吸引子,我們也許就會想這些合適的狀態不止是對最後時間步(上圖模型最頂層)上而是好幾個時間(例子:上圖倒數第二層)步上進行指定。這樣可以使模型穩定下來,而不是前饋很多狀態然後就不知道去哪了。所以通過對最後的幾個狀態進行指定,可以強化學習吸引子,並且BP可以將每個時間步上得到的導數加起來,所以在頂層開始的BP有着最終時間步的導數,然後往下加其他時間步的導數(如圖中列框起來部分)。所以在不同的層中擁有的導數其實是有着非常小的額外的影響(就是沒什麼額外影響)。如果我們指定一個單元子集的激活值(這裏假如是輸出層),最自然的想法去訓練RNN就意味着提供一個連續的輸出。

三、一個訓練RNN的簡單例子

        這部分介紹如何使用RNN去解決一個toy問題(就是玩具級別的問題)。這個問題是用來說明RNN可以幹而一般的前向NN不能幹的地方,也就是如何將兩個二進制數進行相加,接下來可以看到RNN的隱狀態是如何和有限狀態自動機中的隱狀態一樣解決相同的問題的。


所以考慮將兩個二進制數進行相加的問題,可以先訓練一個前饋NN來完成這個事情,上圖中右邊的圖顯示一個有着一些輸入和生成一些輸出的簡單網絡,那麼問題就來了,這時候必須要讓網絡知道輸入和輸出的最大數值,而且更重要的是,這裏的處理還不能應用在不同位數上,也就是說當學會如何將上兩個數值進行相加並得到結果,這時候相加的知識存儲在權重中,但是當考慮這個二進制數值的一部分時,知識也是存儲在不同的權重中的,所以不能得到一個自動生成的效果。(就是比如例子中的00100110,前面的加法知識和後面的加法知識不同,不是按照我們理解的那樣相加,而是當成樣本訓練而已,不遵循數學上定義的加法)

結果就是儘管可以訓練一個前饋NN,並且可以很好的將固定長度的數值進行相加,但是這種方法卻不好。


上圖是關於二進制加法的解釋。這裏顯示的狀態很像HMM中的隱狀態 ,只是他們不是真的隱藏罷了。系統是一個時刻一個狀態,即當輸入一個狀態,就代表一個動作,所以不論是輸出1還是0,當處在某個狀態時就是擁有某種輸入,也就是下一列中的兩個數字,這兩個數字會讓系統轉換到新的狀態。所以如果看上圖的右上方,系統處在carry狀態,並且只輸出1,如果系統遇見【1 1】(輸入爲【1,1】),那麼它就維持當前狀態不變,並且輸出1,如果輸入是【1 0】或者【0 1】那麼當前系統就轉移到下一個狀態並且輸出0(也就是右下角的狀態),如果系統遇到的輸入是【0 0】,那麼就轉移到左上角的no carry狀態並且輸出1。


所以一個二進制版本的RNN需要兩個輸入和一個輸出。在每個時間步上給定兩個輸入數字,而且在每個時間步上還需要一次輸出。強調下這裏的輸出是兩個時間步之前的列的值的輸出(上圖橘紅色框起來部分,這裏的time箭頭是不是反了?),這裏需要兩個時間步的延時是因爲需要一個時間步去基於輸入的更新隱藏單元,另一個時間步去基於隱藏單元生成輸出值。


所以網絡纔像上圖中那樣。這裏假設只有三個隱藏單元(這對於這個任務來說足夠了),雖然有着更多的隱藏單元可以讓它工作的更快,但是這裏三個足矣。

這三個隱藏單元都是完全互相連接而且連接是雙向的(不需要兩個方向上的權值一樣,不過通常來說也沒有相同的權值),隱藏單元之間的連接允許一個時間步上的模式可以給下一個時間步上的模式進行投票。

輸入單元有前饋連接到隱藏單元,相似的,隱藏單元有着前饋連接到輸出單元,這就是他如何生成輸出值的過程。


上圖是解釋RNN如何學習的。它從3個隱藏單元中直接學習4鐘不同的激活模式,而這些模式就是對應於之前的有限狀態自動機中的節點。我們肯定會將NN中的單元和有限狀態自動機中的節點混淆起來:有限狀態自動機中節點對應於RNN中的激活向量,這裏的自動機是被約束稱一個時間步只能處在一個狀態的情況。相似的,在RNN中隱藏單元也是約束成一個時間步只出現一個激活向量。

所以一個RNN可以模擬一個有限狀態自動機但是他的表徵確實相比指數級別的強大,在有着N個隱藏單元的情況下,那麼就有了2^N個可能的二進制激活向量,而且它只需要N^2個權重,所以它不需要全部用上所有的表徵能力,但是如果有bootlenec(瓶頸,雖然意思是這個,但是覺得這裏的意思應該參考 http://blog.csdn.net/shouhuxianjian/article/details/40795453 第四課中瓶頸意思,不是說性能受約束,而是某個地方放置一個特殊的隱藏層吧???)存在於RNN中,那麼他就能做的比有限狀態自動機更好。要注意到這裏輸入流中是每次只有有兩個獨立的事物(thing,翻譯成項也還好吧);一個有限狀態自動機需要對狀態的數目進行平方去處理每次只有兩個事物的情況;而一個RNN只需要兩倍的隱藏單元的數目,就能表達二進制向量的數目平方級別的信息(這裏意思就是RNN需要的節點比隱藏狀態自動機少)。

四、爲什麼訓練RNN這麼難

        這部分將會介紹梯度爆炸和消失的問題,正是因爲這個問題導致訓練RNN變得很困難。在很多年來,研究NN的人們認爲他們沒法對長時間依賴關係的網絡模型進行訓練。但是這裏在這部分的最後會介紹4種不同的方法來解決這個問題。


爲了瞭解爲什麼訓練RNN如此之難,首先就得了解一個在RNN中前饋和後向傳播(這裏不是BP的意思,是與前饋不同的反方向而已)到底有什麼不同。在前饋中,我們使用壓縮型函數,例如邏輯函數去阻止激活向量的爆炸(就是輸入到輸出,輸出是永遠在【0 1】之間不讓他發散出去),所以如上圖所示,每個神經元使用的就是邏輯函數激活(藍色曲線),他們沒法使得結果超過1 或者小於0,以此來阻止爆炸;在後向傳播上,卻是完全的線性的,大多數人們認爲這是很不可思議的,如果將網絡的最後一層上的誤差導數乘以2,那麼當使用BP方法的時候就會發現所有的誤差導數都被乘以了2.。所以如果觀察上圖中紅點(藍色曲線上的紅點)我們認爲這些都是前饋中的激活值所處的位置,當使用BP時,就會使用處在藍色曲線上紅點位置的梯度,所以紅線意味着在紅點處的tangent值(也就是斜率)。一旦完成了前饋,那麼tangent的範圍也就固定了,然後接着使用BP,這時候BP就像是在這些已經固定的非線性範圍上使用一個線性系統,當然每次使用Bp的時候這些範圍還是不同的,因爲他們都是由前饋來決定的,但是在BP過程中,他們還是線性系統,所以還是被線性系統特有的問題所困擾(當迭代的時候,它們不是爆炸就是消失)。


所以當我們用BP經過很多層的時候,如果權值很小,那麼梯度就會縮小,然後以指數級別變得更小,也就是說使用BP through time 的時候位於目標(輸出層)之前好幾層以前的梯度將會變得很小很小。相似的,如果權值很大,那麼梯度就將會爆炸,這也意味着當使用BP through time ,梯度將會變得很大,並且抹平一切知識(權值代表的信息)。

在前饋網絡中,除非這個網絡是很深的,不然這些問題還沒那麼糟,因爲通常來說椰子油很少的幾層隱藏層而已。

但是在長序列(例如100個時間步)上訓練一個RNN,如果梯度隨着BP增長,那麼就差不多以100爲指數增長,如果梯度隨着BP小時,那麼同樣也是以100爲指數消失,所以要麼爆炸,要麼消失。我們也許可以通過對權值的謹慎初始化來避免這樣的問題,最近越來越多的學術成果顯示確實謹慎的權值初始化可以讓網絡的工作做的更好。

但是即使是有着很好初始化的權值,還是很難去檢測當前輸出與許多時間步之間的輸入之間的依賴關係。RNN在處理長時依賴問題上比較棘手。


這裏是一個有關一個試圖去學習吸引子的系統梯度爆炸和消失的例子,假設我們試圖去訓練一個RNN,所以不論是以什麼狀態開始,都是以這兩個吸引子狀態中的一個結束的。所以這裏是學習一個吸引子的藍盆和一個吸引子的粉紅盆,假如我們在吸引子的藍盆中任何狀態開始,我們就會以相同的點結束,這也就是說在初始化狀態上微小的誤差不會讓結束的時候有什麼不同,所以最終狀態上關於初始狀態上變化的導數是0,也就是梯度消失,即當我們BP通過系統的動態的時候(就是BP through time)會發現從開始的地方几乎沒梯度。這當是吸引子的粉紅盆也是一樣的。

然而,如果我們開始的時候很靠近兩個吸引子之間的位置(邊界部分),那麼開始的地方就會有個微小的誤差,在分水嶺的另一邊就會使得在結束的時候有巨大的誤差,這就是梯度爆炸問題。也就是無論何時試圖去訓練這樣一種吸引子,RNN總是手梯度爆炸或者消失問題困擾。


上圖就是至少有四種方法來高效的學習RNN:1、長短時記憶:通過改變NN的結構使得能夠擅長記憶事物(這課下面詳細講解)。2、使用更好的優化方法去處理非常小的梯度(下一課講解),優化中的真正的問題在於檢測即使有着更小曲率的很小的梯度。Hessian-free 優化是按照NN來的,很適合幹這樣的事情。3、這個方法真的是一種躲避問題的方法,我們所要做的就是謹慎的初始化輸入到隱藏的權值,然後謹慎的初始化隱藏到隱藏的權值,然後後向從輸出到隱藏單元的權重,這裏的想法就是謹慎的初始化去確保隱藏狀態有着巨大的弱耦合震盪存儲,所以如果輸入序列,它將會混響(reverberation)很久,並且這些混響還能記憶輸入序列中發生的事情,然後試圖耦合這些混響到想要的輸出,所以在Echo 狀態網絡中學到的唯一的事情就是隱藏單元到輸出單元之間的連接,如果輸出單元是線性的,那麼就很容易訓練,所以這樣其實沒學到遞歸,知識通過使用一個固定的隨機遞歸位 罷了,知識謹慎的選擇,然後只是學習隱藏到輸出的連接而已。4、最後一方法是使用動量,但是是將動量初始化稱可以在第三種方法中使用的值,並使得工作更好。所以聰明的方法是找出如何對這些RNN網絡初始化使得它們擁有很好的動態,但是如果在有助於任務完成的方向上輕微的修改動態是有助於網絡更好的工作(也就是第四種方法添加動量)。

五、長時、短時記憶

這部分將會介紹一種訓練RNN的方法叫做長短時記憶。可以認爲一個NN的動態狀態是一個短時記憶。原理就是想要將這個短時記憶給延長到長時記憶,這是通過創建特別的模塊,通過允許信息封閉在裏面,然後當需要的時候將信息放出。在這過程中,門(形象的比喻)是關閉的,所以在這期間到達的信息都不會影響到記憶的狀態。長時記憶有着非常成功的應用,例如手寫識別,並贏得了一些比賽。


在1997年,Hochreiter和Schmidhuber發了一篇論文在神經計算期刊上,解決了如何讓RNN長時間記憶事情的問題。成功的讓RNN記憶長達幾百個時間步。

他們通過設計一個記憶存儲單元,在這個單元中使用邏輯、線性單元和乘法操作。

所以當邏輯寫門打開的時候,信息就可以進入記憶存儲單元。在這其中RNN剩下的部分決定了寫門的狀態,當剩下的部分想要存儲信息時,就將寫門打開(而且不論從剩下的部分的當前輸入到記憶單元的是什麼)存入單元。裏面的信息只要保持門開着就一直不變。同樣,網絡剩下的部分決定了邏輯保持門的狀態,如果它保持開着,那麼信息就會留着。最後從記憶單元中讀取信息到RNN的剩下的部分並且影響未來的狀態,這時候是通過打開讀門來讀取的,這裏是由網絡剩下的部分控制一個邏輯單元實現的。


這個記憶單元實際上存儲着一個模擬值,所以我們可以認爲他是一個有着模擬值的線性神經元,並且通過設置權值爲1來保持在每個時間步上自寫相同的值,所以信息就能一直存在那裏。這裏的爲 1 的權重是由保持門決定的,所以網絡的剩餘部分決定着那個邏輯保持門的狀態,如果處在爲1的狀態或者接近1 ,那麼信息只是在循環罷了,上圖中的1.73的值就會一直存在,直到網絡剩下的部分說不想要這個值了,那麼所要做的就是將保持門設置成0,然後信息就消失了。爲了存儲信息到記憶單元,網絡剩下部分需要打開寫門,然後不論是從RNN剩下的部分中得到的輸入是什麼都會寫入到這個記憶單元。相似的,爲了從這個記憶單元中讀信息,網絡的剩下部分需要開啓邏輯寫門然後記憶單元中的值就會出來,然後影響RNN剩下的部分。

使用邏輯單元的關鍵在於我們可以通過BP 來穿過他們,因爲他們有着很好的導數,也就是說我們可以學習並使用這種循環很多個時間步。


(一個時間步就是一個1.7爲劃分,視頻中是動態講的,我這裏只是把最後的狀態截圖而已)這裏介紹BP通過一個記憶單元是怎樣子的。首先有個前饋操作:在初始時刻上,假設保持門是爲0,所以可以擦除之前存儲在記憶單元中的信息,然後把寫門打開(設置爲1),所以從RNN剩下部分來的1.7就會寫入到記憶單元中,然後現在不想要進行讀操作,所以將讀門設置成0,然後將保持門設置成1,或者說是NN的剩下部分將保持門設置成1,這也就是說這個值又會寫回到記憶單元中,這就是存儲了。

在下一個時間步上,將寫門設置成0,然後將讀門設置成0,所以信息不受網絡的其他部分影響。然後接着一個時間步,將保持門設置稱1,所以信息可以接着存儲一個時間步,然後將寫門設置稱0,所以沒有信息可以寫入,但是現在想檢索這個信息,那麼就設置讀門爲1,然後這個值1.7就會從記憶單元中出來然後影響網絡的其他部分。如果我們不再需要它了,那麼就把保持門設置成0,然後信息就會被擦除了。現在如果觀察我們索引的時候出來的1.7,然後回頭觀察1.7進來的時候,這一路上的小三角型符號到下個小三角型符號都是1,也就是說這時候的權值是爲1。所以正如我們回頭沿着路徑觀察,不論我們在基於1.7上得到的誤差導數是什麼都是當檢索的時候Bp從存儲的1.7上獲得的。如果想要檢索一個更大的值,那麼就將信息送回然後告訴他需要更大的值(也就是BP通過誤差導數來調整並修改1.7的大小),記得一旦將相關的門設置成1,那麼在BP信號中就沒有衰減了(因爲這時候不需要調整了,所以BP自然用不上了)。

剛好這樣的特性就是我們所需要的,當然,如果這裏的邏輯門有些許的輕微衰減,但是如果衰減足夠小,信息還是能夠堅持幾百個時間步的。


現在來看一個採用長短時記憶的RNN完成的任務。這個任務對於RNN是輕而易舉的,就是讀取草書書寫(估計就是人的各種手寫字吧)。輸入就是由(x,y)代表筆尖座標的序列加上筆是否在紙上的信息。輸出就是識別字符的序列。Graves和Schmidhuber在2009年顯示有着長短時記憶的RNN特別的適合幹這個任務。到目前爲止,他們也是當前最好的能夠完成這個任務的系統(這個課程出來的時間),並且Hinton認爲加拿大post已經用他們來讀取手寫字體了。而在2009年這兩個人沒有使用筆的座標作爲輸入,他們只是使用了小圖像序列,這也就是說他們可以處理光學輸入而不知道筆的時間(估計就是筆上紙到離開紙的時間吧),他們是通過收集寫好的紙然後進行讀取的。


所以這裏介紹一個Alex Graves的系統的實例,這個系統是工作在筆座標上的(就是通過筆在紙上劃過的座標,這具有實時性的意義,就是你寫一個字,還沒完成的時候,有可能這個網絡就能識別出你要寫的是什麼字了)。在後續的視頻(Hinton說的視頻,就是最下面那張圖)中,可以看到四條信息流,

1、頂層行顯示他們所識別的字符,因爲這個系統不會修改他的輸出,所以在做這個艱難的決定(輸出的結果到底是什麼的問題)的時候需要延遲一小會兒來觀察後續一小段的未來來幫助網絡解決這個模棱兩可的問題。

2、第二行顯示記憶單元的子集中的狀態,然後會注意到當識別一個字符的時候他們是如何重置的。

3、第三行顯示實際的寫的東西,而網絡所全部能看見的就是筆尖的 x 和 y 的座標,然後加上一些這個筆是否往上還是向下的信息。

4、最後第四行顯示的是更復雜的。他顯示梯度通過所有的路徑後向傳播到 x y 的位置。所以你所能看到的就是最有可能的字符,如果從那個字符上後向傳播,然後問道怎樣可以使得這個最有可能激活的字符變得更加的激活(就是更加的確定),那麼就需要去觀察到底輸入的哪一位纔是影響真實字符的概率的。所以你所做的決定都是基於以往發生的信息上的。 

8:44-9:15,下面這張圖就是一個從左到右的過程,下面第三行不斷的寫,第四行顯示筆尖的位置,然後第二行顯示網絡的訓練,然後第一行得到結果。(哇,這個網絡好厲害。)

            </div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章