日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LSTM入门必读:从入门基础到工作方式详解 By 机器之心2017年7月24日 12:57 长短期记忆(LSTM)是一种非常重要的神经网络技术,其在语音识别和自然语言处理等许多领域都得到了广泛的应用

發(fā)布時(shí)間:2025/3/21 编程问答 30 豆豆

LSTM入門必讀:從入門基礎(chǔ)到工作方式詳解

By?機(jī)器之心2017年7月24日 12:57

長短期記憶(LSTM)是一種非常重要的神經(jīng)網(wǎng)絡(luò)技術(shù),其在語音識(shí)別和自然語言處理等許多領(lǐng)域都得到了廣泛的應(yīng)用。。在這篇文章中,Edwin?Chen?對(duì)?LSTM?進(jìn)行了系統(tǒng)的介紹。機(jī)器之心對(duì)本文進(jìn)行了編譯。


我第一次學(xué)習(xí)?LSTM?的時(shí)候,它就吸引了我的眼球。然而并不是那種看到果凍甜圈圈時(shí)候的驚喜的形式。事實(shí)證明?LSTM?是對(duì)神經(jīng)網(wǎng)絡(luò)的一個(gè)相當(dāng)簡單的擴(kuò)展,而且在最近幾年里深度學(xué)習(xí)所實(shí)現(xiàn)的驚人成就背后都有它們的身影。所以我會(huì)盡可能直觀地來呈現(xiàn)它們——以便你們自己就可以弄明白。


首先,讓我們來看一幅圖:




LSTM?很漂亮吧?讓我們開始吧!


(提示:如果你已經(jīng)熟知神經(jīng)網(wǎng)絡(luò)和?LSTM,請(qǐng)直接跳到中間部分,本文的前半部分是一個(gè)入門。)


神經(jīng)網(wǎng)絡(luò)


想象一下,我們有一部電影的圖像序列,我們想用一個(gè)活動(dòng)來標(biāo)記每一副圖像(例如,這是一場戰(zhàn)斗嗎?圖中的人物在交談嗎?圖中的人物在吃東西嗎......)


我們?nèi)绾巫龅竭@一點(diǎn)呢?


一種方法就是忽略圖像的順序本質(zhì),構(gòu)造將每幅圖像單獨(dú)考慮的圖像分類器。例如,在提供足夠多的圖像和標(biāo)簽時(shí):


  • 我們的算法首先檢測到較低水平的模式,例如形狀和邊緣。
  • 在更多的數(shù)據(jù)下,它可能學(xué)會(huì)將這些模式組合成更加復(fù)雜的模式,例如人臉(兩個(gè)圓形東西下面有一個(gè)三角形的東西,下面還有一個(gè)橢圓形的東西),或者貓。
  • 甚至在更多的數(shù)據(jù)下,它可能學(xué)會(huì)把這些高水平的模式映射到活動(dòng)本身(具有嘴巴、牛排和叉子的情景可能與吃有關(guān))。


那么,這就是一個(gè)深度神經(jīng)網(wǎng)絡(luò)(deep?neural?network):它使用一副圖片作為輸入返回一個(gè)活動(dòng)作為輸出,就像我們可以在不了解任何關(guān)于狗的知識(shí)就可以學(xué)會(huì)在狗的行為中檢測到模式一樣(在看了足夠多的柯基犬之后,我們會(huì)發(fā)現(xiàn)一些諸如毛茸茸的屁股和鼓槌般的腿),深度神經(jīng)網(wǎng)絡(luò)可以通過隱藏層的表征來學(xué)會(huì)表示圖片。


數(shù)學(xué)描述


我假定讀者早已熟悉了基本的神經(jīng)網(wǎng)絡(luò),下面讓我們來快速地復(fù)習(xí)一下吧。


  • 只有一個(gè)單獨(dú)的隱藏層的神經(jīng)網(wǎng)絡(luò)將一個(gè)向量?x?作為輸入,我們可以將它看做一組神經(jīng)元。
  • 每個(gè)輸入神經(jīng)元都被通過一組學(xué)習(xí)得到的權(quán)重連接到隱藏層。
  • 第?j?個(gè)隱藏神經(jīng)元的輸出如下:(其中??是一個(gè)激活函數(shù))
  • 隱藏層是全連接到輸出層的,第?j?個(gè)輸出神經(jīng)元的輸出?yj?如下:如果我們需要輸出概率,我們可以通過?softmax?函數(shù)對(duì)輸出做一下變換。


寫成矩陣形式如下:



其中


  • x?是輸入向量
  • W?是連接輸入和隱藏層的權(quán)重矩陣
  • V?是連接隱藏層和輸出的權(quán)重矩陣
  • 常用的激活函數(shù)?分別是?sigmoid?函數(shù)σ(x),它可以將數(shù)字壓縮在(0,1)的范圍;雙曲正切函數(shù)(hyperbolic?tangent)tanh(x),它將數(shù)字壓縮在(-1,1)的范圍;以及修正線性單元函數(shù)(rectified?linear?unit)函數(shù),ReLU(x)=max(0,x)。


下面用一幅圖來描述神經(jīng)網(wǎng)絡(luò):


(注意:為了使符號(hào)更加簡潔,我假設(shè)?x?和?h?各包含一個(gè)代表學(xué)習(xí)偏差權(quán)重的固定為?1?的附加偏置神經(jīng)元(bias?neuron)。)


