Paper創新點毫無頭緒?要不試試這個百搭的Attention?

  • 2019 年 10 月 6 日
  • 筆記

重磅乾貨,第一時間送達

本文轉載自:讀芯術

「Attention,Attention,還是Attention,看了三篇高峰會論文,現在CVPR、ICCV都這麼好發了么,隨隨便便加個Attention就算了不得的創新點?」這是曾經有段時間實驗室大家讀paper後很統一的的槽點。

你可能還在通過不斷增加卷積層、池化層、全連接層以盡量讓自己的網路結構「看起來」和別人的不太一樣,也可能還在琢磨怎麼從影像分割領域「借」點東西過來應用於影像識別領域。

對於很多科研小白來說,好不容易啃完了50+篇paper,腦子裡靈光一閃頓悟了一個寫下來手都直打哆嗦的創新點。然後發現了一個比想不到創新點更殘酷的事實——一篇小論文里只有一個創新點還遠遠不夠。

其他創新點那就只能盡量靠「湊」。

神經網路本身就有點玄學的味道,你可不知道加進去哪味佐料就能煉出來一顆神丹妙藥。而這味「Attention」原料經很多神經網路的專業煉丹師妙手驗證,它確實百搭又好用。

所以當你還在為小論文的創新點抓耳撓腮一籌莫展時,不妨試試神經網路結構里的百搭小助手—Attention注意力機制。

當「易上手」Keras遇上「百搭」Attention

隨著TensorFlow 2.0發布,Keras實現的深層網路開始備受開發者關注。在TensorFlow 2.0中,Keras可以利用以下三個強大的高層神經網路API實現深度網路。

· sequence API——這是最簡單的API,首先調動 model = Sequential()並不斷添加層,例如 model.add(Dense(…)) .

· 函數式API——高級API,創建自定義模式,隨機輸入/輸出。此處定義模組要小心謹慎,隨便一點微小改動都會影響用戶端。定義模型可以使用model = Model(inputs=[…],outputs=[…]) .

· 子類化API——高級API,可以將該模型定義為Python類。這裡,在屬類中定義模型的前向傳遞,Keras自動計算後向傳遞。

圖片來源:Keras官方文檔 主頁

Keras作為一個專為支援快速實驗而生的高層神經網咯API,與Tensorflow、Pytorch、Caffe這類深度學習框架相比,它更像是個神經網路介面。儘管它提供的底層彈性和靈活性要遜色於其他幾種深度學習框架,然而它的模組高度封裝,對用戶非常友好,最易上手,用它把想法迅速輸出為結果通常來說是不二之選。

所以,當你需要快速創建一個神經網路,並測試你的網路模組添加或刪減得是否那麼「得當」,不妨嘗試使用下Keras這個非常好上手的API。

而上面說的Attention注意力機制,其實類似神經網路是參考人類大腦神經元的工作原理髮展而來,Attention注意力模型也是巧妙借鑒了人類在發展過程中對於必要資訊的著重關注同時自動忽略非必要資訊的視覺注意力提取機制原理。

接下來,本篇將先從介紹「『序列-序列』模型」入手,然後通過介紹「Attention注意力機制的實質」來表明為什麼Attention機制對於序列-序列的模型來說非常重要,最後通過實例用Keras快速實現Attention Layer。

「序列-序列」模型

「序列-序列」模型(Sequence to Sequence Model)是深度學習模型的強大分支,旨在解決機器學習領域中最棘手的問題。例如:

· 機器翻譯

· 聊天機器人

· 文本摘要

每個問題都分別面臨著各自特定的挑戰。例如,機器翻譯必須處理不同的詞序拓撲(即主謂賓語序)。因此,此「序列-序列」模型是解決複雜的神經語言程式學相關問題的必要武器。

「序列-序列」模型是如何應用於英&法機器翻譯任務的呢?

「序列-序列」模型有兩個組件,一個編碼器和一個解碼器。編碼器將源語句轉化為簡潔的矢量(稱為上下文矢量),其中解碼器鍵入上下文矢量中,並利用解碼錶示執行電腦翻譯。

序列到序列模型

這種方法存在什麼問題嗎?

這種方法存在嚴重瓶頸。上下文矢量需要將給定源語句中的所有資訊編碼為包含幾百個元素的向量。現在,為了融入相關語境,該矢量需要保留以下資訊:

· 關於主語、賓語和謂語動詞的資訊

· 這些字元之間的交互

這個過程任務相當艱巨,特別是對於長句子而言。因此,需要更好的解決方案,這也是Attention機制被用於解決該瓶頸的初衷所在。

Attention注意力機制的實質

