seq2seq与Attention机制
學(xué)習(xí)目標(biāo)
- 目標(biāo)
- 掌握seq2seq模型特點(diǎn)
- 掌握集束搜索方式
- 掌握BLEU評估方法
- 掌握Attention機(jī)制
- 應(yīng)用
- 應(yīng)用Keras實(shí)現(xiàn)seq2seq對日期格式的翻譯
4.3.1 seq2seq
seq2seq模型是在2014年,是由Google Brain團(tuán)隊(duì)和Yoshua Bengio 兩個團(tuán)隊(duì)各自獨(dú)立的提出來。
4.3.1.1 定義
seq2seq是一個Encoder–Decoder 結(jié)構(gòu)的網(wǎng)絡(luò),它的輸入是一個序列,輸出也是一個序列,?Encoder 中將一個可變長度的信號序列變?yōu)楣潭ㄩL度的向量表達(dá),Decoder 將這個固定長度的向量變成可變長度的目標(biāo)的信號序列。
?
注:Cell可以用 RNN ,GRU,LSTM 等結(jié)構(gòu)。
- 相當(dāng)于將RNN模型當(dāng)中的s^{0}s?0??輸入變成一個encoder
4.3.1.2 條件語言模型理解
- 1、編解碼器作用
- 編碼器的作用是把一個不定長的輸入序列x_{1},\ldots,x_{t}x?1??,…,x?t??,輸出到一個編碼狀態(tài)CC
- 解碼器輸出y^{t}y?t??的條件概率將基于之前的輸出序列y^{1}, y^{t-1}y?1??,y?t?1??和編碼狀態(tài)CC
argmax {P}(y_1, \ldots, y_{T'} \mid x_1, \ldots, x_T)argmaxP(y?1??,…,y?T?′????∣x?1??,…,x?T??),給定輸入的序列,使得輸出序列的概率值最大。
- 2、根據(jù)最大似然估計(jì),最大化輸出序列的概率
{P}(y_1, \ldots, y_{T'} \mid x_1, \ldots, x_T) = \prod_{t'=1}^{T'} {P}(y_{t'} \mid y_1, \ldots, y_{t'-1}, x_1, \ldots, x_T) = \prod_{t'=1}^{T'} {P}(y_{t'} \mid y_1, \ldots, y_{t'-1}, {C})P(y?1??,…,y?T?′????∣x?1??,…,x?T??)=∏?t?′??=1?T?′????P(y?t?′????∣y?1??,…,y?t?′???1??,x?1??,…,x?T??)=∏?t?′??=1?T?′????P(y?t?′????∣y?1??,…,y?t?′???1??,C)
由于這個公式需要求出:P(y^{1}|C) * P(y^{2}|y^{1},C)*P(y^{3}|y^{2},y^{2},y^{1},C)...P(y?1??∣C)?P(y?2??∣y?1??,C)?P(y?3??∣y?2??,y?2??,y?1??,C)...這個概率連乘會非常非常小不利于計(jì)算存儲,所以需要對公式取對數(shù)計(jì)算:
\log{P}(y_1, \ldots, y_{T'} \mid x_1, \ldots, x_T) = \sum_{t'=1}^{T'} \log{P}(y_{t'} \mid y_1, \ldots, y_{t'-1}, {C})logP(y?1??,…,y?T?′????∣x?1??,…,x?T??)=∑?t?′??=1?T?′????logP(y?t?′????∣y?1??,…,y?t?′???1??,C)
所以這樣就變成了P(y^{1}|C)+ P(y^{2}|y^{1},C)+P(y^{3}|y^{2},y^{2},y^{1},C)...P(y?1??∣C)+P(y?2??∣y?1??,C)+P(y?3??∣y?2??,y?2??,y?1??,C)...概率相加。這樣也可以看成輸出結(jié)果通過softmax就變成了概率最大,而損失最小的問題,輸出序列損失最小化。
4.3.1.3 應(yīng)用場景
- 神經(jīng)機(jī)器翻譯(NMT)
?
- 聊天機(jī)器人
接下來我們來看注意力機(jī)制,那么普通的seq2seq會面臨什么樣的問題?
4.3.2 注意力機(jī)制
4.3.2.1 長句子問題
?
對于更長的句子,seq2seq就顯得力不從心了,無法做到準(zhǔn)確的翻譯,一下是通常BLEU的分?jǐn)?shù)隨著句子的長度變化,可以看到句子非常長的時候,分?jǐn)?shù)就很低。
?
本質(zhì)原因:在Encoder-Decoder結(jié)構(gòu)中,Encoder把所有的輸入序列都編碼成一個統(tǒng)一的語義特征CC再解碼,因此,?CC中必須包含原始序列中的所有信息,它的長度就成了限制模型性能的瓶頸。當(dāng)要翻譯的句子較長時,一個CC可能存不下那么多信息,就會造成翻譯精度的下降。
4.3.2.2 定義
- 建立Encoder的隱層狀態(tài)輸出到Decoder對應(yīng)輸出y所需要的上下文信息
- 目的:增加編碼器信息輸入到解碼器中相同時刻的聯(lián)系,其它時刻信息減弱
?
4.3.2.3 公式
注意上述的幾個細(xì)節(jié),顏色的連接深淺不一樣,假設(shè)Encoder的時刻記為tt,而Decoder的時刻記為t^{'}t??′????。
-
1、{c}_{t'} = \sum_{t=1}^T \alpha_{t' t}{h}_tc?t?′????=∑?t=1?T??α?t?′??t??h?t??
- \alpha_{t^{'}t}α?t??′????t??為參數(shù),在網(wǎng)絡(luò)中訓(xùn)練得到
- 理解:藍(lán)色的解碼器中的cell舉例子
- \alpha_{4}{1}h_{1}+\alpha_{4}{2}h_{2} + \alpha_{4}{3}h_{3} + \alpha_{4}{4}h_{4} = c_{4}α?4??1h?1??+α?4??2h?2??+α?4??3h?3??+α?4??4h?4??=c?4??
-
2、\alpha_{t^{'}t}α?t??′????t??的N個權(quán)重系數(shù)由來?
- 權(quán)重系數(shù)通過softmax計(jì)算:\alpha_{t' t} = \frac{\exp(e_{t' t})}{ \sum_{k=1}^T \exp(e_{t' k}) },\quad t=1,\ldots,Tα?t?′??t??=?∑?k=1?T??exp(e?t?′??k??)??exp(e?t?′??t??)??,t=1,…,T
- e_{t' t} = g({s}_{t' - 1}, {h}_t)= {v}^\top \tanh({W}_s {s} + {W}_h {h})e?t?′??t??=g(s?t?′???1??,h?t??)=v????tanh(W?s??s+W?h??h)
- e_{t' t}e?t?′??t??是由t時刻的編碼器隱層狀態(tài)輸出和解碼器t^{'}-1t??′?????1時刻的隱層狀態(tài)輸出計(jì)算出來的
- ss為解碼器隱層狀態(tài)輸出,hh為編碼器隱層狀態(tài)輸出
- v,W_{s},W_{h}v,W?s??,W?h??都是網(wǎng)絡(luò)學(xué)習(xí)的參數(shù)
?
4.3.3 機(jī)器翻譯案例
4.3.3.1 問題
使用簡單的“日期轉(zhuǎn)換”任務(wù)代替翻譯任務(wù),為了不然訓(xùn)練時間變得太長。
網(wǎng)絡(luò)將輸入以各種可能格式(例如“1958年8月29日”,“03/30/1968”,“1987年6月24日”)編寫的日期,并將其翻譯成標(biāo)準(zhǔn)化的機(jī)器可讀日期(例如“1958 -08-29“,”1968-03-30“,”1987-06-24“)。使用seq2seq網(wǎng)絡(luò)學(xué)習(xí)以通用機(jī)器可讀格式Y(jié)YYY-MM-DD輸出日期。
4.3.3.2 相關(guān)環(huán)境與結(jié)果演示
pip install faker
pip install tqdm
pip install babel
pip install keras==2.2.4
- faker:生成數(shù)據(jù)包
- tqdm:python擴(kuò)展包
- babel:代碼裝換器
- keras:更加方便簡潔的深度學(xué)習(xí)庫
- 為了快速編寫代碼
4.3.3.4 代碼分析
-
Seq2seq():
- 序列模型類
- load_data(self,m):加載數(shù)據(jù)類,選擇加載多少條數(shù)據(jù)
- init_seq2seq(self):初始化模型,需要自定義自己的模型
- self.get_encoder(self):定義編碼器
- self.get_decoder(self):定義解碼器
- self.get_attention(self):定義注意力機(jī)制
- self.get_output_layer(self):定義解碼器輸出層
- model(self):定義模型整體輸入輸出邏輯
- train(self, X_onehot, Y_onehot):訓(xùn)練模型
- test(self):測試模型
-
訓(xùn)練
if __name__ == '__main__':s2s = Seq2seq()X_onehot, Y_onehot = s2s.load_data(10000)s2s.init_seq2seq()s2s.train(X_onehot, Y_onehot)
整個數(shù)據(jù)集特征值的形狀: (10000, 30, 37)
整個數(shù)據(jù)集目標(biāo)值的形狀: (10000, 10, 11)
查看第一條數(shù)據(jù)集格式:特征值:9 may 1998, 目標(biāo)值: 1998-05-09
[12 0 24 13 34 0 4 12 12 11 36 36 36 36 36 36 36 36 36 36 36 36 36 3636 36 36 36 36 36] [ 2 10 10 9 0 1 6 0 1 10]
one_hot編碼: [[0. 0. 0. ... 0. 0. 0.][1. 0. 0. ... 0. 0. 0.][0. 0. 0. ... 0. 0. 0.]...[0. 0. 0. ... 0. 0. 1.][0. 0. 0. ... 0. 0. 1.][0. 0. 0. ... 0. 0. 1.]] [[0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.][0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.][0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.][0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0.][1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.][0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.][0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0.][1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.][0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.][0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]]
Epoch 1/1100/10000 [..............................] - ETA: 10:52 - loss: 23.9884 - dense_1_loss: 2.3992 - dense_1_acc: 0.3200 - dense_1_acc_1: 0.0000e+00 - dense_1_acc_2: 0.0100 - dense_1_acc_3: 0.1300 - dense_1_acc_4: 0.0000e+00 - dense_1_acc_5: 0.0400 - dense_1_acc_6: 0.0900 - dense_1_acc_7: 0.0000e+00 - dense_1_acc_8: 0.3500 - dense_1_acc_9: 0.1100200/10000 [..............................] - ETA: 5:27 - loss: 23.9289 - dense_1_loss: 2.3991 - dense_1_acc: 0.2550 - dense_1_acc_1: 0.0000e+00 - dense_1_acc_2: 0.0050 - dense_1_acc_3: 0.1150 - dense_1_acc_4: 0.0950 - dense_1_acc_5: 0.0250 - dense_1_acc_6: 0.1150 - dense_1_acc_7: 0.0800 - dense_1_acc_8: 0.3400 - dense_1_acc_9: 0.1050
- 測試
if __name__ == '__main__':s2s = Seq2seq()X_onehot, Y_onehot = s2s.load_data(10000)s2s.init_seq2seq()s2s.train(X_onehot, Y_onehot)# s2s.test()
source: 1 March 2001
output: 2001-03-01
4.3.3.5 代碼編寫
- 1、模型一些參數(shù)確定
def __init__(self, Tx=30, Ty=10, n_x=32, n_y=64):# 定義網(wǎng)絡(luò)的相關(guān)參數(shù)self.model_param = {"Tx": Tx, # 定義encoder序列最大長度"Ty": Ty, # decoder序列最大長度"n_x": n_x, # encoder的隱層輸出值大小"n_y": n_y # decoder的隱層輸出值大小和cell輸出值大小}
對于加載數(shù)據(jù)來說,我們不需要去進(jìn)行編寫邏輯了,看一下大概的邏輯.
- 2、加載數(shù)據(jù)
- 加載的代碼邏輯在nmt_utils當(dāng)中
- from nmt_utils import *
- 加載的代碼邏輯在nmt_utils當(dāng)中
添加一些參數(shù)到model_param中
# 添加特征詞個不重復(fù)個數(shù)以及目標(biāo)詞的不重復(fù)個數(shù)
self.model_param["x_vocab"] = x_vocab
self.model_param["y_vocab"] = y_vocabself.model_param["x_vocab_size"] = len(x_vocab)
self.model_param["y_vocab_size"] = len(y_vocab)
我們先看整個訓(xùn)練的邏輯,并從中來實(shí)現(xiàn)整個模型的定義,計(jì)算邏輯
dataset:[('9 may 1998', '1998-05-09'), ('10.09.70', '1970-09-10')]
x_vocab:翻譯前的格式對應(yīng)數(shù)字{' ': 0, '.': 1, '/': 2, '0': 3, '1': 4, '2': 5, '3': 6, '4': 7,...........}
y_vocab:翻譯后的格式對應(yīng)數(shù)字{'-': 0, '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8, '8': 9, '9': 10}
# 添加特征詞個不重復(fù)個數(shù)以及目標(biāo)詞的不重復(fù)個數(shù)
self.model_param["x_vocab"] = x_vocab
self.model_param["y_vocab"] = y_vocabself.model_param["x_vocab_size"] = len(x_vocab)
self.model_param["y_vocab_size"] = len(y_vocab)
-
3、訓(xùn)練步驟
-
- (1)定義好網(wǎng)絡(luò)的輸入輸出格式
- (2)定義好優(yōu)化器(選擇Adam,參數(shù)lr=0.005, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.001)
- from keras.optimizers import Adam
- model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
- (3)模型訓(xùn)練,
- model.fit(inputs, outputs, epochs=1,batch_size=100)
def train(self, X_onehot, Y_onehot):"""訓(xùn)練:param X_onehot: 特征值的one_hot編碼:param Y_onehot: 目標(biāo)值的one_hot編碼:return:"""# 利用網(wǎng)絡(luò)結(jié)構(gòu)定義好模型輸入輸出model = self.model()opt = Adam(lr=0.005, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.001)model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])s0 = np.zeros((10000, self.model_param["n_y"]))c0 = np.zeros((10000, self.model_param["n_y"]))outputs = list(Y_onehot.swapaxes(0, 1))# 輸入x,以及decoder中LSTM的兩個初始化值model.fit([X_onehot, s0, c0], outputs, epochs=1, batch_size=100)return None
- (1)定義網(wǎng)絡(luò)好的輸入到輸出流程
- 步驟1、定義模型的輸入
- 步驟2:使用encoder的雙向LSTM結(jié)構(gòu)得輸出a
- 步驟3:循環(huán)decoder的Ty次序列輸入,獲取decoder最后輸出
- 1: 定義decoder第t'時刻的注意力結(jié)構(gòu)并輸出context
- context = self.computer_one_attention(a, s)(需要實(shí)現(xiàn)Attention結(jié)構(gòu)的計(jì)算過程)
- 2: 對"context" 和初始兩個狀態(tài)s0,c0輸入到deocder當(dāng)中,返回兩個輸出
- s, _, c = self.decoder(context, initial_state=[s, c])
- 3: 應(yīng)用 Dense layere獲取deocder的t'時刻的輸出 out = self.output_layer(s)
- 1: 定義decoder第t'時刻的注意力結(jié)構(gòu)并輸出context
- 步驟 4: 創(chuàng)建model實(shí)例,定義輸入輸出
- from keras.models import Model
?
def model(self):"""定義模型獲取模型實(shí)例:param model_param: 網(wǎng)絡(luò)的相關(guān)參數(shù):param seq2seq:網(wǎng)絡(luò)結(jié)構(gòu):return: model,Keras model instance"""# 步驟1、定義模型的輸入# 定義decoder中隱層初始狀態(tài)值s0以及cell輸出c0X = Input(shape=(self.model_param["Tx"], self.model_param["x_vocab_size"]), name='X')# 定義deocder初始化狀態(tài)s0 = Input(shape=(self.model_param["n_y"],), name='s0')c0 = Input(shape=(self.model_param["n_y"],), name='c0')s = s0c = c0# 定義裝有輸出值的列表outputs = []# 步驟2:使用encoder的雙向LSTM結(jié)構(gòu)得輸出aa = self.encoder(X)# 步驟3:循環(huán)decoder的Ty次序列輸入,獲取decoder最后輸出# 包括計(jì)算Attention輸出for t in range(self.model_param["Ty"]):# 1: 定義decoder第t'時刻的注意力結(jié)構(gòu)并輸出contextcontext = self.computer_one_attention(a, s)# 2: 對"context" vector輸入到deocder當(dāng)中# 獲取cell的兩個輸出隱層狀態(tài)和,initial_state= [previous hidden state, previous cell state]s, _, c = self.decoder(context, initial_state=[s, c])# 3: 應(yīng)用 Dense layere獲取deocder的t'時刻的輸出out = self.output_layer(s)# 4: 將decoder中t'時刻的輸出裝入列表outputs.append(out)# 步驟 4: 創(chuàng)建model實(shí)例,定義輸入輸出model = Model(inputs=(X, s0, c0), outputs=outputs)return model
- 3、模型初始化模型結(jié)構(gòu)定義
- 在訓(xùn)練中有一些模型結(jié)構(gòu),所以現(xiàn)需要定義這些結(jié)構(gòu)統(tǒng)一初始化,這些模型結(jié)構(gòu)作為整個Seq2Seq類的屬性,初始化邏輯。
def init_seq2seq(self):"""初始化網(wǎng)絡(luò)結(jié)構(gòu):return:"""# 添加encoder屬性self.get_encoder()# 添加decoder屬性self.get_decoder()# 添加attention屬性self.get_attention()# 添加get_output_layer屬性self.get_output_layer()return None
- 定義編解碼器、Attention機(jī)制、輸出層
?
Keras是一個高級神經(jīng)網(wǎng)絡(luò)API,用Python編寫,能夠在TensorFlow之上運(yùn)行。它的開發(fā)重點(diǎn)是實(shí)現(xiàn)快速實(shí)驗(yàn)。能夠以最小的延遲從想法到結(jié)果是進(jìn)行良好研究的關(guān)鍵。
如果您需要深度學(xué)習(xí)庫,請使用Keras:允許簡單快速的原型設(shè)計(jì)(通過用戶友好性,模塊化和可擴(kuò)展性)
- 編碼器
- 編碼器:使用雙向LSTM(隱層傳遞有雙向值傳遞)
- from keras.layers import LSTM, Bidirectional
- LSTM(units, return_sequences=False,name="")
- units: 正整數(shù), units狀態(tài)輸出的維度
- return_sequences:布爾類型 是否返回輸出序列
- return:LSTM layer
- Bidirectional(layer, merge_mode='concat')
- 對RNN、LSTM進(jìn)行雙向裝飾
- layer:RNN layer或者LSTM layer
- merge_mode:將RNN/LSTM的前向和后向輸出值進(jìn)行合并
- {'sum', 'mul', 'concat', 'ave', None}
def get_encoder(self):"""定義編碼器結(jié)構(gòu):return:"""# 指定隱層值輸出的大小self.encoder = Bidirectional(LSTM(self.model_param["n_x"], return_sequences=True, name='bidirectional_1'), merge_mode='concat')return None
- 解碼器
- return_state: 布爾,是否返回輸出以及狀態(tài)值
- if return_state: 第一個值是output. 后面的值是狀態(tài)值shape 為 (batch_size, units).
- return_state: 布爾,是否返回輸出以及狀態(tài)值
def get_decoder(self):"""定義解碼器結(jié)構(gòu):return:"""# 定義decoder結(jié)構(gòu),指定隱層值的形狀大小,return_state=Trueself.decoder = LSTM(self.model_param["n_y"], return_state=True)return None
- 輸出層
- from keras.layer import Dense
- 指定一個普通的全連接層,并且可以指定激活函數(shù)
- Dense(units, activation=None)
- 神經(jīng)元個數(shù)(輸出大小)
- activation=None:激活函數(shù)
def get_output_layer(self):"""定義輸出層:return: output_layer"""# 對decoder輸出進(jìn)行softmax,輸出向量大小為y_vocab大小self.output_layer = Dense(self.model_param["y_vocab_size"], activation=softmax)return None
- computer_one_attention函數(shù)實(shí)現(xiàn):attention層結(jié)構(gòu)
- 1、定義結(jié)構(gòu)
- 2、實(shí)現(xiàn)輸入輸出結(jié)果
- \alpha_{t' t} = \frac{\exp(e_{t' t})}{ \sum_{k=1}^T \exp(e_{t' k}) },\quad t=1,\ldots,Tα?t?′??t??=?∑?k=1?T??exp(e?t?′??k??)??exp(e?t?′??t??)??,t=1,…,T
- e_{t' t} = g({s}_{t' - 1}, {h}_t)= {v}^\top \tanh({W}_s {s} + {W}_h {h})e?t?′??t??=g(s?t?′???1??,h?t??)=v????tanh(W?s??s+W?h??h)
?
- from keras.layers import RepeatVector, Concatenate, Dot, Activation
def get_attention(self):"""定義Attention的結(jié)構(gòu):return: attention結(jié)構(gòu)"""# 定義RepeatVector復(fù)制成多個維度repeator = RepeatVector(self.model_param["Tx"])# 進(jìn)行矩陣拼接concatenator = Concatenate(axis=-1)# 進(jìn)行全連接層10個神經(jīng)元densor1 = Dense(10, activation="tanh", name='Dense1')# 接著relu函數(shù)densor2 = Dense(1, activation="relu", name='Dense2')# softmaxactivator = Activation(softmax,name='attention_weights')# context計(jì)算dotor = Dot(axes=1)# 將結(jié)構(gòu)存儲在attention當(dāng)中self.attention = {"repeator": repeator,"concatenator": concatenator,"densor1": densor1,"densor2": densor2,"activator": activator,"dotor": dotor}return None
- Attention輸入輸出邏輯
- 使用Attention結(jié)構(gòu)去實(shí)現(xiàn)輸入到輸出的邏輯
def computer_one_attention(self, a, s_prev):"""利用定義好的attention結(jié)構(gòu)計(jì)算中的alpha系數(shù)與a對應(yīng)輸出:param a:隱層狀態(tài)值 (m, Tx, 2*n_a):param s_prev: LSTM的初始隱層狀態(tài)值, 形狀(sample, n_s):return: context"""# 使用repeator擴(kuò)大數(shù)據(jù)s_prev的維度為(sample, Tx, n_y),這樣可以與a進(jìn)行合并s_prev = self.attention["repeator"](s_prev)# 將a和s_prev 按照最后一個維度進(jìn)行合并計(jì)算concat = self.attention["concatenator"]([a, s_prev])# 使用densor1全連接層網(wǎng)絡(luò)計(jì)算出ee = self.attention["densor1"](concat)# 使用densor2增加relu激活函數(shù)計(jì)算energies = self.attention["densor2"](e)# 使用"activator"的softmax函數(shù)計(jì)算權(quán)重"alphas"# 這樣一個attention的系數(shù)計(jì)算完成alphas = self.attention["activator"](energies)# 使用dotor,矩陣乘法,將 "alphas" and "a" 去計(jì)算context/ccontext = self.attention["dotor"]([alphas, a])return context
- 4、測試邏輯
- model.load_weights(path):加載模型
def test(self):"""測試:return:"""model = self.model()model.load_weights("./models/model.h5")example = '1 March 2001'source = string_to_int(example, self.model_param["Tx"], self.model_param["x_vocab"])source = np.expand_dims(np.array(list(map(lambda x:to_categorical(x, num_classes=self.model_param["x_vocab_size"]),source))), axis=0)s0 = np.zeros((10000, self.model_param["n_y"]))c0 = np.zeros((10000, self.model_param["n_y"]))prediction = model.predict([source, s0, c0])prediction = np.argmax(prediction, axis=-1)output = [dict(zip(self.model_param["y_vocab"].values(), self.model_param["y_vocab"].keys()))[int(i)] for i in prediction]print("source:", example)print("output:", ''.join(output))return None
4.3.4 集束搜索(Beam Search)
4.3.4.1 問題引入
我們在找到一個合適的句子的時候,一個很直觀的方法是在生成第一個詞y^{1}y?1??分布之后,根據(jù)條件語言模型挑選出最有可能的第一個詞y^{1}y?1???,然后生成第二個詞y^{2}y?2??的概率分布挑選第二個詞y^{2}y?2??,依此類推,始終是選擇每一個最大概率的詞,這種方法在機(jī)器翻譯領(lǐng)域其實(shí)并不管用,我們來舉個例子
法語句子"Jane visite l'Afrique en septembre."
翻譯1-Jane is visiting Africa in September.
翻譯2-Jane is going to be visiting Africa in September.
翻譯1顯然比翻譯2要更好,更加簡潔的表達(dá)了意思。
如果該算法挑選了?y^{1},y^{2}y?1??,y?2??, ('Jane' , 'is'),那么在英語中"is going"更加常見,因此在選擇?y^{3}y?3???='going',于是對于合適的句法來說"Jane is visiting"相比"Jane is going"會有更高的概率使用,所以有時候真正需要的是一次性挑選整個單詞序列y^{1},y^{2},y^{3},...,y^{t}y?1??,y?2??,y?3??,...,y?t???使得整體的條件概率最大。
4.3.4.2 集束搜索流程
- 定義:在Beam Search中有一個參數(shù)B,叫做beam width(集束寬),用來表示在每一次篩選時挑top B的結(jié)果。
例子說明:
?
- 第一次:選出概率最大的三個詞
- 第二次:選擇上一步三個詞,每個詞對應(yīng)三個概率最大的詞(可能存在重復(fù))
- ....
假設(shè)只有兩步,那么得到9個結(jié)果。最終我們要從中選出三組結(jié)果
- is fine
- in alright
- at alright
那么這三個句子就是我們需要的結(jié)果。
4.3.5 BLEU-機(jī)器翻譯的自動評估方法
對于上述篩選的結(jié)果我們可以讓一些語言專家進(jìn)行評估選出最合適的。當(dāng)然有大量人力也是可以這樣去做,但是我們希望系統(tǒng)能夠自動選擇一個最合適的翻譯句子。需要提供兩個
- 1、衡量機(jī)器翻譯結(jié)果越接近人工翻譯結(jié)果的數(shù)值指標(biāo)
- 2、一套人工翻譯的高質(zhì)量參考譯文
4.3.5.1 定義
BLEU的全名為:bilingual evaluation understudy(雙語互譯質(zhì)量評估輔助工具),它是用來評估機(jī)器翻譯質(zhì)量的工具。
- 判斷兩個句子的相似程度
4.3.5.2 N-gram Precision(多元精度得分)方法
- N-gram Precision(多元精度得分)
這里的N是什么意思,我們通過一個例子來理解一下。
候選翻譯: the the the the the the the
參考翻譯: the cat is on the mat
參考翻譯: there is a cat on the mat
兩個句子,S1和S2,S1里頭的詞出現(xiàn)在S2里頭越多,就說明這兩個句子越一致。記做\frac{number1}{number2}?number2??number1??。上面例子,候選翻譯的詞7個詞the都在參考翻譯中出現(xiàn),記做分子得分7,候選翻譯一共就7個詞,分母為7。7/7=1,該候選翻譯顯然不行!!這個時候N=1,選出一個詞
- 改進(jìn)
- 原因:常用詞干擾、選詞的粒度太小(the)
- 使用N-gram,多元詞組:{“the cat”, “cat is”, “is on”, “on the”, “the mat”}
1、同樣還是一個詞的時候的改進(jìn)
- 過濾常見詞(the on is ...so on)
- 公式計(jì)算(分子)
- Count_{w_i,j}^{clip} = min(Count_{w_i},Ref_{j}\_Count_{w_i})Count?w?i??,j?clip??=min(Count?w?i????,Ref?j??_Count?w?i????)
- 統(tǒng)計(jì)候選區(qū)域
- Count_{w_i}Count?w?i????:候選翻譯中單詞w_iw?i??出現(xiàn)過的個數(shù),如上表就是對“the”的計(jì)數(shù)為7
- Ref_{j}\_Count_{w_i}Ref?j??_Count?w?i????:詞w_iw?i??在第個jj參考翻譯里出現(xiàn)的次數(shù)
- {Count}^{clip} = max(Count_{w_i,j}^{clip}), i=1,2,{...}Count?clip??=max(Count?w?i??,j?clip??),i=1,2,...
- 作用:選出候選翻譯在參考翻譯中最大的計(jì)數(shù)
- Count_{w_i,j}^{clip}Count?w?i??,j?clip??:第jj個參考翻譯,w_{i}w?i??計(jì)數(shù)
- Count^{clip}Count?clip??:在所有參考翻譯中的w_iw?i??綜合計(jì)數(shù)
- Count_{w_i,j}^{clip} = min(Count_{w_i},Ref_{j}\_Count_{w_i})Count?w?i??,j?clip??=min(Count?w?i????,Ref?j??_Count?w?i????)
仍然以上面的例子來看:Ref_{1}\_Count_{'the'}=2Ref?1??_Count??′??the?′????=2,則Count_{'the',1}^{clip}=min(7,2)=2Count??′??the?′??,1?clip??=min(7,2)=2,Count_{'the',2}^{clip}=1Count??′??the?′??,2?clip??=1,所以綜合計(jì)數(shù)為Count^{clip}=max(1,2)=2Count?clip??=max(1,2)=2,分母不變,仍是候選句子的n-gram個數(shù)。這里分母為7。得分P = 2/7=0.28
2、多個改進(jìn)的多元精度(modified n-gram precision)進(jìn)行組合
n-gram下的可以衡量翻譯的流程性,當(dāng)我們對不同尺度的詞進(jìn)行統(tǒng)計(jì)出來,計(jì)算精度的時候,結(jié)果為
?
隨著n-gram的增大,精度得分總體上成指數(shù)下降的。采取幾何加權(quán)平均,并且將各n-gram的作用視為等重要的,即取權(quán)重服從均勻分布:p_{ave}=\sqrt[\sum_{n=1}^{N}w_{n}]{\prod_{n=1}^Np_{n}^{w_{n}}}=\frac{1}{\sum_{n=1}^{N}w_{n}}exp(\sum_{i=1}^{N}w_{n}*log^{p_{n}})=exp(\frac{1}{N}*\sum_{i=1}^{N}log^{p_{n}})p?ave??=?∑?n=1?N??w?n????√?∏?n=1?N??p?n?w?n???????=?∑?n=1?N??w?n????1??exp(∑?i=1?N??w?n???log?p?n????)=exp(?N??1???∑?i=1?N??log?p?n????)
上面圖的理解就為:p_{ave}=exp(\frac{1}{4}*(log^{p_{1}}+log^{p_{2}}+log^{p_{3}}+log^{p_{4}}))p?ave??=exp(?4??1???(log?p?1????+log?p?2????+log?p?3????+log?p?4????))
3、進(jìn)行短句懲罰
候選翻譯: the cat
參考翻譯: the cat is on the mat
參考翻譯: there is a cat on the mat
這樣就很容易的高分,所以就需要一個有效的乘懲罰機(jī)制。我們設(shè)c為候選翻譯,r為參考翻譯。則有下面的公式
BP=\lbrace^{1,ifc>r}_{e^{1-\frac{r}{c}},ifc \leq r}BP={?e?1??c??r????,ifc≤r?1,ifc>r??
4、最終BLEU值得計(jì)算公式
BLEU=BP*exp(\sum_{n=1}^{N}w_{n}*log^{p_{n}})BLEU=BP?exp(∑?n=1?N??w?n???log?p?n????)
4.3.6 總結(jié)
- 掌握seq2seq模型特點(diǎn)
- 掌握集束搜索方式
- 掌握BLEU評估方法
- 掌握Attention機(jī)制
總結(jié)
以上是生活随笔為你收集整理的seq2seq与Attention机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 词嵌入与NLP
- 下一篇: 生成对抗网络(GAN)