使用循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)記憶信息


然而忽略電影圖像的序列信息只是最簡單的機(jī)器學(xué)習(xí)。如果我們看見了一副沙灘的景象,我們應(yīng)該在之后的幀里強(qiáng)調(diào)沙灘的活動(dòng):某人在水中的圖片應(yīng)該被更多可能地標(biāo)記為游泳,而不是洗澡;某人閉著眼睛躺著的圖片應(yīng)該被更多地標(biāo)記為日光浴。如果我們記得?Bob?剛剛到了一家超市,那么即使沒有任何特別的超市特征,Bob?拿著一塊培根的照片應(yīng)該更可能地被歸類為購物而不是烹飪。


所以我們想要的就是讓我們的模型去追蹤這個(gè)世界的狀態(tài):


1.?在看完每一張圖片之后,模型會(huì)輸出一個(gè)標(biāo)簽,也會(huì)更新關(guān)于這個(gè)世界的知識(shí)。例如,模型可能學(xué)會(huì)自動(dòng)地發(fā)現(xiàn)和追蹤位置(目前的場景是在室內(nèi)還是在沙灘?)、一天中的時(shí)間(如果場景中包含月亮,那么模型應(yīng)該記住現(xiàn)在是晚上)以及電影中的進(jìn)度(這是第一張圖還是第?100?幀?)等信息。至關(guān)重要的是,就像神經(jīng)網(wǎng)絡(luò)能夠在沒有被饋送信息的情況下自動(dòng)地發(fā)現(xiàn)隱藏的邊緣、形狀以及人臉等圖像一樣,我們的模型也應(yīng)該依靠它們自己來發(fā)現(xiàn)一些有用的信息。

2.?在被給定一張新圖片的時(shí)候,模型應(yīng)該結(jié)合已經(jīng)收集到的知識(shí)來做出更好的工作。


這就是一個(gè)循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)。除了簡單地輸入一幅圖像并返回一個(gè)活動(dòng)標(biāo)簽,RNN?也會(huì)維護(hù)內(nèi)部關(guān)于這個(gè)世界的知識(shí)(就是分配給不同信息片段的權(quán)重),以幫助執(zhí)行它的分類。


數(shù)學(xué)描述


所以,讓我們把內(nèi)部知識(shí)(internal?knowledge)的概念加入到我們的方程中吧,我們可以將內(nèi)部記憶看做網(wǎng)絡(luò)會(huì)隨著時(shí)間進(jìn)行維護(hù)的信息片段的記憶。


但是這是容易的:我們知道神經(jīng)網(wǎng)絡(luò)的隱藏層早已將輸入的有用信息做了編碼,所以我們?yōu)楹尾话堰@些隱藏層作為記憶呢?這就有了我們的?RNN?方程:




注意在時(shí)間?t?計(jì)算得到的隱藏狀態(tài)?ht(ht?就是我們這里的內(nèi)部知識(shí))會(huì)被反饋到下一個(gè)時(shí)間。(另外,我會(huì)使用例如隱藏狀態(tài)、知識(shí)、記憶以及信念這樣的詞語來變換地描述?ht)




通過?LSTM?來實(shí)現(xiàn)更長時(shí)間的記憶


讓我們來思考一下模型是如何更新關(guān)于這個(gè)世界的知識(shí)的。到目前為止,我們還沒有給這種更新施加任何限制,所以它的知識(shí)可能變得非?;靵y:在一幀圖像里面它會(huì)認(rèn)為人物在美國,在下一幀它看到人在吃壽司,就會(huì)認(rèn)為人是在日本,在其后的一幀它看到了北極熊,就會(huì)認(rèn)為他們是在伊茲拉島?;蛘咭苍S它有大量的信息表明?Alice?是一名投資分析師,但是在它看到了她的廚藝之后它就會(huì)認(rèn)定她是一名職業(yè)殺手。


這種混亂意味著信息在快速地轉(zhuǎn)移和消失,模型難以保持長期的記憶。所以我們想要的是讓網(wǎng)絡(luò)學(xué)會(huì)如何讓它以一種更加溫和的方式來進(jìn)化自己關(guān)于這個(gè)世界的知識(shí),從而更新自己的信念(沒有?Bob?的場景不應(yīng)該改變關(guān)于?Bob?的信息包含?Alice?的場景應(yīng)該聚焦于收集關(guān)于她的一些細(xì)節(jié)信息)。


下面是我們?nèi)绾巫鲞@件事的?4?種方式:


1. 添加一個(gè)遺忘機(jī)制(forgetting?mechanism):如果一個(gè)場景結(jié)束了,模型應(yīng)該忘記當(dāng)前場景中的位置,一天的時(shí)間并且重置任何與場景相關(guān)的信息;然而,如果場景中的一個(gè)人死掉了,那么模型應(yīng)該一直記住那個(gè)死去的人已經(jīng)不再活著了。因此,我們想要模型學(xué)會(huì)一種有區(qū)分的遺忘/記憶機(jī)制:當(dāng)新的輸入到來時(shí),它需要知道記住哪些信念,以及丟棄哪些信念。

2. 添加一個(gè)保存機(jī)制(saving?mechanism):當(dāng)模型看到一副新的圖片時(shí),它需要學(xué)習(xí)關(guān)于這張圖片的信息是否值得使用和保存?;蛟S你媽媽給了你一片關(guān)于凱莉·詹娜的文章,但是誰會(huì)在乎呢?

