這幾天看了Stacked Attention Networks for Image Question Answering這篇論文,對文中所提出的模型有了大概了解。本文提到了“SAN”網絡,他是在attention基礎上發展而來的。這裡我先介紹一下注意力機制的使用,再針對這篇論文的stacked attention進行分析,由易到難,效果會更好。
注意力機制
注意力模型最近幾年在深度學習各個領域被廣泛使用,無論是圖像處理、語音識别還是自然語言處理的各種不同類型的任務中,都很容易遇到注意力模型的身影。Attention,顧名思義,是由人類觀察環境的習慣規律總結而來的,人類在觀察環境時,大腦往往隻關注某幾個特别重要的局部,擷取需要的資訊,建構出關于環境的某種描述,而Attention Mechanism正是如此,去學習不同局部的重要性,再結合起來。
Encoder-Decoder架構
Encoder-Decoder架構可以看作是一種深度學習領域的研究模式,應用場景異常廣泛。目前大多數注意力模型附着在Encoder-Decoder架構下。當然,注意力模型可以看作一種通用的思想,本身并不依賴于特定架構,這點需要注意。圖1是文本處理領域裡常用的Encoder-Decoder架構最抽象的一種表示。
圖1 抽象的文本處理領域的Encoder-Decoder架構
我們可以把輸入和輸出看作<Source,Target>,我們的目标是給定輸入句子Source,期待通過Encoder-Decoder架構來生成目标句子Target。Source和Target可以是同一種語言,也可以是兩種不同的語言。而Source和Target分别由各自的單詞序列構成:
文本處理領域的Encoder-Decoder架構可以這麼直覺地去了解:Encoder對輸入句子Source進行編碼,将輸入句子通過非線性變換轉化為中間語義表示C,對于解碼器Decoder來說,其任務是根據句子Source的中間語義表示C和之前已經生成的曆史資訊
來生成i時刻要生成的單詞。
每個yi都依次這麼産生,那麼看起來就是整個系統根據輸入句子Source生成了目标句子Target。如果Source是中文句子,Target是英文句子,那麼這就是解決機器翻譯問題的Encoder-Decoder架構;如果Source是一篇文章,Target是概括性的幾句描述語句,那麼這是文本摘要的Encoder-Decoder架構;如果Source是一句問句,Target是一句回答,那麼這是問答系統或者對話機器人的Encoder-Decoder架構。
Encoder-Decoder架構不僅僅在文本領域廣泛使用,在語音識别、圖像處理等領域也經常使用。比如對于語音識别來說,圖1所示的架構完全适用,差別無非是Encoder部分的輸入是語音流,輸出是對應的文本資訊;而對于“圖像描述”任務來說,Encoder部分的輸入是一副圖檔,Decoder的輸出是能夠描述圖檔語義内容的一句描述語。一般而言,文本處理和語音識别的Encoder部分通常采用RNN模型,圖像處理的Encoder一般采用CNN模型。
添加注意力的Encoder-Decoder架構
圖1中展示的Encoder-Decoder架構是沒有展現出“注意力模型”的,為什麼說它注意力不集中呢?請觀察下目标句子Target中每個單詞的生成過程如下:
其中f是Decoder的非線性變換函數。從這裡可以看出,在生成目标句子的單詞時,不論生成哪個單詞,它們使用的輸入句子Source的語義編碼C都是一樣的,沒有任何差別。
而語義編碼C是由句子Source的每個單詞經過Encoder 編碼産生的,這意味着不論是生成哪個單詞,y1,y2還是y3,其實句子Source中任意單詞對生成某個目标單詞yi來說影響力都是相同的,這就是為何說這個模型沒有展現出注意力的原因。這類似于人類看到眼前的畫面,但是眼中卻沒有注意焦點一樣。這裡舉個例子,英譯漢任務:
"Tom chase Jerry."
顯然答案是:
“湯姆追逐傑瑞”
我們要解決的是這樣一個問題:(Tom, chase, jerry)→ (湯姆,追逐, 傑瑞),按照Encoder-Decoder的原始做法,我們為三個中文單詞分别計算C:
比如在翻譯“傑瑞”這個中文單詞的時候,該模型裡面的每個英文單詞對于翻譯目标單詞“傑瑞”貢獻是相同的,很明顯這裡不太合理,顯然“Jerry”對于翻譯成“傑瑞”更重要,但是該模型是無法展現這一點的,這就是為何說它沒有引入注意力的原因。
沒有引入注意力的模型在輸入句子比較短的時候問題不大,但是如果輸入句子比較長,此時所有語義完全通過一個中間語義向量來表示,單詞自身的資訊已經消失,可想而知會丢失很多細節資訊,這也是為何要引入注意力模型的重要原因。
上面的例子中,如果引入Attention模型的話,應該在翻譯“傑瑞”的時候,展現出英文單詞對于翻譯目前中文單詞不同的影響程度,比如給出類似下面一個機率分布值:
(Tom,0.3)(Chase,0.2) (Jerry,0.5)
每個英文單詞的機率代表了翻譯目前單詞“傑瑞”時,注意力配置設定模型配置設定給不同英文單詞的注意力大小。這對于正确翻譯目智語單詞肯定是有幫助的,因為引入了新的資訊。
同理,目标句子中的每個單詞都應該學會其對應的源語句子中單詞的注意力配置設定機率資訊。這意味着在生成每個單詞yi的時候,原先都是相同的中間語義表示C會被替換成根據目前生成單詞而不斷變化的Ci。了解Attention模型的關鍵就是這裡,即由固定的中間語義表示C換成了根據目前輸出單詞來調整成加入注意力模型的變化的Ci。增加了注意力模型的Encoder-Decoder架構了解起來如圖2所示。
圖3 引入注意力模型的Encoder-Decoder架構
即生成目标句子單詞的過程變成了下面的形式:
而每個Ci可能對應着不同的源語句子單詞的注意力配置設定機率分布,比如對于上面的英漢翻譯來說,其對應的資訊可能如下:
即中間語義表達C有如下公式:
其中,Lx代表輸入句子Source的長度,aij代表在Target輸出第i個單詞時Source輸入句子中第j個單詞的注意力配置設定系數,而hj則是Source輸入句子中第j個單詞的語義編碼。假設下标i就是上面例子所說的“ 湯姆” ,那麼Lx就是3,h1=f(“Tom”),h2=f(“Chase”),h3=f(“Jerry”)分别是輸入句子每個單詞的語義編碼,對應的注意力模型權值則分别是0.6,0.2,0.2,經過權重求和得到語義表達C。
但是這裡還有一個問題:生成目标句子某個單詞,比如“湯姆”的時候,如何知道Attention模型所需要的輸入句子單詞注意力配置設定機率分布值呢?就是說“湯姆”對應的輸入句子Source中各個單詞的機率分布:(Tom,0.6)(Chase,0.2) (Jerry,0.2) 是如何得到的呢?
為了便于說明,我們假設對圖2的非Attention模型的Encoder-Decoder架構進行細化,Encoder采用RNN模型,Decoder也采用RNN模型,這是比較常見的一種模型配置,則圖2的架構轉換為圖4。
假設目前Decoder要輸出的是Yt,已知Decoder上一時刻的隐層輸出St-1,用它與Encoder的各時刻隐層輸出hj做某種fatt操作,計算出來的結果用softmax轉化為機率,就是我們所需的權重a,對輸入權重求和,計算出輸入序清單達C,作為Decoder目前的部分輸入,進而生成Yt。這就是Attention的工作機制。
可以說attention的核心就是C的計算,即通過函數F(hj,Hi-1)來獲得目标單詞yi和每個輸入單詞對應的對齊可能性。
,即使跳出Encoder-Decoder這個架構,Attention也可以單獨存在,因為他的本質就是“權重求和”。
還可以從另一個角度看Attention,那就是鍵值查詢。鍵值查詢應該有三個基本元素:索引(Query),鍵(Key)和值(Value),可以了解為這是一個查字典的過程,Key-Value對構成一個字典,使用者給一個Query,系統找到與之相同的Key,傳回對應的Value。那麼問題來了,字典裡沒有與Query相同的Key怎麼辦?答案是分别計算Query和每一個已有的Key的相似度w,作為權重配置設定到所有的Value上,并傳回它們的權重求和。Attention也可以了解為某種相似性度量。
是以本質上Attention機制是對Source中元素的Value值進行權重求和,而Query和Key用來計算對應Value的權重系數。即可以将其本質思想改寫為如下公式:
Attention也可以了解為某種相似性度量。 其中,Lx=||Source||代表Source的長度,公式含義即如上所述。上文所舉的機器翻譯的例子裡,因為在計算Attention的過程中,Source中的Key和Value合二為一,指向的是同一個東西,也即輸入句子中每個單詞對應的語義編碼。
其中,計算Query和某個Key的相似性或者相關性,最常見的方法包括:求兩者的向量點積、求兩者的向量Cosine相似性或者通過再引入額外的神經網絡來求值,即如下方式:
講到這裡,我們已經知道了什麼是注意力機制,為什麼要使用注意力機制,接下來我們來說一下注意力機制在視覺問答中的應用。
Stacked-Attention-Networks
首先來看一下SAN的大緻結構:
可以看出SAN其實主要分為3個部分:LSTM/CNN(用來提取輸入的問題特征)、CNN(提取圖像特征)、Attention(注意力層)。其中CNN部分其實不是內建在SAN網絡中的,原文的實作方式其實是用已經預訓練好了的VGG16來提取圖檔feature,然後直接調用這些feature,而不會去更新VGG16網絡的權重。是以最終實際程式需要實作的部分其實就是LSTM/CNN部分和Attention部分。
圖像模型
首先image應當在輸入VGG16網絡前被rescale成448x448大小,然後,為了保證原始圖像的空間資訊,輸入圖像後應當直接從最後一層pooling層拿到feature。最終我們得到的feature的形狀應當是512×14×14,即把原始圖像劃分為196個區域,每個區域是512維的feature vector,每個區域對應原圖檔32×32大小的區域,如下圖所示:
因為在後文attention部分中将會将這問題向量和圖像向量加在一起,這裡我們對feature進行處理:
通過一個以tanh為激活函數的全連接配接層,最後得到的vector應當是與後面得到的問題的feature長度一緻。
問題模型
這裡使用了兩種方法來提取問題特征,先讨論使用lstm來提取問題特征。
LSTM模型
作者這裡使用了Sequence to Sequence中的多對一形式,問題中每個單詞按照時間順序依次輸入到lstm中,在最後時刻輸出該問題的表達向量,如下圖所示:
在每一步中,lstm單元接受一個輸入的單詞xt,并且更新記憶單元ct,然後輸出隐藏層狀态ht,更新過程使用了門機制,分别有輸入門,遺忘門,輸出門和記憶單元,簡單來說就是選擇性遺忘,選擇性輸入,選擇性輸出。詳細的更新過程如下所示:
question q = [q1, ...qT ] ,qt 是t時刻輸入單詞的one hot vector表示,但是one-hot vector表示存在兩個問題,(1)生成的向量次元往往很大,容易造成維數災難;(2)難以刻畫詞與詞之間的關系(如語義相似性,也就是無法很好地表達語義),是以通過一個嵌入矩陣将單詞嵌入到向量空間。然後将詞向量輸入到lstm中。最後我們取最後一個隐藏層輸出的ht 作為問題的feature。
這裡的意思就是将每一個詞(用qt 表示)轉換成對應的embedding向量,實作方法是使用嵌入矩陣乘以單詞的one hot向量得到該詞的詞向量。
CNN模型
與lstm方法類似,首先也需要将要輸入的單詞轉換成詞向量,将每個單詞的詞向量組合成一個矩陣,進行卷積操作。文中使用了三個卷積核。具體流程如下圖所示:
卷積視窗的大小設定對最終的分類結果影響較大,借鑒N-gram語言模型的思想,通過提取相鄰n個詞進行局部特征的提取,進而捕捉上下文搭配詞語的語義資訊,對整個文本的語義進行表示。根據這種思想,将卷積視窗大小設定為n*m,n為視窗内詞的個數,m為詞向量次元。詳細流程如下圖所示:
将經過最大池化得到的向量連接配接起來得到的向量,即為問題向量。
Attention部分
其實就是将圖檔和問題的feature線性變換下,然後再矩陣與向量求和(要用到架構内置的broadcasting機制),以此将文字資訊和圖檔資訊融合。最後通過對線性變換之後的圖像-文本資訊進行softmax來計算出圖檔與文字的相關性(或者說與問題相關的資訊在圖像的分布)。
然後将pi和圖像每個區域的feature相乘,就可以隻保留與問題相關的資訊。然後将資訊疊加在一起(權重求和),最後和問題的feature相加,形成一個更加精化的查詢向量,再經過一個softmax函數得到預測結果。
但是對于一些複雜的問題,一個注意力層是不夠的,這時我們需要使用多個注意層疊代上述過程,每一次疊代都可以形成一個更加精确的視覺注意資訊。
k代表第k個注意力層。u0被初始化為vQ
循環k次 ,使用最後一層輸出的u來推斷答案。
結束語
我認為對于Attention可以有三種了解。
- 首先,從數學公式上和代碼實作上Attention可以了解為權重求和。
- 其次,從形式上Attention可以了解為鍵值查詢。
- 最後,從實體意義上Attention可以了解為相似性度量