1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        解析Transformer模型

        共 7023字,需瀏覽 15分鐘

         ·

        2020-10-07 23:23

        ?

        GiantPandaCV導語:這篇文章為大家介紹了一下Transformer模型,Transformer模型原本是NLP中的一個Idea,后來也被引入到計算機視覺中,例如前面介紹過的DETR就是將目標檢測算法和Transformer進行結合,另外基于Transformer的魔改工作最近也層出不窮,感興趣的同學可以了解一下。

        ?

        要讀DETR論文視頻解讀的同學可以點下方鏈接:

        CV和NLP的統(tǒng)一,DETR 目標檢測框架論文解讀

        前言

        Google于2017年提出了《Attention is all you need》,拋棄了傳統(tǒng)的RNN結構,「設計了一種Attention機制,通過堆疊Encoder-Decoder結構」,得到了一個Transformer模型,在機器翻譯任務中「取得了BLEU值的新高」。在后續(xù)很多模型也基于Transformer進行改進,也得到了很多表現(xiàn)不錯的NLP模型,前段時間,相關工作也引申到了CV中的目標檢測,可參考FAIR的DETR模型

        引入問題

        常見的時間序列任務采用的模型通常都是RNN系列,然而RNN系列模型的順序計算方式帶來了兩個問題

        1. 某個時間狀態(tài),依賴于上一時間步狀態(tài),導致模型「不能通過并行計算來加速」
        2. RNN系列的魔改模型比如GRU, LSTM,雖然「引入了門機制」(gate),但是對「長時間依賴的問題緩解能力有限」,不能徹底解決

        因此我們設計了一個全新的結構Transformer,通過Attention注意力機制,來對時間序列更好的建模。同時我們不需要像RNN那樣順序計算,從而能讓模型更能充分發(fā)揮并行計算性能。

        模型架構

        TransFormer模型架構一覽

        上圖展示的就是Transformer的結構,左邊是編碼器Encoder,右邊是解碼器Decoder。通過多次堆疊,形成了Transformer。下面我們分別看下Encoder和Decoder的具體結構

        Encoder

        編碼器架構

        Encoder結構如上,它由以下sublayer構成

        • Multi-Head Attention 多頭注意力
        • Feed Forward 層

        Self Attention

        Multi-Head Attention多頭注意力層是由多個self attention來組成的,因此我們先講解下模型的自注意力機制。

        在一句話中,如果給每個詞都分配相同的權重,那么會很難讓模型去學習詞與詞對應的關系。舉個例子

        The?animal?didn't?cross?the?street?because?it?was?too?tired

        我們需要讓模型去推斷 it 所指代的東西,當我們給模型加了注意力機制,它的表現(xiàn)如下

        注意力機制效果

        我們通過注意力機制,讓模型能看到輸入的各個單詞,然后它會更加關注于 The animal,從而更好的進行編碼。

        論文里將attention模塊記為「Scaled Dot-Product Attention」,計算如下

        自注意力機制一覽
        • Q 代表 Query 矩陣
        • K 代表 Key 矩陣
        • V 代表 Value 矩陣
        • dk 是一個縮放因子

        其中 Q, K, V(向量長度為64)是由輸入X經(jīng)過三個不同的權重矩陣(shape=512x64)計算得來,

        經(jīng)過Embedding的向量X,與右邊三個權重矩陣相乘,分別得到Query,Key,Value三個向量

        下面我們看一個具體例子

        注意力機制運算過程

        Thinking這個單詞為例,我們需要計算整個句子所有詞與它的score。

        • X1是Thinking對應的Embedding向量。
        • 然后我們計算得到了X1對應的查詢向量q1
        • 然后我們與Key向量進行相乘,來計算相關性,這里記作Score。「這個過程可以看作是當前詞的搜索q1,與其他詞的key去匹配」。當相關性越高,說明我們需要放更多注意力在上面。
        • 然后除以縮放因子,做一個Softmax運算
        • Softmax后的結果與Value向量相乘,得到最終結果

        MultiHead-Attention

        理解了自注意力機制后,我們可以很好的理解多頭注意力機制。簡單來說,多頭注意力其實就是合并了多個自注意力機制的結果

        多頭注意力機制概覽,將多個自注意力機制并在一起

        我們以原文的8個注意力頭為例子,多頭注意力的操作如下

        • 將輸入數(shù)據(jù)X分別輸入進8個自注意力模塊

        • 分別計算出每個自注意力模塊的結果Z0, Z1, Z2.....Z7

        • 將各個自注意力模塊結果Zi拼成一個大矩陣Z

        • 經(jīng)過一層全連接層,得到最終的輸出 最后多頭注意力的表現(xiàn)類似如下

          多頭注意力機制效果

        Feed Forward Neural Network

        這個FFN模塊比較簡單,本質(zhì)上全是兩層全連接層加一個Relu激活

        Positional Encoding

        摒棄了CNN和RNN結構,我們無法很好的利用序列的順序信息,因此我們采用了額外的一個位置編碼來進行緩解

        然后與輸入相加,通過引入位置編碼,給詞向量中賦予了單詞的位置信息

        位置編碼

        下圖是總Encoder的架構

        Encoder的整體結構

        Decoder

        Decoder的結構與Encoder的結構很相似

        Decoder結構

        「只不過額外引入了當前翻譯和編碼特征向量的注意力」,這里就不展開了。

        代碼

        這里參考的是TensorFlow的官方實現(xiàn)notebook transformer.ipynb

        位置編碼

        def?get_angles(pos,?i,?d_model):
        ??angle_rates?=?1?/?np.power(10000,?(2?*?(i//2))?/?np.float32(d_model))
        ??return?pos?*?angle_rates

        def?positional_encoding(position,?d_model):
        ??angle_rads?=?get_angles(np.arange(position)[:,?np.newaxis],
        ??????????????????????????np.arange(d_model)[np.newaxis,?:],
        ??????????????????????????d_model)
        ??
        ??#?apply?sin?to?even?indices?in?the?array;?2i
        ??angle_rads[:,?0::2]?=?np.sin(angle_rads[:,?0::2])
        ??
        ??#?apply?cos?to?odd?indices?in?the?array;?2i+1
        ??angle_rads[:,?1::2]?=?np.cos(angle_rads[:,?1::2])
        ????
        ??pos_encoding?=?angle_rads[np.newaxis,?...]
        ????
        ??return?tf.cast(pos_encoding,?dtype=tf.float32)

        這里就是根據(jù)公式,生成位置編碼

        Scaled-Dot Attention

        def?scaled_dot_product_attention(q,?k,?v,?mask):
        ??"""Calculate?the?attention?weights.
        ??q,?k,?v?must?have?matching?leading?dimensions.
        ??k,?v?must?have?matching?penultimate?dimension,?i.e.:?seq_len_k?=?seq_len_v.
        ??The?mask?has?different?shapes?depending?on?its?type(padding?or?look?ahead)?
        ??but?it?must?be?broadcastable?for?addition.
        ??
        ??Args:
        ????q:?query?shape?==?(...,?seq_len_q,?depth)
        ????k:?key?shape?==?(...,?seq_len_k,?depth)
        ????v:?value?shape?==?(...,?seq_len_v,?depth_v)
        ????mask:?Float?tensor?with?shape?broadcastable?
        ??????????to?(...,?seq_len_q,?seq_len_k).?Defaults?to?None.
        ????
        ??Returns:
        ????output,?attention_weights
        ??"
        ""

        ??matmul_qk?=?tf.matmul(q,?k,?transpose_b=True)??#?(...,?seq_len_q,?seq_len_k)
        ??
        ??#?scale?matmul_qk
        ??dk?=?tf.cast(tf.shape(k)[-1],?tf.float32)
        ??scaled_attention_logits?=?matmul_qk?/?tf.math.sqrt(dk)

        ??#?add?the?mask?to?the?scaled?tensor.
        ??if?mask?is?not?None:
        ????scaled_attention_logits?+=?(mask?*?-1e9)??

        ??#?softmax?is?normalized?on?the?last?axis?(seq_len_k)?so?that?the?scores
        ??#?add?up?to?1.
        ??attention_weights?=?tf.nn.softmax(scaled_attention_logits,?axis=-1)??#?(...,?seq_len_q,?seq_len_k)

        ??output?=?tf.matmul(attention_weights,?v)??#?(...,?seq_len_q,?depth_v)

        ??return?output,?attention_weights

        輸入的是Q, K, V矩陣和一個mask掩碼向量 根據(jù)公式進行矩陣相乘,得到最終的輸出,以及注意力權重

        MultiheadAttention

        這里的代碼就是將多個注意力結果組合在一起

        class?MultiHeadAttention(tf.keras.layers.Layer):
        ??def?__init__(self,?d_model,?num_heads):
        ????super(MultiHeadAttention,?self).__init__()
        ????self.num_heads?=?num_heads
        ????self.d_model?=?d_model
        ????
        ????assert?d_model?%?self.num_heads?==?0
        ????
        ????self.depth?=?d_model?//?self.num_heads
        ????
        ????self.wq?=?tf.keras.layers.Dense(d_model)
        ????self.wk?=?tf.keras.layers.Dense(d_model)
        ????self.wv?=?tf.keras.layers.Dense(d_model)
        ????
        ????self.dense?=?tf.keras.layers.Dense(d_model)
        ????????
        ??def?split_heads(self,?x,?batch_size):
        ????"""Split?the?last?dimension?into?(num_heads,?depth).
        ????Transpose?the?result?such?that?the?shape?is?(batch_size,?num_heads,?seq_len,?depth)
        ????"
        ""
        ????x?=?tf.reshape(x,?(batch_size,?-1,?self.num_heads,?self.depth))
        ????return?tf.transpose(x,?perm=[0,?2,?1,?3])
        ????
        ??def?call(self,?v,?k,?q,?mask):
        ????batch_size?=?tf.shape(q)[0]
        ????
        ????q?=?self.wq(q)??#?(batch_size,?seq_len,?d_model)
        ????k?=?self.wk(k)??#?(batch_size,?seq_len,?d_model)
        ????v?=?self.wv(v)??#?(batch_size,?seq_len,?d_model)
        ????
        ????q?=?self.split_heads(q,?batch_size)??#?(batch_size,?num_heads,?seq_len_q,?depth)
        ????k?=?self.split_heads(k,?batch_size)??#?(batch_size,?num_heads,?seq_len_k,?depth)
        ????v?=?self.split_heads(v,?batch_size)??#?(batch_size,?num_heads,?seq_len_v,?depth)
        ????
        ????#?scaled_attention.shape?==?(batch_size,?num_heads,?seq_len_q,?depth)
        ????#?attention_weights.shape?==?(batch_size,?num_heads,?seq_len_q,?seq_len_k)
        ????scaled_attention,?attention_weights?=?scaled_dot_product_attention(
        ????????q,?k,?v,?mask)
        ????
        ????scaled_attention?=?tf.transpose(scaled_attention,?perm=[0,?2,?1,?3])??#?(batch_size,?seq_len_q,?num_heads,?depth)

        ????concat_attention?=?tf.reshape(scaled_attention,?
        ??????????????????????????????????(batch_size,?-1,?self.d_model))??#?(batch_size,?seq_len_q,?d_model)

        ????output?=?self.dense(concat_attention)??#?(batch_size,?seq_len_q,?d_model)
        ????????
        ????return?output,?attention_weights

        FFN

        def?point_wise_feed_forward_network(d_model,?dff):
        ??return?tf.keras.Sequential([
        ??????tf.keras.layers.Dense(dff,?activation='relu'),??#?(batch_size,?seq_len,?dff)
        ??????tf.keras.layers.Dense(d_model)??#?(batch_size,?seq_len,?d_model)
        ??])

        有了這三個模塊,就可以組合成Encoder和Decoder了,這里限于篇幅就不展開,有興趣的可以看下官方notebook

        總結

        Transformer這個模型設計還是很有特點的,雖然本質(zhì)上還是全連接層的各個組合,但是通過不同的權重矩陣,對序列進行注意力機制建模。并且根據(jù)模型無法利用序列順序信息的缺陷,設計了一套位置編碼機制,賦予詞向量位置信息。近年來對Transformer的魔改也有很多,相信這個模型還有很大的潛力去挖掘。

        相關資料參考

        • Tensorflow官方notebook transformer.ipynb: ('https://github.com/tensorflow/docs/blob/master/site/en/tutorials/text/transformer.ipynb')
        • illustrated-transformer: (http://jalammar.github.io/illustrated-transformer/) 該作者的圖示很明晰,相對容易理解

        歡迎關注GiantPandaCV, 在這里你將看到獨家的深度學習分享,堅持原創(chuàng),每天分享我們學習到的新鮮知識。( ? ?ω?? )?

        有對文章相關的問題,或者想要加入交流群,歡迎添加BBuf微信:

        二維碼

        為了方便讀者獲取資料以及我們公眾號的作者發(fā)布一些Github工程的更新,我們成立了一個QQ群,二維碼如下,感興趣可以加入。

        公眾號QQ交流群
        瀏覽 125
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            男女啪啪啪网站 | 麻豆网站视频 | 最新在线中文字幕 | xxxx农村野外hd | 国产精品美女久久久久av爽李椋 | 女教师少妇高潮免费 | 公交车被脱了内裤进入动漫 | 国产亚洲欧美在线 | 亚洲最大成人在线 | 狠狠色噜噜噜 |