3.?所以當(dāng)新的輸入來臨時(shí),模型首先要忘掉任何它認(rèn)為不再需要的長期記憶信息。然后學(xué)習(xí)新輸入的哪些部分是值得利用的,并將它們保存在自己的長期記憶中。

4. 將長期記憶聚焦在工作記憶中:最后,模型需要學(xué)習(xí)長期記憶中的哪些部分是即刻有用的。例如,Bob?的年齡可能是一條需要長期保持的信息(兒童很可能正在玩耍,而成年人很可能正在工作),但是如果他不在當(dāng)前的場景中,那么這條信息很可能就不是特別相關(guān)。所以,模型學(xué)習(xí)去聚焦哪一部分,而不總是使用完全的長期記憶。


這就是一個(gè)長短期記憶網(wǎng)絡(luò)(long?short-term?memory?network)。LSTM?會(huì)以一種非常精確的方式來傳遞記憶——使用了一種特定的學(xué)習(xí)機(jī)制:哪些部分的信息需要被記住,哪些部分的信息需要被更新,哪些部分的信息需要被注意。與之相反,循環(huán)神經(jīng)網(wǎng)絡(luò)會(huì)以一種不可控制的方式在每一個(gè)時(shí)間步驟都重寫記憶。這有助于在更長的時(shí)間內(nèi)追蹤信息。


數(shù)學(xué)描述


讓我們來對(duì)?LSTM?做一下數(shù)學(xué)描述。


在時(shí)間?t,我們收到了新的輸入?xt。我們也有自己的從之前的時(shí)間步中傳遞下來的長期記憶和工作記憶,ltm(t?1)以及?wm(t?1)(兩者都是?n?維向量),這就是我們想要更新的東西。


我們將要開始我們的長期記憶。首先,我們需要知道哪些長期記憶需要保持,哪些需要丟棄,所以我們想要使用新的輸入和我們的工作記憶來學(xué)習(xí)一個(gè)由?n?個(gè)介于?0?和?1?之間的數(shù)字組成的記憶門,每一個(gè)數(shù)字都決定一個(gè)長期記憶的元素被保持多少。(1?意味著完全保持,0?意味著完全丟棄。)


自然地我們可以使用一個(gè)小型神經(jīng)網(wǎng)絡(luò)來學(xué)習(xí)這個(gè)記憶門:


(注意與我們之前的神經(jīng)網(wǎng)絡(luò)方程的相似性;這只是一個(gè)淺層的神經(jīng)網(wǎng)絡(luò)。并且,我們使用了?sigmoid?激活函數(shù),因?yàn)槲覀冃枰臄?shù)字是介于?0?和?1?之間的。)


接下來,我們需要計(jì)算我們能夠從?xt?中學(xué)習(xí)到的信息,也就是我們長期記憶中的候選者:


?是一個(gè)激活函數(shù),通常選擇雙曲正切函數(shù)。


然而,在我們將這個(gè)候選者加進(jìn)我們的記憶之前,我們想要學(xué)到哪些部分是實(shí)際上值得使用和保存的:


(思考一下當(dāng)你在網(wǎng)頁上讀到某些內(nèi)容的時(shí)候會(huì)發(fā)生什么。當(dāng)一條新聞文章可能包含希拉里的信息時(shí),如果消息來源是?Breitbart,那你就應(yīng)該忽略它。)


現(xiàn)在讓我們把所有這些步驟結(jié)合起來。在忘掉我們認(rèn)為將來不會(huì)再次用到的信息以及保存有用的新來的信息之后,我們就有了更新的長期記憶:


接下來,來更新我們的工作記憶:我們想要學(xué)習(xí)如何將我們的長期記憶專注于那些將會(huì)即刻有用的信息上。(換句話說,我們想要學(xué)習(xí)將哪些信息從外部硬盤移動(dòng)到正在工作的筆記本內(nèi)存上。)所以我們會(huì)學(xué)習(xí)一個(gè)聚焦/注意向量(focus/attention?vector):


然后我們的工作記憶就成為了:



換言之,我們將全部注意集中在?focus?為?1?的元素上,并且忽略那些?focus?是?0?的元素。


然后我們對(duì)長期記憶的工作就完成了!也希望這能夠稱為你的長期記憶。


總結(jié):一個(gè)普通的?RNN?用一個(gè)方程來更新隱藏狀態(tài)/記憶:



而?LSTM?使用數(shù)個(gè)方程:


其中每一個(gè)記憶/注意子機(jī)制只是?LSTM?的一個(gè)迷你形式:


(注意:我在這里使用的術(shù)語和變量的名字和通常文獻(xiàn)中是有所不同的。以下是一些標(biāo)準(zhǔn)名稱,以后我將會(huì)交換使用:


  • 長期記憶?ltm(t),?通常被稱為**cell?state**,?簡寫?c(t).
  • 工作記憶?wm(t)?通常被稱為**hidden?state**,?簡寫?h(t)。這個(gè)和普通?RNN?中的隱藏狀態(tài)是類似的。
  • 記憶向量?remember(t),通常被稱為**forget?gate**?(盡管遺忘門中,1?仍舊意味著完全保持記憶?0?意味著完全忘記),簡稱?f(t)。
  • 保存向量?save(t),通常被稱為?input?gate,(因?yàn)樗鼪Q定輸入中有多少被允許進(jìn)入?cell?state),簡稱?i(t)。
  • 注意向量?focus(t),通常被稱為?output?gate,簡稱?o(t)。


