引言
本文是接上一篇李宏毅機器學習——循環神經網絡(一)
Learning Target
在RNN中如何定義損失函數呢。還是以Slot Filling為例,給定一些句子作為訓練資料
并且要給這些句子一些标簽,告訴機器第一單詞arrive屬于other這個slot,Taipei屬于dest這個slot等。
此時要怎麼定義損失函數呢,比如把arrive丢到RNN中後,可以得到一個輸出,接下來這個要和參考向量計算交叉熵。
再把Taipei丢到RNN中取希望得到的與這個參考向量計算交叉熵,越小越好。這裡注意是有順序的,在把Taipei丢進去之前,一定要先丢arrive。
Learing(訓練)
現在有了損失函數後,如果做訓練呢,還是用梯度下降。
還是計算對的偏微分,用梯度下降的方法更新參數。在NN中我們用反向傳播算法來更新參數,而在RNN中,需要使用反向傳播算法的更新版——基于時間的反向傳播算法(BPTT)。這裡不細講BPTT了。
不幸的是,RNN的訓練是比較困難的。
一般來說,在做訓練的時候,希望學習曲線是藍色的這條線。但是在訓練RNN的時候,可能會看到綠色的這條線。
為什麼會這樣呢,因為誤差曲面要麼非常陡峭,要麼非常平緩。平緩的時候學習的非常慢,此時你嘗試增大學習率,結果又遇到了陡峭的曲面,然後整個損失會急劇上升。
那麼怎麼辦呢,RNN的提出者就想了一招,叫Clipping(修建),當梯度大于某個門檻值的時候,就把梯度取那個門檻值,通常門檻值取15。
那為什麼誤差曲面是這樣呢。
這裡以一個簡單的RNN為例,它隻有一個線性的神經元。假設這個網絡的輸入是。那麼在第1000個時間點的輸出就是。
然後我們嘗試改變的值,變動,如果我們增大,那麼最終會得到的輸出是20000(這時可能需要一個很小的學習率),也就是20000倍! 反之如果減少,最終得到的值為(此時又需要很大的學習率)。
因為從記憶體接到神經元的那一組權重是反複被使用的(比如這裡被使用了1000次),造成的變換一旦有影響,那麼影響是巨大的。
那有什麼樣的技巧可以幫助我們解決這個問題呢,現在常用的就是LSTM。它能讓你的誤差曲面不那麼崎岖,能解決梯度消失的問題,但是不能解決梯度爆炸的問題。
是以你可以把學習率設得小一點。
這也是為什麼常用LSTM而不是RNN的原因。
為什麼LSTM能處理梯度消失的問題呢,RNN和LSTM在處理記憶體的方式是不一樣的。在RNN中,每個時間點,記憶體中的資料都會被覆寫掉。
但在LSTM中是把原來記憶體中的值乘上一個值,再加上輸入的值,最後再覆寫。
如果權重可以影響到記憶體中的值,一旦發生影響,那麼這個影響會一直存在(除非被遺忘門忘掉),不像RNN在每個時間點會被覆寫掉。
現在比較流行的一種RNN是GRU(Gated Recurrent Unit),它比LSTM要簡單,隻有兩個門,更新門和重置門。是以它需要的參數量比較少,也就是模型更新簡單,不容易過拟合。
GRU需要把存在記憶體中的值洗掉,才可以存入新的值。
更多的應用
其實RNN除了填槽,還有很多應用。
在上面填槽的時候,我們假設輸入和輸出的序列是一樣長的。實際上RNN還可以做更複雜的事情。
比如輸入是一個向量序列,但輸出可以隻是一個向量,常用的場景就是情感分析(sentiment analysis)。
比如分析電影的評價。
還可以做關鍵字抽取。
上面都是多(個向量)對一(個向量)的情況,還可以做多對多,不過輸出的多個向量要比輸入的要短。
比如在語音識别中,每隔一小段時間就用一個向量來表示,這一小段時間可以是0.01秒,輸出就是字元串。
如果我們用做填槽的那個RNN來做語音識别的話,它最多就輸出每個向量對應的字元。
因為這一小段時間很短,哪怕你講話講得再快,一個字也會對應多個時間段,也就會有多個向量。比如這裡輸出是“好好好棒棒棒棒棒”。
可以通過Trimming拿掉重複的字元,但這樣會有一個問題,可能真正對應的字元串是“好棒棒”。
Connectionist Temporal Classification (CTC) [Alex Graves, ICML’06][Alex Graves, ICML’14][Haşim Sak, Interspeech’15][Jie Li, Interspeech’15][Andrew Senior, ASRU’15]
怎麼辦呢,可以用CTC,主要思想就是在輸出的時候,除了輸出中文字元,還可以輸出一個代表沒有任何東西
null
的符号。
如果我們的輸出是這樣的,就可以把拿掉,得到輸出“好棒”。
或者這樣可以得到“好棒棒”。CTC在做訓練的時候,隻給定聲音特征(Acoustic Features)和最終的标簽(好棒)。
但不會給定“好”、“棒”以及分别對應哪幾個向量,此時需要窮舉所有可能的排列。
然後我們不知道哪個是對的,隻好假設每個都是對的,在訓練的時候全部都當成是正确的進行訓練。下面是文獻得到的結果:
Graves, Alex, and Navdeep Jaitly. “Towards end-to-end speech recognition with recurrent neural networks.” Proceedings of the 31st International Conference on Machine Learning (ICML-14). 2014.
另一個神奇的應用是機器翻譯,此時輸入和輸出都是序列,但不确定輸入和輸出哪個比較長。
[Ilya Sutskever, NIPS’14][Dzmitry Bahdanau, arXiv’15]
除了都是輸出序列外,還可以進行句法分析。
Oriol Vinyals, Lukasz Kaiser, Terry Koo, Slav Petrov, Ilya Sutskever, Geoffrey Hinton, Grammar as a Foreign Language, NIPS 2015
Seq2Seq Auto-encoder
文本
我們之前講過把一個文檔表示成向量的話, 往往會用詞袋法,但是這種方法會忽略掉單詞之前的順序資訊。
比如上面兩句話white blood cells destroying an infection(白細胞殺死細菌),和an infection destroying white blood cells(細菌殺死白細胞)。它們裡面的詞彙是一樣的,但是因為順序不同,表示的意思完全相反。如果我們用Seq2Seq Auto-encoder這種做法,來考慮序列順序的情況下,把一個文檔變成一個向量。
Li, Jiwei, Minh-Thang Luong, and Dan Jurafsky. “A hierarchical neural autoencoder for paragraphs and documents.” arXiv preprint arXiv:1506.01057(2015).
輸入一個單詞序列“Mary was hungy.she didn’t find any food”,通過一個RNN把它變成一個詞嵌入向量,再把這個詞嵌入向量當做Decode的輸入,然後讓這個Decode輸出一模一樣的句子(倒序)。
那編碼的向量代表這個輸入序列的重要資訊,我們就可以通過這個Encoded 向量來讓這個Decode把這個序列解碼回來。
語音
Seq2Seq auto-encoder還可以用在語音上。
可以給變長的語音序列降維,将一段聲音訊号變成固定長度的向量。
比如不同的描述dog的語音經過降維變成向量後,它們分布的距離是比較接近的。
Yu-An Chung, Chao-Chung Wu, Chia-Hao Shen,
Hung-Yi Lee, Lin-Shan Lee, Audio Word2Vec: Unsupervised Learning of Audio Segment Representations using Sequence-to-sequence Autoencoder, Interspeech 2016
那這種技術有什麼用呢,還是有很多用的,比如可以用來進行語音搜尋。
那麼要怎麼做呢,先把輸入的聲音訊号變成一段一段的,然後用上面介紹的技術把它們變成向量。
然後來一個人,講一段語音,也把它變成向量,接下來計算這個向量與庫裡面向量的相似度,就可以得到搜尋結果了。
那怎麼把聲音訊号變成一個向量呢?
先把聲音訊号抽成聲學特征段(acoustic features segment),然後丢到RNN中去,這個RNN起到Encoder的作用。
在RNN讀過這個聲學特征段後,它最後時間點存在記憶體中的值就成代表整個聲音訊号,存在記憶體中的值是個向量,而這個向量就是我們想要的,這樣就把一段聲音訊号轉換為一個向量。
那現在的問題是如何訓練RNN解碼器呢?
RNN解碼器的作用是把編碼器存在記憶體中的值當做輸入,産生一個聲學特征,然後希望和越接近越好;
然後根據産生,根據産生…
這樣其實RNN編碼器和RNN解碼器可以一起訓練的。
Attention-based Model
除了RNN用到了memory以外,還有另外一種網絡也用到的,就是Attention-based Model。
可以把它看成是RNN更新版,我們知道人的大腦可以同時記得很多東西,比如可以同時記得早餐吃了什麼和10年前的夏天發生的事情。
當有人問你什麼是深度學習的時候,你的腦中會提取重要資訊,然後把這些資訊組織起來,得到答案。但是此時你的大腦會自動忽略無關的資訊,比如10年前夏天發生的事情。
我們也可以讓機器有個很大的記憶容量
可以配置設定一個很大的空間,裡面可以放很多向量,每個向量可以存放某種記憶。
當你把輸入喂給DNN或RNN的時候,這個NN會操控一個Reading Head Controller(DispatchServletController?),這個Controller會決定Reading Head放的位置,
然後機器會從Reading Head的位置讀取資訊出來,然後産生最後的輸出。
它還有一個2.0的版本,這個新版本它可以操控一個Writing Head Controller,這個Controller會決定在哪裡寫,然後機器會把資訊寫到這個位置。這個東西就是大名鼎鼎的神經圖靈機。
Reading Comprehension
現在Attention-based Model常用在閱讀了解(Reading Comprehension,不是高中做的英語閱讀了解啊)裡面。
所謂閱讀了解就是讓機器去讀一堆文檔,機器把文檔中的每句話變成一個向量,每個向量代表每句話的語義。
接下來你可以問機器一些問題,看它了解了這些文檔沒有。
這些問題會丢進中央處理器裡面(DNN/RNN),由它來決定哪些向量是與這些個問題有關的。