本文首發於微信公衆號:查叔筆錄
前段在公司做YouTube Dnn模型的復現,然後想在YouTube DNN(Deep Neural Network)裏面加一下魔幻的搭配,就去了解了一下Attention。
可是,很多事情要更詳細的瞭解難免追根溯源。
最後回溯到Seq2Seq模型,本篇主要介紹一下Seq2Seq相關的一些內容,爲後面的Attention機制的瞭解做一下鋪墊。
一般我在瞭解一個新概念之前會先找一個稍微正經一點的資料,不要被中文資料把自己帶跑偏了。一般用的是維基百科。
什麼是Seq2Seq模型
維基百科裏面關於Seq2Seq的介紹:
Seq2seq is a family of machine learning approaches used for language processing. Applications include language translation, image captioning, conversational models and text summarization.
Seq2seq是機器學習裏用於自然語言處理的一個算法簇,主要應用於語言翻譯,圖像字幕,會話模型和文本摘要提取。
Seq2Seq模型起初是谷歌發明用於做機器翻譯的算法。
此外,在2019年12月Facebook在<<Deep learning for symbolic mathematics>>中提出了用Seq2Seq求解符號數學問題,包括函數微分,一階常微分方程,二階常微分方程等複雜問題。
不明覺厲。 小朋友,你是否有很多問號???
目前主流的Seq2Seq模型包括:
- RNN(Recurrent Neural Network,循環神經網絡)
- LSTM(Long Short-Term Memory, 長短期記憶網絡)
- GRU(Gated recurrent unit)
Seq2Seq 模型的輸入是一系列的單詞,輸出是被翻譯過後的另外一個系列的單詞。
在Seq2seq模型中主要分爲兩個部分:
-
編碼階段: 在編碼階段,Seq2seq模型的編碼器(Encoder)將輸入的序列(比如一箇中文句子)編碼爲一個隱藏層向量。
-
解碼階段: 在解碼階段,Seq2seq模型的解碼器(Decoder)將隱藏層的向量解碼爲輸出序列(比如一個英文句子)。
Seq2Seq中的RNN
接下來,我們以RNN爲例,進一步瞭解Seq2Seq模型的內部結構。
在上面的圖中,爲了進一步解析了RNN的具體結構,將圖1中的黑盒進一步透明化。
上圖中的RNN cell
表示RNN模型中的一個神經元細胞。
每一個神經元細胞的輸入包括兩個部分input
和hidden state #0
。
輸出同樣的包括兩個部分output
和hidden state #2
對於RNN而言,每一個神經元的輸入hidden #t
,是上一個神經元t-1的輸出。
舉一個簡單的例子:
在RNN模型中我們以:
今天你被綠了。
作爲輸入得到的輸出爲:
Your wife cheated on you today.
那麼對於RNN的神經元細胞而言對應的六次輸入輸出分別爲:
輸入1: 今
hidden state #0
輸出1: Your
hidden state #1
輸入2: 天
hidden state #1
輸出2: wife
hidden state #2
輸入3: 你
hidden state #2
輸出3: cheated
hidden state #3
…依此類推。
上述的例子並不表示實際情況(實際情況是你連對象都沒有),只是爲了表示hidden state #t
和 hidden state #t-1
之間的關係。
很明顯的,在RNN中以上一個神經元的輸出hidden state #t-1
作爲下一個神經元的輸入主要是爲了捕獲上下文之間的語意關係。
而hidden state #t-1
和 hidden state #t
所記錄的關係的作用有點像我們小學作業裏面填寫單位。
小明身高1.75 __ (米,釐米,毫米,千米)
小王的爸爸是一 ___ 出租車司機(個,頭,匹)
在RNN模型中通過hidden state的向下傳播記錄了詞彙之間的序列關係,從而讓我們記住了需要填寫哪一個詞彙,或者說哪一個詞彙更符合現在的語境。
Seq2Seq模型上所做的優化
在Seq2Seq模型的基礎之上,後來的研究人員爲了進一步提升模型的效果有了其他的一些研究和優化。
主要的優化操作包括:
- Attention
Attention 翻譯過來的中文名叫做注意力機制。所謂的注意力機制就是神經網絡需要處理大量的序列信息的時候,通過Attention機制達到關注重要信息的目的。
我們還是以上面這個例子爲例:你今天被綠了。
如果現在輸入變成:
你今天下午加班的時候正在看一篇<<什麼是Seq2Seq模型>>的微信公衆號文章。然後,你的老婆給你打了一個電話:說她感冒了正在醫院。你說:你很忙沒有空接她的電話。就掛掉了。然後她打電話找了她的前任,於是你被綠了。
當我們輸入一個很長的序列的時候,關注的點不可能是全部的信息,或者關注的信息所有偏重。
這個時候通過Attention機制挑選出一些重要的信息進行加權作爲輸入。
這樣做可以直觀理解的優勢有兩個:
(1) 通過Attention方式挑選重點信息作爲輸入,減少了複雜模型的計算量。
(2) 通過Attention方式將信息壓縮,在處理長序列的時候能夠記住更多的信息。
這個過程是不是有點像我們小學的時候的縮寫句子?
- Beam Search
聊到Beam search,我第一時間想到的阿里的TDM(Tree-based Deep Model)。
雖然,對TDM的具體原理我不是很理解,但是第一次聽到Beam search的時候是在阿里的關於TDM的一次分享會上。
Beam Search 具體是指:
在當前級別的狀態下計算所有可能性,並按照遞增順序對他們進行排序,但只保留一定數量的可能結果(依據Beam Width決定數量),接着根據這些可能結果進行擴展,迭代以上的動作直到搜索結束並返回最佳解(具有最高概率的那個).
我知道看完上面這段話的時候你也不知道Beam search是在幹嘛的,但是沒有關係。
雖然我們做事情要認真一些,但是很多很多事情點到爲止。這一次搞不懂的俺們下次再搞懂。今天的重點是瞭解一下Seq2Seq模型。
- Bucketing
Bucketing(裝桶)和Padding(填充)主要是爲了處理不同長度的句子。我是這麼理解的。
在處理翻譯問題的時候。如果輸入輸出Seq的長度不同。假如,輸入的Seq長度爲 輸出的Seq 長度爲
還是上面的例子爲例,如果輸入是:
你今天被你老婆的前任綠了。
輸出假設還是原來的樣子:
Your wife cheated on you today.
那麼對應的輸入和輸出的Seq序列長度不等(當然實際上中文是要分詞的)。
這個是時候,我們需要訓練一個長度的Seq 到 長度的Seq模型。
如果輸入有 種長度,輸出有 種長度那麼我們理論上需要設計最大到 種可能組合的子圖。
很顯然,這樣在實際的訓練過程中是不太可能的。
這個時候我們通過padding的方式,對輸入序列或者輸出序列做固定字段的填充來達到序列長度相同的效果。
舉個例子。一共有5組Seq2Seq的輸入輸出對,對應的輸入長度 和輸出長度 分別如下。
輸入長度 | 輸出長度L2 |
---|---|
10 | 20 |
9 | 17 |
2 | 3 |
20 | 60 |
25 | 52 |
這個時候如果不採用padding的方式,對應就有5種對應序列長度輸入輸出的子圖。
爲了減少子圖的數量,我們採用Padding的方式,統一輸入輸出的長度。
對輸入我們統一Padding達到的長度爲25,對輸出我們統一padding達到的長度爲60。
這種情況下,只需要訓練一個Seq2Seq的子圖。
OK, 這個時候出來了另外一個問題。
對於對三條數據,輸入的長度爲2,輸出的長度爲3。如果採用Padding的方式。那麼會存在大量的無效輸入從而產生大量的低效計算。
我摸着禿掉的頭想一想,我還不如多訓練一個子圖來得實在呢。
這個時候Bucketing應運而生,具體思路應該是這個樣子。
[1] 首先,我們確定了Padding這種思想的有效性。
[2] 其次,我們對全局使用同一個長度的Padding是否能夠帶來效率的提升持懷疑態度。或者是否有其他方式能夠使得效率更高存在保留意見。
[3] 最後,我們提出了一種新的方法,以少量的Bucketing和少量的Padding進行折中處理,使得效率最大化。
這個時候對於上述例子,我們可以對所有的輸入輸出對分成兩個桶。
這時候我們需要訓練兩個子圖,但是同樣的獲取了兩種Padding的方式。例如我們的分桶爲{[10, 20],[20, 60]}
那麼對應上述的五個例子,Padding之後的輸入就是:
Padding 後長度 | Padding 後長度L2 |
---|---|
10 | 20 |
10 | 20 |
10 | 20 |
20 | 60 |
20 | 60 |
如果到這裏,大家還沒有理解Padding和Bucketing結合使用的作用呢!
我就再勉爲其難地再舉一個例子。
假設,你家有開了一個伐木場。你是場裏的光頭強。
你砍掉的木頭要從伐木場運送到傢俱廠,但是木頭的長度不一樣(前提是不能鋸成一樣的長度。)
這種時候你要去租車公司租車。每輛車10000塊,但是每種車跑一趟耗油量不同,大車可能耗油300塊,中車150塊,小車100塊,嬰兒車50塊錢一趟等等還有其他車。
這個時候爲了把木材運完,你選擇租用哪幾種類型的就是選用了哪幾種Bucketing,當你使用一個能裝大木材的汽車裝一個小木材,就相當於使用了Padding操作。
每一輛車相當於一個Seq2Seq的子圖。每一次運送相當於一次計算。Bucketing和Padding結合的目的是爲了花最少的錢把木材運完。
這裏的錢就表示我們的算力。
最後
以上爲了說明所舉出的例子麼有任何惡意。
只是希望提醒的是,所有的加班和技術的使用以及學習是爲了更好地生活,而不是成爲一個更好的工具人。
所以,工作之外應該還有很多人需要去陪伴和守護。
同樣,技術只是手段,我們可以熱愛技術但是也可以有更多和更好的其他目的。
論語裏面說:君子不器。
最後,如果可以我希望通過技術解放自己,解放一批人。
當有一天我們每一個人都可以真正遵從內心的喜好去生活的時候。當我們每一個人的天賦可以充分的被釋放並且得以彰顯的時候。
那個時候是真正的——君子不器。