卡比獸


寫這篇博文的時(shí)間我本可以抓一百只?Pidgeys,請(qǐng)看下面的漫畫。


神經(jīng)網(wǎng)絡(luò)


神經(jīng)網(wǎng)絡(luò)會(huì)以?0.6?的概率判定輸入圖片中的卡比獸正在淋浴,以?0.3?的概率判定卡比獸正在喝水,以?0.1?的概率判定卡比獸正在遭遇襲擊。


循環(huán)神經(jīng)網(wǎng)絡(luò)


當(dāng)循環(huán)神經(jīng)網(wǎng)絡(luò)被用來做這件事的時(shí)候,它具有對(duì)前一幅圖的記憶。最終結(jié)果是卡比獸正在遭遇襲擊的概率為?0.6,卡比獸正在淋浴的概率是?0.3,卡比獸正在喝水的概率是?0.1。結(jié)果要明顯好于上一幅圖中的神經(jīng)網(wǎng)絡(luò)。


LSTM



具備長期記憶的?LSTM,在記憶了多種相關(guān)信息的前提下,將對(duì)卡通圖畫中的場景描述準(zhǔn)確的概率提高到了?0.9。


學(xué)會(huì)編程


讓我們來看一下一個(gè)?LSTM?可以做到的一些例子吧。遵循著?Andrej?Karpathy?的精湛的博文(http://karpathy.github.io/2015/05/21/rnn-effectiveness/),我將使用字符級(jí)別的?LSTM?模型,這些模型接受字符序列的輸入,被訓(xùn)練來預(yù)測序列中的下一個(gè)字符。


雖然這看起來有點(diǎn)玩笑,但是字符級(jí)別的模型確實(shí)是非常有用的,甚至比單詞級(jí)別的模型更加有用。例如:


  • 試想一個(gè)自動(dòng)編程器足夠智能,能夠允許你在你的手機(jī)上編程。從理論上講,一個(gè)?LSTM?模型能夠追蹤你當(dāng)前所在函數(shù)的返回類型,可以更好地建議你返回那個(gè)變量;它也能夠在不經(jīng)過編譯的情況下通過返回的錯(cuò)誤類型就知道你是不是已經(jīng)造成了一個(gè)?bug。
  • 像機(jī)器翻譯這樣的自然語言處理應(yīng)用在處理罕見詞條的時(shí)候經(jīng)常會(huì)出現(xiàn)問題。你如何翻譯一個(gè)從未見過的單詞呢,或者你如何將一個(gè)形容詞轉(zhuǎn)換成動(dòng)詞呢?即使你知道一條推文的意思,你如何生成一個(gè)新的標(biāo)簽來描述它呢?字符級(jí)別的模型可以空想出新的項(xiàng),所以這是另外一個(gè)具有有趣應(yīng)用的領(lǐng)域。


所以就開始了,我啟動(dòng)了一個(gè)?EC2?p2.xlarge?spot?實(shí)例,并在?Apache?Commons?Lang?代碼庫(鏈接:https://github.com/apache/commons-lang)上訓(xùn)練了一個(gè)?3?層的?LSTM?模型。以下是幾個(gè)小時(shí)后生成的程序:


/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the "License"); you may not use this file except in compliance with* the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package org.apache.commons.math4.linear;import java.text.NumberFormat; import java.io.ByteArrayInputStream; import java.io.ObjectOutputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.List;import org.apache.commons.math4.optim.nonlinear.scalar.GoalType; import org.apache.commons.math4.ml.neuralnet.sofm.NeuronSquareMesh2D; import org.apache.commons.math4.distribution.DescriptiveStatistics; import org.apache.commons.math4.optim.nonlinear.scalar.NodeFieldIntegrator; import org.apache.commons.math4.optim.nonlinear.scalar.GradientFunction; import org.apache.commons.math4.optim.PointValuePair; import org.apache.commons.numbers.core.Precision;/*** <p>Natural infinite is defined in basic eigenvalues of a transform are in a subconsider for the optimization ties.</p>** <p>This implementation is the computation at a collection of a set of the solvers.</p>* <p>* This class is returned the default precision parameters after a new value for the interpolation interpolators for barycenter.* <p>* The distribution values do not ratio example function containing this interface, which should be used in uniform real distributions.</p>* <p>* This class generates a new standard deviation of the following conventions, the variance was reached as* constructor, and invoke the interpolation arrays</li>* <li>{@code a < 1} and {@code this} the regressions returned by calling* the same special corresponding to a representation.* </p>** @since 1.2*/ public class SinoutionIntegrator implements Serializable {/** Serializable version identifier */private static final long serialVersionUID = -7989543519820244888L;/*** Start distance between the instance and a result (does not all lead to the number of seconds).* <p>* Note that this implementation this can prevent the permutation of the preneved statistics.* </p>* <p>* <strong>Preconditions</strong>: <ul>* <li>Returns number of samples and the designated subarray, or* if it is null, {@code null}. It does not dofine the base number.</p>** @param source the number of left size of the specified value* @param numberOfPoints number of points to be checked* @return the parameters for a public function.*/public static double fitness(final double[] sample) {double additionalComputed = Double.POSITIVE_INFINITY;for (int i = 1; i < dim; i++) {final double coefficients[i] = point[i] * coefficients[i];double diff = a * FastMath.cos(point[i]);final double sum = FastMath.max(random.nextDouble(), alpha);final double sum = FastMath.sin(optimal[i].getReal() - cholenghat);final double lower = gamma * cHessian;final double fs = factor * maxIterationCount;if (temp > numberOfPoints - 1) {final int pma = points.size();boolean partial = points.toString();final double segments = new double[2];final double sign = pti * x2;double n = 0;for (int i = 0; i < n; i++) {final double ds = normalizedState(i, k, difference * factor);final double inv = alpha + temp;final double rsigx = FastMath.sqrt(max);return new String(degree, e);}}// Perform the number to the function parameters from one count of the valuesfinal PointValuePair part = new PointValuePair[n];for (int i = 0; i < n; i++) {if (i == 1) {numberOfPoints = 1;}final double dev = FastMath.log(perturb(g, norm), values[i]);if (Double.isNaN(y) &&NaN) {sum /= samples.length;}double i = 1;for (int i = 0; i < n; i++) {statistics[i] = FastMath.abs(point[i].sign() + rhs[i]);}return new PointValuePair(true, params);}}}/*** Computes the number of values* @throws NotPositiveException if {@code NumberIsTooSmallException if {@code seed <= 0}.* @throws NullArgumentException if row or successes is null*/public static double numericalMean(double value) {if (variance == null) {throw new NotStrictlyPositiveException(LocalizedFormats.NUMBER_OF_SUBCORSE_TRANSTOR_POPULATIONS_COEFFICIENTS,p, numberOfSuccesses, true);}return sum;}/*** {@inheritDoc}*/@Overridepublic LeastSquaresProblem create(final StatisticalSummary sampleStats1,final double[] values, final double alpha) throws MathIllegalArgumentException {final double sum = sumLogImpl.toSubSpace(sample);final double relativeAccuracy = getSumOfLogs();final double[] sample1 = new double[dimension];for (int i = 0; i < result.length; i++) {verifyInterval.solve(params, alpha);}return max;}/*** Test creates a new PolynomialFunction function* @see #applyTo(double)*/@Testpublic void testCosise() {final double p = 7.7;final double expected = 0.0;final SearchInterval d = new Power(1.0, 0.0);final double penalty = 1e-03;final double init = 0.245;final double t = 0.2;final double result = (x + 1.0) / 2.0;final double numeratorAdd = 13;final double bhigh = 2 * (k - 1) * Math.acos();Assert.assertEquals(0.0, true);Assert.assertTrue(percentile.evaluate(singletonArray), 0);Assert.assertEquals( 0.0, getNumberOfTrials(0, 0), 1E-10);Assert.assertEquals(0.201949230731, percentile.evaluate(specialValues), 1.0e-3);Assert.assertEquals(-10.0, distribution.inverseCumulativeProbability(0.50), 0);Assert.assertEquals(0.0, solver.solve(100, f, 1.0, 0.5), 1.0e-10);}

盡管這段代碼確實(shí)不是完美的,但是它比很多我認(rèn)識(shí)的數(shù)據(jù)科學(xué)家要做的好一些。我們可以發(fā)現(xiàn)?LSTM?已經(jīng)學(xué)會(huì)了很多有趣的(也是正確的!)編程行為。


  • 它懂得如何構(gòu)造類:?最頂部有?license?相關(guān)的信息,緊跟著是?package?和?import,再然后是注釋和類的定義,再到后面是變量和函數(shù)。類似地,它知道如何創(chuàng)建函數(shù):注釋遵循正確的順序(描述,然后是?@param,然后是?@return,等等),decorator?被正確放置,非空函數(shù)能夠以合適的返回語句結(jié)束。關(guān)鍵是,這種行為跨越了大篇幅的代碼——你看圖中的代碼塊有多大!
  • 它還能夠追蹤子程序和嵌套級(jí)別:縮進(jìn)總是正確的,if?語句和?for?循環(huán)總能夠被處理好。
  • 它甚至還懂得如何構(gòu)造測試。


那么模型是如何做到這一點(diǎn)的呢?讓我們來看一下幾個(gè)隱藏狀態(tài)。


下面是一個(gè)貌似在追蹤代碼外層縮進(jìn)的神經(jīng)元(當(dāng)讀取字符作為輸入的時(shí)候,也就是說,在嘗試生成下一個(gè)字符的時(shí)候,每一個(gè)字符都被著上了神經(jīng)元狀態(tài)的顏色;紅色的單元是負(fù)的,藍(lán)色的單元是正的):


下面是一個(gè)統(tǒng)計(jì)空格數(shù)量的神經(jīng)元:




娛樂一下,下面是在?TensorFlow?代碼庫上訓(xùn)練得到的另一個(gè)不同的?3?層?LSTM?模型的輸出:

"""Tests for softplus layer tests."""from __future__ import absolute_import from __future__ import division from __future__ import print_functionimport collections import numpy as npfrom tensorflow.python.platform import testclass InvalidAllOpCost(Experiment):def _runTestToIndForDead(self):return self._divs()def testPad(self):with ops.Graph().as_default():var = sess.run(bucketized_op)self.assertAllClose(list(variables.global_variables()), status.eval())def testHttptimenaterRoutingOptimizerSize(self):with self.test_session() as sess:table = lookup_ops.IdTableWithHashBuckets(keys=['id', 'z'],example_id_column='price',num_outputs=6,input_columns=['dummy_range', 'feature', 'dimensions'])with self.assertRaisesRegexp(ValueError, 'Expected dict of rank dimensions'):fc.numeric_column('aaa', indices=[[0, 0], [1, 0]], dtype=dtypes.int64)output = table.lookup(input_string)# all input tensors in SparseColumn has dimensions [end_back_prob, dimension] in the format.with self.assertRaisesRegexp(TypeError, "Shape of values must be specified during training."):fc.bucketized_column(attrs, boundaries=[62, 62])

網(wǎng)絡(luò)上還有很多有趣的例子,如果你想了解更多,請(qǐng)查看:http://karpathy.github.io/2015/05/21/rnn-effectiveness/


研究?LSTM?的內(nèi)部


讓我們再稍往深處挖掘一下。我們看一下上一部分隱藏狀態(tài)的例子,但是我也想玩轉(zhuǎn)?LSTM?cell?狀態(tài)以及其他的記憶機(jī)制。我們期待著,它們會(huì)迸發(fā)出火花呢,還是會(huì)有令人驚喜的畫面?


計(jì)數(shù)


為了研究,讓我們從教一個(gè)?LSTM?計(jì)數(shù)開始。(你應(yīng)該還記得?Java?和?Python?的?LSTM?模型是如何生成合適的縮進(jìn)的!)所以我生成了如下形式的序列:

aaaaaXbbbbb

(N?個(gè)字母「a」,后面跟著一個(gè)字母分隔符?X,后面是?N?個(gè)字母「b」,其中?1?<=?N?<=?10),然后訓(xùn)練一個(gè)具有?10?個(gè)隱藏神經(jīng)元的單層?LSTM。


不出所料,LSTM?模型在訓(xùn)練期間完美地學(xué)習(xí)--甚至能夠?qū)⑸赏茝V到幾步之外。(即使在開始的時(shí)候當(dāng)我們嘗試讓它記到?19?的時(shí)候它失敗了。)

aaaaaaaaaaaaaaaXbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaaXbbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaaaXbbbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaaaaXbbbbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaaaaaXbbbbbbbbbbbbbbbbbb # Here it begins to fail: the model is given 19 "a"s, but outputs only 18 "b"s.


我們期望找到一個(gè)隱藏狀態(tài)神經(jīng)元,它能夠在我們觀察模型內(nèi)部的時(shí)候計(jì)出每一個(gè)?a?的數(shù)目。正如我們做的:



我開發(fā)了一個(gè)可以讓你玩轉(zhuǎn)?LSTM?的小型的?web?app,神經(jīng)元?#2?貌似既能夠記錄已經(jīng)看到的?a?的數(shù)目,也能記錄已經(jīng)看到的字符?b?的數(shù)目。(請(qǐng)記得,單元的顏色是根據(jù)激活程度著色的,從深紅色的?[-1]?到深藍(lán)色的?[+1]。)


那么?cell?的狀態(tài)是怎么樣的呢?它的行為類似于這樣:


有趣的是,工作記憶就像是長期記憶的「銳化版」。但是這個(gè)在一般情況是否成立呢?


這確實(shí)是成立的。(我正是我們所期望的,因?yàn)殚L期記憶被雙曲正切激活函數(shù)進(jìn)行了壓縮,而且輸出門限制了通過它的內(nèi)容。)例如,下圖是所有的?10?個(gè)?cell?在某一時(shí)刻的狀態(tài)。我們看到了大量的顏色很清淡的?cell,這代表它們的值接近?0。


相比之下,10?個(gè)工作記憶的神經(jīng)元看起來更加聚焦。第?1、3、5、7?個(gè)神經(jīng)元甚至在序列的前半部分全是?0。


讓我們再回頭看一下神經(jīng)元?#2。這里有一些候選的記憶和輸入門。它們在每個(gè)序列的前半部分或者后半部分都是相對(duì)不變的——就像神經(jīng)元在每一步都在進(jìn)行?a+=1?或者?a-=1?的計(jì)算。




最后,這里是神經(jīng)元?2?的整體概覽:


如果你想自己研究一下不同計(jì)數(shù)神經(jīng)元,你可以在這個(gè)可視化?web?app?中自己玩一下。


(注意:這遠(yuǎn)遠(yuǎn)不是一個(gè)?LSTM?模型可以學(xué)會(huì)計(jì)數(shù)的唯一方式,我在這里只描述了一個(gè)而已。但是我認(rèn)為觀察網(wǎng)絡(luò)行為是有趣的,并且這有助于構(gòu)建更好的模型;畢竟,神經(jīng)網(wǎng)絡(luò)中的很多思想都是來自于人腦。如果我們看到了意料之外的行為,我們也許會(huì)有能力設(shè)計(jì)出更加有效地學(xué)習(xí)機(jī)制。)


來自計(jì)數(shù)的計(jì)數(shù)


讓我們來看一下一個(gè)稍微有點(diǎn)復(fù)雜的計(jì)數(shù)器。這次,我生成了如下的序列形式:

aaXaXaaYbbbbb

(N?個(gè)?a?中間隨機(jī)地插入?X,后邊跟一個(gè)分隔符?Y,再后邊是?N?個(gè)?b。)LSTM?仍然必須數(shù)清楚?a?的數(shù)目,但是這一次需要忽略?X?的數(shù)目。


在這個(gè)鏈接中查看整個(gè)?LSTM(http://blog.echen.me/lstm-explorer/#/network?file=selective_counter)我們希望看到一個(gè)正在計(jì)數(shù)的神經(jīng)元——一個(gè)正在計(jì)數(shù)的、每看到一個(gè)?X?輸入門就變成?0?的神經(jīng)元。在我們做到了!




上圖是?neuron?20?的?cell?狀態(tài)。它的值一直保持增大,直到遇到分割字符?Y,然后就一直減小,直到序列的末尾——就像在計(jì)算一個(gè)隨著?a?增大,隨著?b?減小的變量?num_bs_left_to_print?一樣。


如果我們觀察它的輸入門,會(huì)看到它確實(shí)是將?X?的數(shù)量忽略了:


然而,有趣的是,候選的記憶會(huì)在有關(guān)聯(lián)的?X?上被完全激活--這證明了為什么需要哪些輸入門。(但是,如果輸入門不是模型架構(gòu)的一部分,至少在這個(gè)簡單的例子中,網(wǎng)絡(luò)也會(huì)以其他的方式忽略?X?的數(shù)量。)



我們再來看一下神經(jīng)元?10。




這個(gè)神經(jīng)元是有趣的,因?yàn)樗鼉H僅在讀取到?Y?的時(shí)候才會(huì)被激活—然而它還是能夠?qū)π蛄兄杏龅降?a?字符進(jìn)行編碼。(在圖中可能很難區(qū)分出來,但是序列中?a?的數(shù)目一樣的時(shí)候,Y?的顏色是相同的,即便不相同,差距也在?0.1%?以內(nèi)。你可以看到,a?比較少的序列中?Y?的顏色要淺一些。)或許其他的神經(jīng)元會(huì)看到神經(jīng)元?10?比較松弛。



記憶狀態(tài)


下面我想研究一下?LSTM?是如何記憶狀態(tài)的。同樣的,我生成了以下形式的序列:

AxxxxxxYa BxxxxxxYb

(也就是說,一個(gè)「A」或者「B」,后面跟著?1-10?個(gè)?x,然后是一個(gè)分割字符「Y」,最終以一個(gè)起始字符的小寫形式結(jié)尾。)這種情況下,網(wǎng)絡(luò)需要記住到底是一個(gè)「狀態(tài)?A」還是一個(gè)「B」?fàn)顟B(tài)。


