深度解析注意力模型(attention model) --- image_caption的應用

@author : jasperyang
@school : BUPTgit

前言

這裏學習的注意力模型是我在研究image caption過程當中的出來的經驗總結,其實這個注意力模型理解起來並不難,可是國內的博文寫的都很不詳細或說很不明確,我在看了 attention-mechanism後才徹底明白。得以進行後續工做。github

這裏的注意力模型是論文 Show,Attend and Tell:Neural Image Caption Generation with Visual Attention裏設計的,可是注意力模型在大致上來說都是相通的。函數

先給你們介紹一下我須要注意力模型的背景。學習

圖片描述

I是圖片信息矩陣也就是[224,224,3],經過前面的cnn也就是所謂的sequence-sequence模型中的encoder,我用的是vgg19,獲得a,這裏的a實際上是[14*14,512]=[196,512],很形象吧,表明的是圖片被分紅了這麼多個區域,後面就看咱們單詞注意在哪一個區域了,你們能夠先這麼泛泛理解。經過了本文要講的Attention以後獲得z。這個z是一個區域機率,也就是當前的單詞在哪一個圖像區域的機率最大。而後z組合單詞的embedding去訓練。spa

好了,先這麼大概理解一下這張圖就好。下面咱們來詳細解剖attention,附有代碼~設計

attention的內部結構是什麼?

圖片描述

這裏的c其實一個隱含輸入,計算方式以下code

首先咱們這麼個函數:blog

def _get_initial_lstm(self, features):
    with tf.variable_scope('initial_lstm'):
        features_mean = tf.reduce_mean(features, 1)

        w_h = tf.get_variable('w_h', [self.D, self.H], initializer=self.weight_initializer)
        b_h = tf.get_variable('b_h', [self.H], initializer=self.const_initializer)
        h = tf.nn.tanh(tf.matmul(features_mean, w_h) + b_h)

        w_c = tf.get_variable('w_c', [self.D, self.H], initializer=self.weight_initializer)
        b_c = tf.get_variable('b_c', [self.H], initializer=self.const_initializer)
        c = tf.nn.tanh(tf.matmul(features_mean, w_c) + b_c)
        return c, h

上面的c你能夠暫時不用管,是lstm中的memory state,輸入feature就是經過cnn跑出來的a,咱們暫時考慮batch=1,就認爲這個a是一張圖片生成的。因此a的維度是[1,196,512]圖片

y向量表明的就是feature。ip

下面咱們打開這個黑盒子來看看裏面究竟是在作什麼處理。

圖片描述

上圖中能夠看到

圖片描述

這裏的tanh不能替換成ReLU函數,一旦替換成ReLU函數,由於有不少負值就會消失,會很影響後面的結果,會形成最後Inference句子時,無論你輸入什麼圖片矩陣的到的句子都是同樣的。不能隨便用激活函數!!!ReLU是能解決梯度消散問題,可是在這裏咱們須要負值信息,因此只能用tanh

c和y在輸入到tanh以前要作個全鏈接,代碼以下。

w = tf.get_variable('w', [self.H, self.D], initializer=self.weight_initializer)
        b = tf.get_variable('b', [self.D], initializer=self.const_initializer)
        w_att = tf.get_variable('w_att', [self.D, 1], initializer=self.weight_initializer)

        h_att = tf.nn.relu(features_proj + tf.expand_dims(tf.matmul(h, w), 1) + b)    # (N, L, D)

這裏的features_proj是feature已經作了全鏈接後的矩陣。而且在上面計算h_att中你能夠看到一個矩陣的傳播機制,也就是relu函數裏的加法。features_proj和後面的那個維度是不同的。

def _project_features(self, features):
    with tf.variable_scope('project_features'):
        w = tf.get_variable('w', [self.D, self.D], initializer=self.weight_initializer)
        features_flat = tf.reshape(features, [-1, self.D])
        features_proj = tf.matmul(features_flat, w)  
        features_proj = tf.reshape(features_proj, [-1, self.L, self.D])
        return features_proj

而後要作softmax了,這裏有個點,由於上面獲得的m的維度是[1,196,512],1是表明batch數量。通過softmax後想要獲得的是維度爲[1,196]的矩陣也就是每一個區域的注意力權值。因此

out_att = tf.reshape(tf.matmul(tf.reshape(h_att, [-1, self.D]), w_att), [-1, self.L])   # (N, L)
alpha = tf.nn.softmax(out_att)

圖片描述

最後計算s就是一個相乘。

context = tf.reduce_sum(features * tf.expand_dims(alpha, 2), 1, name='context')   #(N, D)

這裏也是有個傳播的機制,features維度[1,196,512],後面那個維度[1,196,1]。

最後給個完整的注意力模型代碼。

def _attention_layer(self, features, features_proj, h, reuse=False):
        with tf.variable_scope('attention_layer', reuse=reuse):
            w = tf.get_variable('w', [self.H, self.D], initializer=self.weight_initializer)
            b = tf.get_variable('b', [self.D], initializer=self.const_initializer)
            w_att = tf.get_variable('w_att', [self.D, 1], initializer=self.weight_initializer)

            h_att = tf.nn.relu(features_proj + tf.expand_dims(tf.matmul(h, w), 1) + b)    # (N, L, D)
            out_att = tf.reshape(tf.matmul(tf.reshape(h_att, [-1, self.D]), w_att), [-1, self.L])   # (N, L)
            alpha = tf.nn.softmax(out_att)  
            context = tf.reduce_sum(features * tf.expand_dims(alpha, 2), 1, name='context')   #(N, D)
            return context, alpha

若是你們想研究整個完整的show-attend-tell模型,能夠去看看github連接

以上咱們講的是soft_attention,還有一個hard_attention。hard_attention比較不適合於反向傳播,其原理是取代了咱們以前將softmax後的全部結果相加,使用採樣其中一個做爲z。反向傳播的梯度就很差算了,這裏用蒙特卡洛採樣方式。

clipboard.png

ok,回到咱們的image_caption中,看下圖

圖片描述

這個圖其實不太準確,每個z其實還會用tf.concat鏈接上當前這個lstm_cell的單詞embedding輸入。也就是維度變成[512]+[512]=[1024]

這樣就能夠結合當前單詞和圖像區域的關係了,我以爲注意力模型仍是很巧妙的。

相關文章
相關標籤/搜索