Transfomer解析

代碼:https://www.github.com/kyubyong/transformer
重點解讀:https://jalammar.github.io/illustrated-transformer/

在這裏插入圖片描述
全連接層:重新擬合,減少特徵信息的損失

seq2seq

http://www.51ui.cn/66/829571/
編碼器,按照順序處理源句,得到一個描述(representation)向量。
然後解碼器利用這個描述,來翻譯出整個句子。
然而這導致了信息的大量丟失,特別是對一些長的句子,和有不同語序的語言對。

在這裏插入圖片描述
把 “like” 翻譯成 “好き(suki)”:得經歷很長的距離,這中間會混入噪音,還會丟失有用信息,所以很難翻譯準確。
即使之後,加了部分注意力機制來輔助翻譯,也會因爲對關係的捕捉不足,而出現翻譯失誤。

翻譯任務中,需要發現的關係有三種:源句內部的關係;目標句內部的關係;源句和目標句之間的關係。

seq2seq 只在捕捉源句和目標句之間關係用注意力機制進行了捕捉,而源句內部和目標句內部還是在用 RNN,從一邊到另一邊來捕捉關係,但這樣並不夠直接,特別是對一些距離遠的關係捕捉很差。

除了對遠距離關係難以學習的不足以外,RNN默認是按時序來進行處理的,所以得一個個詞從左到右看過去,再逐詞生成翻譯。這樣導致 RNN 不能像 CNN 一樣,充分利用 GPU 的並行運算優勢。

attention機制

先用 query 和所有的 keys 值相乘(也能用其他一些運算),於是每個 key 都能得到一個值,看做是每個 key 的權重,爲了使得權重加起來等於1,這裏需要用 softmax 壓一下得到注意力評分(attention score);最後用評分和相對應的 value 值相乘,決定哪個 value 比較重要,再相加,就得到想要的注意力向量了。
在這裏插入圖片描述

transformer block

https://mp.weixin.qq.com/s?__biz=MzU3NTY3MTQzMg==&mid=2247484373&idx=1&sn=7165d95ac89f2651a8b761cb5f29df20&chksm=fd1ede32ca69572470a8f0ce917ff6ca5546fc437fd42022123eccb073a8fe3472fcbe72bfd7&mpshare=1&scene=23&srcid=0212NjRB7t6jYTBDdwlF1o9a#rd
在這裏插入圖片描述將6個編碼器堆疊在一起,每一個解碼器連接至編碼器???

embedding:每個單詞都嵌入到512維的向量(最長的句子長度)中。

底部的編碼器接收的是詞嵌入,但其他編碼器接收的則是其下方的編碼器的輸出。

encoder

一旦定義了輸出詞彙,我們就可以使用相同寬度的向量來表示詞彙表中的每個單詞,這被稱爲one-hot編碼。

編碼器輸入首先經過self-attention層:對特定單詞編碼時,可以幫助編碼器查看輸入語句中的其他單詞,以確定具體的語境(Transformer用self-attention將其他相關單詞的“理解“融入到目前正在處理的單詞中)。

Self-attention層所輸出的內容(multi-head attention:Transformer使用8個attention heads,爲每個編碼器/解碼器設置了8組矩陣,每組都是隨機初始化的。在訓練之後,每組被用於將輸入的詞嵌入(或者低層編碼器/解碼器的向量)投入到不同的表示子空間。用不同的權重矩陣做8次不同的計算,最終就能得到8個不同的Z矩陣將8個矩陣合併,然後讓它們和一個額外的權重矩陣W0相乘)會被輸入到前饋神經網絡層。完全相同的前饋神經網絡會分別應用於每個編碼器中,最後輸出到下一個編碼器

每個位置的單詞在編碼器中沿着自己的路徑流動。在self-attention層中,這些路徑之間存在依賴關係。由於前饋層中不存在依賴關係,因此各種路徑在經過前饋層時可以並行執行

在這裏插入圖片描述

在這裏插入圖片描述假設我們要計算第一個單詞“Thinking”的self-attention得分。我們需要根據這個單詞爲輸入語句中的每個詞打分,這個分數決定了當我們在編碼某一位置的單詞時對輸入語句的其他部分投入多少關注度。Softmax的結果決定了每個單詞的在這一位置的權重,顯然,在這個位置上的單詞將獲得最高的softmax得分,但有時也需要注意與當前單詞相關的詞彙

decoder

在這裏插入圖片描述在解碼階段,每一步都輸出一個輸出序列的元素(翻譯後的單詞)。每一步的輸出都會在下一個步驟時被反饋到底層解碼器,並且解碼器也和編碼器一樣,將輸出結果向更高層傳遞。正如我們對編碼器輸入所操作的那樣,我們嵌入並添加位置編碼到那些解碼器輸入中去,以表明每個單詞的位置。

在解碼器中,self-attention僅被允許關注到輸出序列中較前的位置,在self-attention計算的softmax步驟前通過用掩碼mask遮罩序列後面的位置(將它們設置爲負無窮)

假設我們的模型通過訓練數據學習到10000個不同的英文單詞(即我們模型的“輸出詞彙”)。那麼logits向量就有10000個維度,每個維度對應每個單詞的分數。

然後,Softmax層將這些分數轉化爲概率(全都是正數,並且相加等於1)。選擇概率最大的維度,並且與之關聯的詞彙將在這一步中輸出。

loss function