我們希望找到一個(gè)神經(jīng)元能夠在記得序列是以「A」開頭的,希望找到另一個(gè)神經(jīng)元記得序列是以「B」開頭的。我們做到了。


例如這里是一個(gè)「A」神經(jīng)元,當(dāng)讀取到「A」的時(shí)候它會(huì)激活,持續(xù)記憶,直到需要生成最后一個(gè)字母的時(shí)候。要注意,輸入門忽略了序列中所有的?x。


下面是對(duì)應(yīng)的「B」神經(jīng)元:


有趣的一點(diǎn)是,即使在讀取到分隔符「Y」之前,關(guān)于?A?和?B?的知識(shí)是不需要的,但是隱藏狀態(tài)在所有的中間輸入中都是存在的。這看上去有一點(diǎn)「低效」,因?yàn)樯窠?jīng)元在計(jì)數(shù)?x?的過程中做了一些雙重任務(wù)。



復(fù)制任務(wù)


最后,讓我們來看一下?LSTM?是如何學(xué)會(huì)復(fù)制信息的。(回想一下我們的?Java?版的?LSTM?曾經(jīng)學(xué)會(huì)了記憶并且復(fù)制一個(gè)?Apache?license。)


(注意:如果你思考?LSTM?是如何工作的,記住大量的單獨(dú)的、細(xì)節(jié)的信息其實(shí)并不是它們所擅長的事情。例如,你可能已經(jīng)注意到了?LSTM?生成的代碼的一個(gè)主要缺陷就是它經(jīng)常使用未定義的變量—LSTM?無法記住哪些變量已經(jīng)在環(huán)境中了。這并不是令人驚奇的事情,因?yàn)楹茈y使用單個(gè)?cell?就能有效地對(duì)想字符一樣的多值信息進(jìn)行編碼,并且?LSTM?并沒有一種自然的機(jī)制來連接相鄰的記憶以形成單詞。記憶網(wǎng)絡(luò)(memory?networks)和神經(jīng)圖靈機(jī)(neutral?turing?machine)就是兩種能夠有助于修正這個(gè)缺點(diǎn)的神經(jīng)網(wǎng)絡(luò)的擴(kuò)展形式,通過增加外部記憶組件。所以盡管復(fù)制并不是?LSTM?可以很有效地完成的,但是無論如何,去看一下它是如何完成這個(gè)工作是有趣的。)


