递归神经网络不可思议的有效性
遞歸神經網絡不可思議的有效性
發表于2015-09-03 21:48|?18710次閱讀| 來源karpathy.github.io|?36?條評論| 作者Andrej Karpathy
foundation神經網絡ProcessingcommandXMLPythonFilterAPIURL深度學習 allowtransparency="true" frameborder="0" scrolling="no" src="http://hits.sinajs.cn/A1/weiboshare.html?url=http%3A%2F%2Fwww.csdn.net%2Farticle%2F2015-08-28%2F2825569&type=3&count=&appkey=&title=%E9%80%92%E5%BD%92%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E6%9C%89%E4%B8%80%E4%BA%9B%E4%B8%8D%E5%8F%AF%E6%80%9D%E8%AE%AE%E7%9A%84%E5%9C%B0%E6%96%B9%EF%BC%8C%E6%9C%89%E4%BA%9B%E6%97%B6%E5%80%99%EF%BC%8C%E6%A8%A1%E5%9E%8B%E4%B8%8E%E4%BD%A0%E6%9C%9F%E6%9C%9B%E7%9A%84%E7%9B%B8%E5%B7%AE%E7%94%9A%E8%BF%9C%EF%BC%8C%E8%AE%B8%E5%A4%9A%E4%BA%BA%E8%AE%A4%E4%B8%BA%E6%98%AFRNNS%E9%9D%9E%E5%B8%B8%E9%9A%BE%E8%AE%AD%E7%BB%83%EF%BC%8C%E9%82%A3%E4%B9%88RNNs%E7%A9%B6%E7%AB%9F%E6%98%AF%E4%BB%80%E4%B9%88%E5%91%A2%EF%BC%9F%E5%B0%B1%E6%9C%89%E8%BF%99%E7%AF%87%E6%96%87%E7%AB%A0%E6%9D%A5%E5%B8%A6%E7%BB%99%E5%A4%A7%E5%AE%B6%E3%80%82&pic=&ralateUid=&language=zh_cn&rnd=1460969792107" width="22" height="16">摘要:遞歸神經網絡有一些不可思議的地方,有些時候,模型與你期望的相差甚遠,許多人認為是RNNS非常難訓練,那么RNNs究竟是什么呢?就有這篇文章來帶給大家。遞歸神經網絡(RNNs)有一些不可思議的地方。我仍然記得我訓練的第一個用于?圖片字幕的遞歸網絡。從花幾十分鐘訓練我的第一個嬰兒模型(相當隨意挑選的超參數)開始,到訓練出能夠針對圖像給出有意義描述的模型。有些時候,模型對于輸出結果質量的簡單程度的比例,會與你的期望相差甚遠,而這還僅僅是其中一點。有如此令人震驚結果,許多人認為是因為RNNs非常難訓練(事實上,通過多次試驗,我得出了相反的結論)。一年前:我一直在訓練RNNs,我多次見證了它們的強大的功能和魯棒性,而且它們的輸出結果同樣讓我感到有趣。這篇文章將會給你展現它不可思議的地方。
我們將訓練一個RNNs讓它一個字符一個字符地生成文本,然后我們思考“這怎么可能?”
順便說句,在講述這篇文章的同時,我同樣會將代碼上傳到?Github?上,這樣你就可以基于多層LSTMs來訓練字符級語言模型。你向它輸入大量的文本,它會學習并產生類似的文本。你也可以用它來重新運行我下面的代碼。但是我們正在不斷超越自己;那么RNNs究竟是什么呢?
遞歸神經網絡
序列。你可能會問:是什么讓遞歸神經網絡如此特殊?Vanilla神經網絡(卷積網絡也一樣)最大的局限之處就是它們API的局限性:它們將固定大小的向量作為輸入(比如一張圖片),然后輸出一個固定大小的向量(比如不同分類的概率)。還不止這些:這些模型按照固定的計算步驟來(比如模型中層的數量)實現這樣的輸入輸出。遞歸網絡更令人興奮的主要原因是,它允許我們對向量序列進行操作:輸入序列、輸出序列、或大部分的輸入輸出序列。通過幾個例子可以具體理解這點:
每一個矩形是一個向量,箭頭則表示函數(比如矩陣相乘)。輸入向量用紅色標出,輸出向量用藍色標出,綠色的矩形是RNN的狀態(下面會詳細介紹)。從做到右:(1)沒有使用RNN的Vanilla模型,從固定大小的輸入得到固定大小輸出(比如圖像分類)。(2)序列輸出(比如圖片字幕,輸入一張圖片輸出一段文字序列)。(3)序列輸入(比如情感分析,輸入一段文字然后將它分類成積極或者消極情感)。(4)序列輸入和序列輸出(比如機器翻譯:一個RNN讀取一條英文語句然后將它以法語形式輸出)。(5)同步序列輸入輸出(比如視頻分類,對視頻中每一幀打標簽)。我們注意到在每一個案例中,都沒有對序列長度進行預先特定約束,因為遞歸變換(綠色部分)是固定的,而且我們可以多次使用。
正如你預想的那樣,與使用固定計算步驟的注定要失敗的固定網絡相比,使用序列進行操作要更加強大,因此,這激起了我們建立更智能系統更大的興趣。而且,我們可以從一小方面看出,RNNs將輸入向量與狀態向量用一個固定(但可以學習)函數綁定起來,從而用來產生一個新的狀態向量。在編程層面,在運行一個程序時,可以用特定的輸入和一些內部變量對其進行解釋。從這個角度來看,RNNs本質上可以描述程序。事實上,眾所周知,?RNNs是圖靈完備的?,即它們可以模擬任意程序(使用恰當的權值向量)。但是,類似于通用逼近定理神經網絡,你還不應該深入閱讀。就當我沒說過這些吧。
如果訓練Vanilla神經網絡是優化功能,那么訓練遞歸神經網絡則是優化程序。序列缺失情況下的序列處理。你可能會想,有序列作為輸入或輸出可能是相對少見的,但關鍵是,即使你的輸入/輸出是固定向量,仍然有可能使用這種強大的以序列的方式來處理它們。比如,下圖顯示了?DeepMind?中兩篇非常棒的論文的結果。在左邊,一個算法學習了一種遞歸網絡策略,可以將它的注意力集中在圖像周圍;特別的,它學會了從左到右閱讀門牌號碼(?Ba等人?)。在右邊,一個遞歸網絡通過學習在畫布上序列化地添加顏色然后生成一張數字圖像(?Gregor等人?):
??
左邊:RNN學習閱讀門牌號。右邊:RNN學習學習繪制門牌號。
即使你的數據不是序列形式的,你仍然可以制定并訓練出強大的模型來學習處理它。你可以學習有狀態的程序來處理固定大小的數據。
RNN計算。那么這些是如何工作的呢?主要是,RNNs有一個非常簡潔的API:它們將向量x作為輸入,然后輸出結果向量y.然而,關鍵的是這個輸出向量的內容不僅受到前一次輸入數據的影響,而且還會受整個歷史輸入數據的影響。這個API編寫成了一個類,它由一個step方法構成:
rnn = RNN() y = rnn.step(x) # x is an input vector, y is the RNN's output vector
RNN類有一些內部的狀態,會在每一次調用?step方法的時候進行更新。最簡單的情況是,這個狀態由單個隱藏向量h構成。下面是Vanilla RNN中對step方法的一種實現:
class RNN:# ...def step(self, x):# update the hidden stateself.h = np.tanh(np.dot(self.W_hh, self.h) + np.dot(self.W_xh, x))# compute the output vectory = np.dot(self.W_hy, self.h)return y
上面的代碼指明了vanilla RNN的前饋操作。這個RNN的參數是以下三個矩陣:w_hh,w_xh,w_hy。隱藏狀態self.h由兩個零向量初始化。np.tanh函數實現了非線性的方法,將活化結果壓縮到范圍[-1,1]之內。簡單介紹工作原理:tanh中有兩種形式:一種是基于前面的隱藏狀態,另一種是基于當前的輸入。numpy中的np.dot是矩陣乘法。這兩種中間體相加,然后由tanh函數將它壓縮成一個新的狀態向量。如果你適合看數學公式的話,我們同樣可以將隱藏狀態寫成?ht+1?=tanh(Whh?ht+?Wxhxt),?tanh函數是元素智能的。
我們用隨機數來初始化RNN矩陣,通過大量的訓練找到一個令人滿意的矩陣,并且用一些損失函數來度量,你可以在輸入序列x上得到你希望的輸出y。
更深層次說明。RNNs是一種神經網絡,而且如果你開始學習深度學習并開始像堆煎餅一樣積累模型,它們將會工作得更好(如果做得正確的話)。例如,我們可以通過以下方式建立一個2層的遞歸網絡:
y1 = rnn1.step(x) y = rnn2.step(y1)
換句話說,我們有兩個獨立的RNNs:一個RNN接收輸入向量,另一個將前一個RNN的輸出作為輸入。這兩個RNN沒有本質區別——這不外乎就是向量的輸入輸出而已,而且在反向傳播過程中每個模塊都伴隨著梯度操作。
來點更奇特的。我會簡要說明,實際上我們大多數人使用一種與上面我所提及稍微不同的網絡,它叫做長短期記憶(LSTM)網絡。LSTM是一種特殊類型的遞歸網絡,在實踐中工作效果更佳,這歸功于其強大的更新方程和一些吸引人的動態反向傳播功能。我不會詳細介紹,除了用于更新計算(self.h=···)的數學形式有點更復雜外,與其他RNNs沒有多大區別。從現在開始,我將會交替使用術語“RNN/LSTM”,但是這篇文章中所有的實驗都是用LSTM完成的。
字符級語言模型
好,我們現在已經初步了解了什么是RNNs,為什么它們如此令人興奮,還有它們是如何工作的。我們現在就用它來實現一個有趣的應用:我們將要訓練字符級的語言RNN模型。具體來說就是,我們將會向RNN輸入大量的文本數據,然后在一個序列中給定一個前面的字符,用它來建立計算這個序列下一個字符概率的模型。這將會讓我們在同一時間產生新文本字符。
作為一個案例,假設我們只有四種字母的詞匯“helo”,然后我們想要用訓練序列“hello”訓練一個RNN。這個訓練序列實際上是來自于4個獨立的訓練案例:1.字母e應該在字母h出現的情況下才可能出現,2.字母l應該出現在he出現的情況下,3.字母l同樣可以出現在hel出現的情況下,最后4.字母o應該出現在hell出現的情況下。
具體來說,我們將用1-of-k編碼(所有都是0,除了詞匯中字符的索引)將每個字符編碼成一個向量,然后用step函數每次向RNN中輸入一個字符。然后我們會看到一個4維序列的輸出向量(每個字符代表一個維度),我們將此作為RNN分配給序列下一個字符的置信度。下面是一張案例圖:
一個有四維輸入輸出層和一個有著3個單元(神經元)的隱藏層的實例。這張圖顯示了當將“helo”作為RNN的輸入時前饋操作的活化結果。輸出層包含了RNN對下一個出現字符(這里詞匯是“h,e,l,o”)的置信度。我們希望使得綠色的數字盡可能高而紅色數字盡可能低。
比如,我們可以看出,在第一次執行step函數的時候,RNN讀取到字符“h”然后將它之后可能出現字符“h”的置信度設置為1.0,可能出現字符“e”的置信度設置為2.2,可能出現字符“l”的置信度設置為-3.0,可能出現字符“o”的置信度設置為4.1。因為在我們的訓練數據中,下一個出現的字符是“e”,我們將要提高這個字符的置信度(綠色數字)并且降低其他字符的置信度(紅色數字)。通常的做法是使用一個交叉熵損失函數,這相當于在每個輸出向量上使用Softmax分類器,將下一個出現的字符的索引作為一個正確的分類。一旦損失進行了反向傳播并且RNN權值得到更新,在輸入相同的情況下,下一個正確的字符將會有更高的分數。技術解釋:該RNN是由小批量隨機梯度下降訓練的。我喜歡使用?RMSProp?(每個參數的自適應學習率)來穩定更新。
同樣可以注意到,字符“l”第一次輸入時,得到的結果是“l”,但是第二得到的結果是“o”。因此,這個RNN不能單獨依賴于輸入數據,必須使用它的遞歸連接來跟蹤內容以達到準確結果。
在測試的時候,我們向RNN輸入一個字符,然后得到了下一個可能出現字符的分布。我們從這個分布中抽樣,然后又將這些樣本輸入到RNN中得到下一個字符。重復這個過程,你就在做取樣的工作了!現在讓我們在不同數據集上訓練RNN,看看會有什么發生。
為進一步說明,出于教育目的我還寫了一篇文章?minimal character-level RNN language model in Python/numpy?。只有大約100行代碼,如果你更擅長閱讀代碼而不是文字,你可以從中得到簡明的、具體的、有用的結論?,F在我們將深入到實例結果,使用更高效的Lua/Torch代碼庫來編程。
開心使用RNNs
下面的5個字符模型案例都是使用我發布在Github上的?代碼?進行訓練的。每個實例的輸入都是單個文本文件,然后我們訓練RNN預測序列中下一個可能出現的字符。
Paul Graham生成器
首先讓我們嘗試用一個小英語數據集作一個全面檢查。我個人最喜歡的數據集是?Paul Graham散文串聯集。其基本思路是,散文中有很多智慧,不幸的是Paul Graham是一個相對緩慢的生成器。如果我們能夠按需生成智慧樣本,那不是很強大?RNNs在這里就起到了作用。
連接過去5年所有的論文,我們得到了大約1MB的文本文件,或者說是大約100萬個字符(這是一個非常小的數據集)。技術方面:我們用512個隱藏節點(大約350萬個參數)來訓練一個2層的LSTM,然后在每層之后設定參數為0.5的dropout層。我們將每批訓練100個實例,然后每超過100個字符則停止反向傳播。通過這些設置,每一批在TITAN Z GPU上處理完成大約需要0.46秒(這通過性能代價忽略不計的50個字符的BPTT算法將它分為兩半)。事不宜遲,讓我們看看RNN中的樣本:
"The surprised in investors weren't going to raise money. I'm not the company with the time there are all interesting quickly, don't have to get off the same programmers. There's a super-angel round fundraising, why do you can do. If you have a different physical investment are become in people who reduced in a startup with the way to argument the acquirer could see them just that you're also the founders will part of users' affords that and an alternation to the idea. [2] Don't work at first member to see the way kids will seem in advance of a bad successful startup. And if you have to act the big company too."
好了,很明顯上面的樣本不會很快隨時取代Paul Graham,但請記住,?RNN不得不完全從一個小的數據集(包括逗號,頓號和空格的位置)開始學習英語。我同樣喜歡讓它來學習支持自己的論證(比如上面的[2])。有時,它會提供一些可洞察的東西,比如“?a company is a meeting to think to investors”。如果你想了解更多,點擊這個?鏈接,它有5萬個字符樣本數據。
溫度。我們同樣可以在Softmax取樣的時候對溫度進行操作。將溫度從1降至更低的數字(比如0.5)可以讓RNN有更高的置信度,但是樣本就會更保守。相反地,較高的溫度將會得到更多元化的結果,但是失誤就更多(比如拼寫錯誤等)。特別地,將溫度設置成與0接近的數字就會得到與Paul Graham相似的言論:
"is that they were all the same thing that was a startup is that they were all the same thing that was a startup is that they were all the same thing that was a startup is that they were all the same"
看起來我們陷入了startups的死循環了。
Shakespeare
看樣子好像我們的模型可以學習拼寫英語單詞,但是數據更結構化更風格化又會怎樣呢?為了檢測這一點,我下載了莎士比亞所有的作品并將它們串起來組成一個單一的(4.4MB)文件?,F在我們可以訓練一個更大的網絡了,在這個例子中,我們嘗試使用每層上都擁有512個隱藏節點的3層RNN網絡。在我們訓練網絡幾小時后,我們得到了如下樣本:
PANDARUS: Alas, I think he shall be come approached and the day When little srain would be attain'd into being never fed, And who is but a chain and subjects of his death, I should not sleep.Second Senator: They are away this miseries, produced upon my soul, Breaking and strongly should be buried, when I perish The earth and thoughts of many states.DUKE VINCENTIO: Well, your wit is in the care of side and that.Second Lord: They would be ruled after this chamber, and my fair nues begun out of the fact, to be conveyed, Whose noble souls I'll have the heart of the wars.Clown: Come, sir, I will make did behold your worship.VIOLA: I'll drink it.
切記,RNN只認識字符,所以它將說話者的名字和內容一起生成為樣本。有時,我們還可以得到相對延伸的獨白段落,比如:
VIOLA: Why, Salisbury must find his flesh and thought That which I am not aps, not a man and in fire, To show the reining of the raven and the wars To grace my hand reproach within, and not a fair are hand, That Caesar and my goodly father's world; When I was heaven of presence and our fleets, We spare with hours, but cut thy council I am great, Murdered and by thy master's ready there My power to give thee but so much as hell: Some service in the noble bondman here, Would show him to her wine.KING LEAR: O, if you were a feeble sight, the courtesy of your law, Your sight and several breath, will wear the gods With his heads, and my hands are wonder'd at the deeds, So drop upon your lordship's head, and your opinion Shall be against your honour.
在這些樣本中,我幾乎認不出這是莎士比亞的作品:)如果你喜歡莎士比亞,你可能會重視這份100,000個字符的樣本。當然,你也可以用我提供的代碼,在不同溫度下生成許多你自己的樣本。
Wikipedia
我們看到,LSTM可以學習拼寫單詞和復制一般的句法結構。讓我來加大難度,在結構化markdown語言上訓練網絡。特別的,讓我們使用?Hutter Prize?的100MB的Wikipedia原始數據訓練一個LSTM。在Graves等人?之后,我使用前96MB數據來訓練,剩下的則花一個晚上用來驗證和運行幾個模型?,F在我們可以取樣Wikipedia文章了!下面是幾個有趣的節選。首先,一些基本的markdown輸出:
Naturalism and decision for the majority of Arab countries' capitalide was grounded by the Irish language by [[John Clair]], [[An Imperial Japanese Revolt]], associated with Guangzham's sovereignty. His generals were the powerful ruler of the Portugal in the [[Protestant Immineners]], which could be said to be directly in Cantonese Communication, which followed a ceremony and set inspired prison, training. The emperor travelled back to [[Antioch, Perth, October 25|21]] to note, the Kingdom of Costa Rica, unsuccessful fashioned the [[Thrales]], [[Cynth's Dajoard]], known in western [[Scotland]], near Italy to the conquest of India with the conflict. Copyright was the succession of independence in the slop of Syrian influence that was a famous German movement based on a more popular servicious, non-doctrinal and sexual power post. Many governments recognize the military housing of the [[Civil Liberalization and Infantry Resolution 265 National Party in Hungary]], that is sympathetic to be to the [[Punjab Resolution]] (PJS)[http://www.humah.yahoo.com/guardian. cfm/7754800786d17551963s89.htm Official economics Adjoint for the Nazism, Montgomery was swear to advance to the resources for those Socialism's rule, was starting to signing a major tripad of aid exile.]]
你可能會想,上面的雅虎url并不真實存在,該模型只是將它作為假想事物。同樣,可以注意到模型學會正確打開和關閉插入語。模型同樣學會了許多結構化markdown語言,比如,有時候它創建了頭部信息和列表等:
{ { cite journal | id=Cerling Nonforest Department|format=Newlymeslated|none } } ''www.e-complete''.'''See also''': [[List of ethical consent processing]]== See also == *[[Iender dome of the ED]] *[[Anti-autism]]===[[Religion|Religion]]=== *[[French Writings]] *[[Maria]] *[[Revelation]] *[[Mount Agamul]]== External links== * [http://www.biblegateway.nih.gov/entrepre/ Website of the World Festival. The labour of India-county defeats at the Ripper of California Road.]==External links== * [http://www.romanology.com/ Constitution of the Netherlands and Hispanic Competition for Bilabial and Commonwealth Industry (Republican Constitution of the Extent of the Netherlands)]
有時模型會生成隨機但是有效的XML文件:
<page><title>Antichrist</title><id>865</id><revision><id>15900676</id><timestamp>2002-08-03T18:14:12Z</timestamp><contributor><username>Paris</username><id>23</id></contributor><minor /><comment>Automated conversion</comment><text xml:space="preserve">#REDIRECT [[Christianity]]</text></revision> </page>
這個模型完全拼湊出了timestamp,id等等。同樣,注意到它以正確的嵌套順序適當的閉合了正確的標簽。如果你有興趣了解更多,這里有?100,000 characters of sampled wikipedia
代數幾何(Latex)
以上結果表明,該模型在學習復雜句法結構方面表現得相當不錯。這些結果令人印象深刻,我的實驗伙伴(?Justin Johnson?)和我打算在結構上再深入研究,我們使用這本關于代數棧/幾何的?書?。我們下載了Latex的源文件(16MB),然后訓練了一個多層的LSTM。令人驚訝的是,由Latex產生的樣本幾乎是已經匯總好了的。我們不得不介入并手動修復了一些問題,這樣你就得到了合理的數學推論,這是相當驚人的:
代數幾何樣本(假的),?真正的PDF文件在這?。
這是另一份樣本:
?
產生了更多假的代數幾何,嘗試處理圖像(右)
正如上面你所看到的那樣,有些時候這個模型試圖生成LaTeX圖像,但很明顯它并不明白圖像的具體意思。同樣我很喜歡模型選擇跳過證明過程的那部分(“Proof omitted”,左上角)。當然,Latex有相對困難的結構化句法格式,我自己都還沒有完全掌握。為舉例說明,下面是模型中的一個原始樣本(未被編輯):
\begin{proof} We may assume that $\mathcal{I}$ is an abelian sheaf on $\mathcal{C}$. \item Given a morphism $\Delta : \mathcal{F} \to \mathcal{I}$ is an injective and let $\mathfrak q$ be an abelian sheaf on $X$. Let $\mathcal{F}$ be a fibered complex. Let $\mathcal{F}$ be a category. \begin{enumerate} \item \hyperref[setain-construction-phantom]{Lemma} \label{lemma-characterize-quasi-finite} Let $\mathcal{F}$ be an abelian quasi-coherent sheaf on $\mathcal{C}$. Let $\mathcal{F}$ be a coherent $\mathcal{O}_X$-module. Then $\mathcal{F}$ is an abelian catenary over $\mathcal{C}$. \item The following are equivalent \begin{enumerate} \item $\mathcal{F}$ is an $\mathcal{O}_X$-module. \end{lemma}
這份樣本來自一個相對合適的模型,其中顯示出了一些常見錯誤。比如,模型打開了一個\begin{proof}環境,但是卻以\end{lemma}結束。這個問題我們必須手動修復,這可能是由于依賴關系太長而導致的:當這個模型做完了?proof過程,它就忘記了它是在做proof還是lemma了。同樣的,當模型打開了一個\begin{enumerate}環境,然后卻忘記關閉它了。我們發現,當我們使用更大/更好的模型的時候,這種情況出現得就較少了,盡管如此,這些問題還是會出現。
Linux源代碼
我想看看這個模型處理結構化數據的極限,所以為了這一終極目標,我打算開始編寫一些代碼,特別的,我瀏覽了?Github上Linux repo?所有的原始資料和頭文件,把它們串在一起形成一個單一的巨大文件(474MB大小的C代碼)(我本來打算只訓練內核,但是它只有16MB)。然后,我花了幾天時間訓練出了大小剛好適合我GPU的3層LSTM網絡。這些模型有大約1000萬個參數,然而這對于RNN網絡來說還是微不足道的。結果非常有趣:
/** Increment the size file of the new incorrect UI_FILTER group information* of the size generatively.*/ static int indicate_policy(void) {int error;if (fd == MARN_EPT) {/** The kernel blank will coeld it to userspace.*/if (ss->segment < mem_total)unblock_graph_and_set_blocked();elseret = 1;goto bail;}segaddr = in_SB(in.addr);selector = seg / 16;setup_works = true;for (i = 0; i < blocks; i++) {seq = buf[i++];bpf = bd->bd.next + i * search;if (fd) {current = blocked;}}rw->name = "Getjbbregs";bprm_self_clearl(&iv->version);regs->new = blocks[(BPF_STATS << info->historidac)] | PFMR_CLOBATHINC_SECONDS << 12;return segtable; }
這代碼整體上看起來非常棒。我認為它不會馬上就能編譯通過,但是當你滾動查看這些代碼的時候給你的感覺是這是一個非常強大的C代碼庫。注意到,RNN到處隨機生成代碼片段和注釋。它很少會犯語法錯誤。比如,它適當的使用了字符類型、指針概念等。同樣它正確打開和關閉了代碼塊{[,并且學習將代碼縮進。一處常見的錯誤就是它不能跟蹤變量名:它常常會使用未定義的變量(比如上面出現的rw),或者聲明它從來不用的變量(比如上面的int error),或者返回一個不存在的變量。讓我們來看看更多的案例。下面是另外一個代碼片段,顯示了RNN學習操作數組的情況:
/** If this error is set, we will need anything right after that BSD.*/ static void action_new_function(struct s_stat_info *wb) {unsigned long flags;int lel_idx_bit = e->edd, *sys & ~((unsigned long) *FIRST_COMPAT);buf[0] = 0xFFFFFFFF & (bit << 4);min(inc, slist->bytes);printk(KERN_WARNING "Memory allocated x/x, ""original MLL instead\n"),min(min(multi_run - s->len, max) * num_data_in),frame_pos, sz + first_seg);div_u64_w(val, inb_p);spin_unlock(&disk->queue_lock);mutex_unlock(&s->sock->mutex);mutex_unlock(&func->mutex);return disassemble(info->pending_bh); }static void num_serial_settings(struct tty_struct *tty) {if (tty == tty)disable_single_st_p(dev);pci_disable_spool(port);return 0; }static void do_command(struct seq_file *m, void *v) {int column = 32 << (cmd[2] & 0x80);if (state)cmd = (int)(int_state ^ (in_8(&ch->ch_flags) & Cmd) ? 2 : 1);elseseq = 1;for (i = 0; i < 16; i++) {if (k & (1 << 1))pipe = (in_use & UMXTHREAD_UNCCA) +((count & 0x00000000fffffff8) & 0x000000f) << 8;if (count == 0)sub(pid, ppc_md.kexec_handle, 0x20000000);pipe_set_bytes(i, 0);}/* Free our user pages pointer to place camera if all dash */subsystem_info = &of_changes[PAGE_SIZE];rek_controls(offset, idx, &soffset);/* Now we want to deliberately put it to device */control_check_polarity(&context, val, 0);for (i = 0; i < COUNTER; i++)seq_puts(s, "policy "); }
注意到,在第二個函數中,模型進行了這樣的比較tty == tty,這是永遠成立的。但是,至少這次變量tty只在這個函數中起作用!最后一個函數,注意到代碼沒有返回任何值,但是這是正確的因為函數的返回值聲明成了void。但是,前兩個函數同樣聲明成了void返回類型,卻返回了數值。這又是一個由于長期迭代導致的常見錯誤。
有些時候模型會決定現在是時候產生一個新的文件了。這通常是有趣的部分:首先模型一個一個字符記住GNU許可證,然后include幾個頭文件,聲明一些宏,然后就開始生成代碼部分:
/** Copyright (c) 2006-2010, Intel Mobile Communications. All rights reserved.** This program is free software; you can redistribute it and/or modify it* under the terms of the GNU General Public License version 2 as published by* the Free Software Foundation.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software Foundation,* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <linux/kexec.h> #include <linux/errno.h> #include <linux/io.h> #include <linux/platform_device.h> #include <linux/multi.h> #include <linux/ckevent.h>#include <asm/io.h> #include <asm/prom.h> #include <asm/e820.h> #include <asm/system_info.h> #include <asm/setew.h> #include <asm/pgproto.h>#define REG_PG vesa_slot_addr_pack #define PFM_NOCOMP AFSR(0, load) #define STACK_DDR(type) (func)#define SWAP_ALLOCATE(nr) (e) #define emulate_sigs() arch_get_unaligned_child() #define access_rw(TST) asm volatile("movd %%esp, %0, %3" : : "r" (0)); \if (__type & DO_READ)static void stat_PC_SEC __read_mostly offsetof(struct seq_argsqueue, \pC>[1]);static void os_prefix(unsigned long sys) { #ifdef CONFIG_PREEMPTPUT_PARAM_RAID(2, sel) = get_state_state();set_pid_sum((unsigned long)state, current_state_str(),(unsigned long)-1->lr_full; low; }
這里有太多有趣的地方可以講述了,關于這部分我可能可以寫一篇完整的博客來講述。但是在這里我就省略這部分了,如果你有興趣查看,請點擊?1MB of sampled Linux code
了解到底發生了什么
我們可以看出,最終訓練出的結果是令人印象深刻的,但是這一切都是如何工作的?讓我們通過運行兩個快速的實驗來簡要探索下。
訓練中樣本的演變
首先,探索模型訓練過程中樣本文本是如何演變的是件有趣的事,比如,我用列夫·托爾斯泰的《戰爭與和平》訓練了一個LSTM網絡,然后每100次迭代訓練就生成樣本。100次迭代后模型生成了隨機、混亂的樣本:
tyntd-iafhatawiaoihrdemot lytdws e ,tfti, astai f ogoh eoase rrranbyne 'nhthnee e plia tklrgd t o idoe ns,smtt h ne etie h,hregtrs nigtike,aoaenns lng
但是,注意到模型最少知道了要在每個“單詞”間加上空格。有些時候會加上兩個空格。同樣模型不知道逗號后面通常跟著空格。300次迭代后我們可以看到模型開始有了引號和句號的概念:
"Tmont thithey" fomesscerliund Keushey. Thom here sheulke, anmerenith ol sivh I lalterthend Bleipile shuwy fil on aseterlome coaniogennc Phe lism thond hon at. MeiDimorotion in ther thize."
這次單詞之間同樣由空格隔開,而且模型開始知道在句子末尾加上句號。500次迭代:
we counter. He stutn co des. His stanted out one ofler that concossions and was to gearang reay Jotrets and with fre colt otf paitt thin wall. Which das stimn
現在模型會拼寫最短、最常見單詞,比如“we”,“He”,“His”,“Which”,“and”等。700次迭代的時候,我們得到了更像英語的文本:
Aftair fall unsuch that the hall for Prince Velzonski's that me of her hearly, and behs to so arwage fiving were to it beloge, pavu say falling misfort how, and Gogition is so overelical and ofter.
在經過1200次迭代后,我們發現模型開始使用引號和問號/感嘆號了,與此同時也學會了更長的單詞:
"Kite vouch!" he repeated by her door. "But I would be done and quarts, feeling, then, son is people...."
經過2000次迭代,模型能夠正確拼寫的單詞,引號,名字等:
"Why do what that day," replied Natasha, and wishing to himself the fact the princess, Princess Mary was easier, fed in had oftened him. Pierre aking his soul came to the packs and drove up his father-in-law women.
大體上我們可以這么認為,首先模型發現了單詞-空格這樣普遍的結構,然后迅速學會拼寫單詞;從學習拼寫簡單單詞開始到最后學習拼寫長單詞。在單詞中顯現出主題內容(一般依賴于長期性)在很多次迭代后才出現。
RNN預測結果和神經元激活可視化
可視化有趣的另一個方面是可以按字符來觀察預測分布。在下面的可視化圖中,我們向Wikipedia RNN模型中輸入了校驗好的數據集(藍色/綠色的行)中的字符,然后在每個字符下面,我們列出了(紅色部分)模型預測會出現的前5個字符,顏色深淺根據它們概率大小決定(深紅:預測準確,白色:不準確)。比如,注意到有一連串字符是模型非常有信心能夠預測準確的(對http://www.序列模型置信度非常高)。
輸入字符序列(藍色/綠色)的顏色取決于RNN隱藏層中隨機選擇的神經元的激活情況。定義綠色=非常興奮,藍色=不是那么興奮(對于那些熟悉LSTMs細節的人來說,這些就是隱藏向量中[-1,1]范圍內的值,也就是經過門限操作和tanh函數的LSTM單元狀態)。直觀的,下圖顯示了在RNN“大腦”讀取輸入序列時一些神經元的激活情況。不同的神經元可能有不同的模式;下面我們將會看到我找到的4個不同的神經元,我認為這幾個是有趣的,并且是可解釋的(許多其他的并不容易解釋):
此圖中高亮的神經元似乎對URL極度興奮,URL以外的地方就不那么興奮。LSTM似乎會用這種神經元來記住它是否在URL之中。
在這張圖中,當RNN在[[]]標記之中時,高亮的神經元表現極度興奮,所以在這種標記之外就沒那么興奮,在神經元碰到字符“[”的時候不會表現得興奮,它一定要等到出現第二個“[”才會激活。計算模型是否碰到了一個還是兩個“[”的任務似乎可以用一個不同的神經元完成。
在這里,我們可以看出在[[]]環境中,神經元有著線性的變化。換句話說,它的激活函數給了RNN中[[]]范圍的一種基于時間的坐標系統。RNN可以通過這些信息或多或少的依賴于字符在[[]]中出現的早/晚來生成不同的字符(有可能是這樣)。
這是另外一個神經元,它有著更個性化的行為:它整體上比較平淡無常,但是碰到“www”中第一個“w”的時候突然就開始變得興奮。RNN可能可以使用這種神經元來計算“www”序列的長度,這樣它就知道是否應該再添加一個“w”還是開始添加URL。
當然,由于RNN隱藏狀態的龐大性,高維度性和分布式特性,很多這樣的結論都稍微要加上特別說明才能理解。
源代碼
我希望通過我上面的講述,你會覺得訓練一個字符級語言模型是一次有趣的練習。你可以使用我在Github(擁有MIT許可)上發布的?char-rnn code?來訓練你自己的模型。它將大量文本文件作為輸入,訓練出一個字符級模型,然后你就可以從中得到樣本文件。同時,如果你有一個GPU的話會對你有所幫助,否在在CPU上訓練的話會花大約10多倍的時間。不管怎樣如果你完成了訓練并且得到了有趣的結果,請告知我!如果你在使用Torch/Lua代碼庫的時候碰到困難,請記住,這只是?100-line gist的一個版本。
一些題外話。代碼是由?Torch7?編寫的,它最近成了我最喜歡的深度學習框架。我是最近幾個月才開始使用Torch/Lua的,它們并不簡單(我花了大量時間來閱讀Github上Torch源碼,向它的發布者提問才掌握它),但是一旦你掌握了足夠的知識,它就會給你帶來很大的靈活性和速度提升。我以前同樣使用過Caffe和Theano,我認為Torch并不完美,但是它的抽象層次和原理比其他的要優秀。在我看來,一個有效框架應該具有以下功能:
延伸閱讀
在結束這篇文章之前,我還想再介紹更多關于RNNs的東西,并大致提供目前的研究方向。最近在深度學習領域,RNNs頗受歡迎。和卷積網絡一樣,它們已經存在了幾十年,但它們的潛力最近才開始得到廣泛的認可,這在很大程度上是因為我們不斷增長的計算資源。下面是一些最近事態發展的簡要介紹(這絕對不是完整的列表,很多這樣的工作讓研究界好像回到了上世紀90那種研究熱潮,來看看相關的工作部分):
在NLP/語音領域,RNNs將?語音轉錄成文本?,使用?機器翻譯?,?生成手寫文本?,當然,它們已經被用來當做強大的語言模型(?Sutskever等人?)(?Graves?)(?Mikolov等人?)(都是在字符和單詞層面)。目前看來,單詞級的模型比字符級的模型要更好,但這肯定是暫時的。
計算機視覺。在計算機視覺方面,RNNs也很快成為了無處不在的技術。比如,我們會見到RNNs在幀層面?分類視頻?,?添加圖片字幕?(同樣包括我和其他人的工作),?添加視頻字幕?,最近又用來?視覺問答?。我個人最喜歡的RNNs計算機視覺方面的論文是?Recurrent Models of Visual Attention?,這是因為它有著高層次方向特性(glance順序處理圖像)和低層次建模(REINFORCE學習規定它是強化學習中一個特定的梯度方法,可以訓練出進行不可微計算的模型(以圖像周邊glance處理為例))。我相信,這種混合模型類型——由CNN形成的原始感知器再加上RNN glance策略,將會在感知器中普遍存在,特別是對于比分類更復雜的任務。
歸納推理,存儲和關注模塊。另一個非常令人興奮的研究方向是面向解決Vanilla遞歸網絡的局限性。它的一個問題是RNNs不是數學歸納的:它們能夠非常好的記住序列,但是并不一定總能夠得到正確的結果(我會舉幾個例子來具體說明)。第二個問題是,它們不必每步都將代表大小和計算數量結合起來。具體來說,如果你把隱藏狀態向量的大小增加一倍,由于矩陣乘法,每步中FLOPS的數量會變成原來的四倍。理想情況下,我們想保持龐大的代表性/存儲(比如,包含維基百科所有的內容或者多個中間狀態變量),而同時保持計算的每個時間步長固定的能力。
在這些方向上,第一個有說服力的例子在DeepMind上的?Neural Turing Machines?這篇論文中講述了。這篇論文描述了在計算開始時,模型在大的、外部的存儲陣列和更小寄存器之間執行讀寫操作的方法(把它想象成是你自己的工作存儲器)。至關重要的是,這篇論文也同樣介紹了有趣的內存尋址機制,這是用一個(平緩的,完全可微的)關注模塊實現的。平緩關注模塊的概念是一個強大的建模特征,同時也是?Neural Machine Translation by Jointly Learning to Align and Translate?這篇文章再機器翻譯上的一大特色,網絡存儲則用來問答。事實上,我不得不說:
關注模塊的概念在最近的神經網絡架構創新中是最有趣的。現在,我不想講太多的細節,但是內存尋址的平緩關注模塊機制是非常方便的,因為它讓模型完全可微,但不幸的是,這會犧牲一些效率,因為所有可以被關注的都被關注了(平緩的)。你可以把它想象成C語言中的指針,它不指向具體的地址,而是定義了在整個內存中分布的所有地址,并將指針返回的所指向內容的加權總和值非關聯化(這個操作代價會很大!)。這促使多位作者在給多塊內存進行關注操作的時候使用平緩關注方式而不是猛烈關注方式(比如,對某些內存單元進行讀取操作,而不是從內存單元中讀出/寫入到某些地方)。這種模型有著更顯著的哲學吸引力,可擴展性和高效率性,但是不幸的是,它是不可微的。這就要使用強化學習文獻(比如REINFORCE)中使用到的技術來解決,人們將它完美地用于不可微的模型之中。這是正在進行的工作,但是針對這些困難的關注模型進行了探討,你可以在?Inferring Algorithmic Patterns with Stack-Augmented Recurrent Nets?,Reinforcement Learning Neural Turing Machines?,?Show Attend and Tell?這幾篇論文中了解到。
人物。如果你愿意閱讀我推薦的?Alex Graves?,?Ilya Sutskever?和?Tomas Mikolov?所寫的文章。你可以從?David Silver?或?Pieter Abbeel?的公開課中了解到更多的關于REINFORCE,強化學習和策略梯度方法的知識。
代碼。如果你想實踐實踐訓練RNNs,我推薦你使用Theano的?keras?和?passage?,也可以使用連同這篇文章一同發布的Torch?代碼?,或者使用我先前寫好的numpy源代碼?要點?,它實現了一個有效率的、批量處理的LSTM前饋和后饋處理。你也可以看看我基于numpy的?NeuralTalk?,它用了RNN/LSTM來給圖片加字幕,或者你可以使用Jeff Donahue寫的?Caffe?。
總結
我們已經學習了RNNs是如何工作的,它們為什么變得至關重要,我們在幾個有趣的數據集上訓練了一個字符級的RNN模型,并且我們看到了RNNs的執行情況。你完全可以毫無顧忌的用RNNs進行大量創新,并且我相信它們會在智能系統中成為一種普遍存在并且至關重要的組成部分。
最后,在這篇文章中加上一些元數據,我用這篇文章的源文件訓練了一個RNN。不幸的是,我只有46K的字符,沒有足夠的字符給RNN,但是返回的樣本(使用低溫度以得到更典型的樣本)如下所示:
I've the RNN with and works, but the computed with program of the RNN with and the computed of the RNN with with and the code
好了,這篇文章是講述關于RNN和它工作狀況的,很明顯它工作良好 :)。我們下回見!
原文鏈接:?The Unreasonable Effectiveness of Recurrent Neural Networks(譯者/劉翔宇 審校/劉帝偉、朱正貴、李子健 責編/周建丁)
關于譯者:??劉翔宇,中通軟開發工程師,關注機器學習、神經網絡、模式識別。
本文為CSDN編譯整理,未經允許不得轉載,如需轉載請聯系market#csdn.net(#換成@)
總結
以上是生活随笔為你收集整理的递归神经网络不可思议的有效性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 快速稀疏编码算法
- 下一篇: 基于Apache Spark的机器学习及