假設我們的第一步是用一個簡單的例子進行訓練——將“merci”翻譯爲“thanks”。這意味着,我們希望輸出的是表示單詞”thanks“的概率分佈。但由於這個模型沒有經過充分的訓練,因此這目前還不可能發生。

由於模型的參數是隨機初始化的,未經訓練的模型對每個單詞的任意值產生概率分佈。我們可以將其與實際輸出進行比較(交叉熵、KL散度),然後使用反向傳播調整所有模型的權重,使輸出更接近所需的輸出。

實際上,我們會使用一個句子而非一個單詞。比如,輸入“je suis étudiant”,期望輸出“I am a student”。這意味着,我們想要我們的模型連續地輸出概率分佈,其中:每個概率分佈由一個維度等於詞彙表大小的向量來表示;第一個概率分佈中概率最大的是與”I”相關的維度;第二格概率分佈中概率最大的是與”am“相關的維度;一直重複輸出,直到輸出的概率分佈顯示的符號。

在這裏插入圖片描述
現在,因爲模型每次只能產生一個輸出:假設模型從概率分佈中選擇了最大概率的單詞,並捨棄掉其他單詞。這是一種方法(稱爲貪婪解碼)。另外一種方法是選擇概率第一第二大的單詞(比如,“I”和“a”),然後下一步運行模型兩次:第一次假設第一個輸出位置的單詞爲“I”,第二次假設第一個輸出位置的單詞是“me”,哪個版本的錯誤更少就保留那一版本的位置1和2。繼續重複操作來確定後續的位置。這一方法被稱爲“beam search”,在我們的例子中beam_size是2(因爲我們在計算了位置1和位置2的beams之後比較了結果),top_beam也是2(因爲我們保留了2個單詞)。你可以對這兩個超參數進行實驗。

文件集合

hyperparams.py
prepro.py
data_load.py
modules.py
train.py
eval.py

關鍵步驟(德語-》英語)

1. 定義超參數

1.1 源語言、目標語言的訓練數據和測試數據的路徑
1.2 batch大小(32)、初始learning rate(0.0001,In paper, learning rate is adjusted to the global step)、日誌目錄
1.3 最大詞長度(T=10)、min_cnt(words whose occurred less than min_cnt are encoded as )、hidden_units(C=512)、num_blocks、num_heads、num_epochs(20)、dropout(0.1)、sinusoid(If True, use sinusoid. If false, positional embedding.)

2. 預處理

目的:生成源語言和目標語言的詞彙文件。

2.1 生成德語文件、英語文件
2.1.1 用“”替換掉非空白字符或latin的
2.1.2 按空字符(空格、\n、\t)分割成word
2.1.3 計數,返回字典(key:詞; value:次數)
2.1.4 預處理文件保存:
①設置了四個特殊的標記符號PAD、UNK、S、/s,把他們設定爲出現次數很多放在文件的最前。
②依詞出現的頻率將訓練集中出現的詞和其對應的計數保存。

3. 加載德語\英語詞彙文件爲字典數組

3.1 讀取預處理prepro.py中生成的詞彙文件進數組,去掉出現次數少於hp.min_cnt=20的詞
3.2 枚舉數組元素及下標,返回兩個字典(word:id; id:word)

4. 構建圖graph類

4.1 定義Graph類:所有圖中定義的節點和操作都以這個爲默認圖
4.1.1 設置使用tf默認圖
4.1.2 訓練:get_batch_data()得到滿足最大長度的訓練數據以及batch的數量。
4.1.2.1 生成句子列表:讀取源、目標文件,\n分隔開每一行,選擇那些那些行開頭符號不是‘<’的句子(’<’:數據描述的行)、並用“”代替非空白或latin的。
4.1.2.2 雙語字典生成。
4.1.2.3 用字典中id表示句子列表,生成id表示的等長句子列表,並返回合法id句子(x_list\y_list\Sources\Targets)
①若該word不在字典中則id用1代替(即UNK的id), 加</s>表示句子末尾
②對句子長度<=最大長度hp.maxlen合法句子:連接到x_list\y_list\Sources\Targets.
③對小於最大長度id句子pad:前補零個數,後補maxlen-len(x)個(id=0)
4.1.2.4 句子的數量//batch_size=batch的數量。
4.1.2.5 將返回的等長id句子序列轉變爲tensor:tf.convert_to_tensor
4.1.2.6 從tensor列表中按順序或者隨機抽取出tensor放入隊列(作爲tf.train.shuffle_batch的參數):tf.train.slice_input_producer([X, Y])
4.1.2.7 通過隨機打亂tensor的順序創建batch,讀取一個文件並且加載一個張量中的batch_size行:tf.train.shuffle_batch()

4.1.3 推斷:將測試數據定義爲placeholder先放着。
4.1.4 定義decode部分的輸入:保持與輸入同維度,最前補全爲2的列。???
4.1.5 加載id對應的雙語字典。
4.1.6 設置作用域encoder
4.1.6.1 作用域enc_embed中將de2id embedding(embedding後是否scale)
4.1.6.1.1 embedding隱藏層512層。???
4.1.6.2 作用域enc_pe中,使用正弦曲線作positional_encoding;不使用正弦曲線則作embedding???
4.1.6.3 dropout:tf.layers.dropout()
4.1.6.4 每個block依次調用multihead_attention以及feedforward函數
4.1.7 作用域decoder
4.1.7.1 embedding\positional encoding\dropout
4.1.7.2 每個block依次調用2個multihead_attention以及feedforward函數
4.1.8 線性變換

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章