針對(duì)這個(gè)復(fù)制任務(wù),我訓(xùn)練了一個(gè)很小的兩層?LSTM?來生成如下形式的序列:


baaXbaa abcXabc


(也就是說,一個(gè)由?a、b、c3?種字符組成的子序列,后面跟著一個(gè)分隔符「X」,后面再跟著一個(gè)同樣的子序列)。


我不確定「復(fù)制神經(jīng)元」到底應(yīng)該是長什么樣子的,所以為了找到能夠記住部分初始子序列的神經(jīng)元,我觀察了一下它們在讀取分隔符?X?時(shí)的隱藏狀態(tài)。由于神經(jīng)網(wǎng)絡(luò)需要編碼初始子序列,它的狀態(tài)應(yīng)該依據(jù)它們學(xué)到的東西而看起來有所不同。


例如,下面的這一幅圖畫出了神經(jīng)元?5?在讀入分隔符「X」時(shí)候的隱藏狀態(tài)。這個(gè)神經(jīng)元明顯將那些以「c」開頭的序列從那些不是以「c」開頭的序列中區(qū)分出來。


另一個(gè)例子,這是神經(jīng)元?20?在讀入分隔符「X」時(shí)的隱藏狀態(tài)??雌饋硭x擇了那些以「b」開頭的子序列。