如果解碼器可以訪問過去的所有狀態,而不只是上下文矢量,那會怎麼樣?這正是注意力機制所做的事情。每個解碼步驟中,解碼器都可以任意查看編碼器的特定狀態。在這裡,我們將討論巴赫達瑙注意機制(Bahdanau Attention)。下圖描述了注意力機制的內部工作原理。

注意機製作用下的序列到序列模型

從圖中不難看出,上下文矢量成為了所有編碼器過去狀態的加權和。事實上Attention機制從數學公式和程式碼實現上來看就是加權求和,而研究加權求和中權重的合理性配置正是Attention想要解決的問題。

引入Keras注意力機制

目前的一些注意力機制運作起來會相當麻煩。而Keras注意力機制則採用了更模組化的方法,它在更細的層級上實現注意力機制(即給定解碼器RNN/LSTM/GRU的每個解碼器步驟)。

使用Attention注意力層

可以將Attention Layer用作任何層,例如,定義一個注意力層:

attn_layer = AttentionLayer(name='attention_layer')([encoder_out,decoder_out])

這裡提供了一個簡單神經機器翻譯(NMT)的示例,演示如何在NMT(nmt.py)中利使用注意層,下面給大家介紹些細節。

利用注意力機制實現NMT

在這裡,簡要介紹一下利用注意力機制實現NMT的步驟。

首先定義編碼器和解碼器輸入((源/目標字元)。它們都具有一定規格(批量大小、時間步驟、辭彙表大小)。

encoder_inputs = Input(batch_shape=(batch_size,en_timesteps, en_vsize), name='encoder_inputs') decoder_inputs = Input(batch_shape=(batch_size, fr_timesteps – 1, fr_vsize),name='decoder_inputs')

定義編碼器(注意return_sequences=True )。

encoder_gru =GRU(hidden_size, return_sequences=True, return_state=True, name='encoder_gru') encoder_out, encoder_state = encoder_gru(encoder_inputs)

定義解碼器(注意return_sequences=True)。

decoder_gru =GRU(hidden_size, return_sequences=True, return_state=True, name='decoder_gru')

decoder_out, decoder_state = decoder_gru(decoder_inputs,initial_state=encoder_state)

定義注意力層。輸入進注意力層的是encoder_out (編碼器輸出序列)和 decoder_out (解碼器輸出序列)。

attn_layer =AttentionLayer(name='attention_layer') attn_out, attn_states = attn_layer([encoder_out, decoder_out])

連接 attn_out和 decoder_out並將其作為Softmax層的輸入。

decoder_concat_input =Concatenate(axis=-1, name='concat_layer')([decoder_out, attn_out])

定義 TimeDistributed Softmax層,並輸入 decoder_concat_input。

dense =Dense(fr_vsize, activation='softmax', name='softmax_layer') dense_time = TimeDistributed(dense, name='time_distributed_layer') decoder_pred = dense_time(decoder_concat_input)

定義全模型。

full_model =Model(inputs=[encoder_inputs, decoder_inputs], outputs=decoder_pred) full_model.compile(optimizer='adam', loss='categorical_crossentropy')

支援注意力機制可視化

事實上,這不僅實現了注意力機制,還提供了將注意力機制可視化的方法。因為對於每個解碼步驟這一層都返回兩個值:

· 注意力上下文矢量(用作解碼器Softmax層的額外輸入)

· 注意力權重(注意力機制的Softmax輸出)

因此,通過可視化注意力權重,就能充分了解注意力在訓練/推理過程中所做的事情。下面詳細談論討論這個過程。

由NMT獲得注意力權重推斷

NMT推斷需要完成以下步驟:

· 獲取編碼器輸出

· 定義一個解碼器,執行解碼器的單個步驟(因為我們需要提供該步驟的預測為下一步的輸入做準備)

· 使用編碼器輸出作為解碼器的初始狀態

· 執行解碼,直到得到一個無效的單詞/輸出<EOS>/固定部署

讓我們來看看如何利用該模型獲得注意力權重。

for i in range(20): dec_out, attention, dec_state =decoder_model.predict([enc_outs, dec_state, test_fr_onehot_seq]) dec_ind = np.argmax(dec_out,axis=-1)[0, 0] … attention_weights.append((dec_ind,attention))

然後,需要將這個注意權重列表傳遞給 plot_attention_weights(nmt.py)以便獲得帶有其他參數的注意力熱度圖。繪圖後的輸出可能如下所示。

本文使用Keras實現了Attention Layer。對於順序模型或者其他一些模型來說,注意力機制都非常重要,因為它確實十分百搭。

現有的實現注意力機制的方法要麼過於老舊,要麼還沒有實現模組化。而恰好Keras可以為注意力機制的實現提供了一個不錯的解決辦法。

看完本文,你不妨趕緊去試試用Keras實現Attention機制是否真如我說的那麼簡單,說不定你遭遇的paper創新點瓶頸馬上就能迎刃而解(Good Luck)。