有趣的是,如果我們觀察神經(jīng)元?20?的?cell?狀態(tài),它貌似能夠捕捉這三種子序列。


這里是神經(jīng)元?20?關(guān)于整個(gè)序列的?cell?狀態(tài)個(gè)隱藏狀態(tài)。請(qǐng)注意在整個(gè)初始序列中它的隱藏狀態(tài)是關(guān)閉的(也許這是期望之中的,因?yàn)樗挠洃泝H僅需要在某一點(diǎn)被動(dòng)保持)。



然而,如果我們看得更加仔細(xì)一些,就會(huì)發(fā)現(xiàn),只要下一個(gè)字符是「b」,?它就是正的。所以,與其說是以?b?字母開頭的序列,還不如說是下一個(gè)字符是?b?的序列。


就我所知,這個(gè)模式在整個(gè)網(wǎng)絡(luò)中都存在——所有的神經(jīng)元貌似都在預(yù)測下一個(gè)字符,而不是在記住處在當(dāng)前位置的字符。例如,神經(jīng)元?5?貌似就是一個(gè)「下一個(gè)字符」預(yù)測器.



我不確定這是不是?LSTM?在學(xué)習(xí)復(fù)制信息時(shí)候的默認(rèn)類型,或者復(fù)制機(jī)制還有哪些類型呢?


擴(kuò)展


讓我們來回顧一下你如何自己來探索?LSTM。


首先,我們想要解決的大多數(shù)問題都是階段性的,所以我們應(yīng)該把一些過去的學(xué)習(xí)結(jié)合到我們的模型中。但是我們早已知道神經(jīng)網(wǎng)絡(luò)的隱藏層在編碼自己的信息,所以為何不使用這些隱藏層,將它們作為我們向下一步傳遞的記憶呢?這樣一來,我們就有了循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)。


但是從我們的行為就能知道,我們是不愿意去追蹤知識(shí)的;當(dāng)我們閱讀一篇新的政論文章時(shí),我們并不會(huì)立即相信它所談?wù)摰膬?nèi)容并將其與我們自己對(duì)這個(gè)世界的信念所結(jié)合。我們選擇性地保存哪些信息,丟棄哪些信息,以及哪些信息可以用來決定如何處理下一次讀到的新聞。因此,我們想要學(xué)習(xí)收集、更新以及應(yīng)用信息——為何不通過它們自己的小型神經(jīng)網(wǎng)絡(luò)來學(xué)習(xí)這些東西呢?如此,我們就有了?LSTM。


現(xiàn)在我們已經(jīng)走通了這個(gè)過程,我們也可以想出我們的修正:


  • 例如,或許你認(rèn)為?LSTM?區(qū)分長期記憶和工作記憶是愚蠢的行為—為何不使用一種記憶呢?或者,或許你能夠發(fā)現(xiàn)區(qū)分記憶門和保存門是多余的--任何我們忘記地東西都應(yīng)該被新的信息代替,反之亦然。所以我們現(xiàn)在想出了一種流行的?LSTM?變種,門控循環(huán)神經(jīng)網(wǎng)絡(luò)(GRU):https://arxiv.org/abs/1412.3555
  • 或者你可能認(rèn)為,當(dāng)決定哪些信息需要被記住、保存、注意的時(shí)候,我們不應(yīng)該僅僅依靠我們的工作記憶—為什么不同時(shí)使用長期記憶呢?如此,你發(fā)現(xiàn)了?Peephole?LSTM。


讓我們看一下最后的例子,使用一個(gè)兩層多的?LSTM?來訓(xùn)練?Trump?的推特,盡管這是很大規(guī)模的數(shù)據(jù)集,但是這個(gè)?LSTM?已經(jīng)足以學(xué)到很多模式。


例如,這是一個(gè)在標(biāo)簽、URL?以及?@mention?中跟蹤位置的神經(jīng)元:


這是一個(gè)合適的名詞檢測器(注意它并不是簡單的注重大寫單詞):


這是一個(gè)助動(dòng)詞+「to?be」的檢測器(例如?will?be,?I've?always?been,has?never?been)



這是一個(gè)引文屬性:



這是一個(gè)?MAGA?和大小寫神經(jīng)元:


這里是一些用?LSTM?生成的公告(ok,其中有一個(gè)是一條真正的推特,你猜一下哪個(gè)是):


不幸的是,LSTM?僅僅學(xué)會(huì)了像瘋子一樣瘋狂書寫。

總結(jié)

以上是生活随笔為你收集整理的LSTM入门必读:从入门基础到工作方式详解 By 机器之心2017年7月24日 12:57 长短期记忆(LSTM)是一种非常重要的神经网络技术,其在语音识别和自然语言处理等许多领域都得到了广泛的应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。