在前幾講中筆者和大家講到了詞向量的一些內容,關於 word2vec 詞向量的主要類型和訓練方式,以及如何基於訓練好的詞向量做一些簡單的分析。本節開始我們繼續回到之前的 RNN 模型,學習一些經典的深度學習自然語言模型,以及一些常見的 NLP 應用。
本講筆者要說的是著名的 seq2seq 模型,翻譯過來也就是序列對序列的模型,在前面 RNN 的幾種類型內容中我們已經了解到了 seq2seq 本質上是一種多對多(N vs M)RNN 模型,也就是輸入序列和輸出序列不等長的 RNN 模型。也正是因為 seq2seq 的這個特性,使得其有著廣泛的應用場景,比如神經機器翻譯、文本摘要、語音識別、文本生成、AI寫詩等等。
seq2seq先簡單來圖解一下 seq2seq 模型,剛剛說了 seq2seq 針對的是輸入輸出序列不等長的情況,對於這種情況,seq2seq 的做法是先將輸入序列編碼成一個上下文向量 c,如下圖所示:
N VS M 編碼 (圖片選自何之源知乎專欄)
https://zhuanlan.zhihu.com/p/28054589
如上圖所示,我們可以通過對最後一個隱變量以 c 進行賦值,然後展開來寫。編碼完成後我們再用一個 RNN 對 c 的結果進行解碼,簡而言之就是將 c 作為初始狀態的隱變量輸入到解碼網絡,如下圖所示:
N VS M 解碼 (圖片選自何之源知乎專欄)
https://zhuanlan.zhihu.com/p/28054589
seq2seq 模型最早是在 2013 年由 cho 等人提出一種 RNN 模型,主要的應用目的就是機器翻譯。
最早的編碼解碼結構:
除了上面這篇文章之外,奠定 seq2seq 理論的還有一幹谷歌大佬們的這篇論文:
關於 seq2seq 的數學細節這裡不做更多講述,感興趣的朋友可以認真研讀上述兩篇論文。
seq2seq 的keras實現 下面我們來嘗試使用 keras 實現一個簡單的 seq2seq 模型。實現代碼如下:
導入相關 package:
from recurrentshop import LSTMCell, RecurrentSequential
from .cells import LSTMDecoderCell, AttentionDecoderCell
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, TimeDistributed, Bidirectional, Input
定義一個簡單的 seq2seq 模型:
def SimpleSeq2Seq(output_dim, output_length, hidden_dim=None, input_shape=None, batch_size=None, batch_input_shape=None, input_dim=None, input_length=None, depth=1, dropout=0.0, unroll=False, stateful=False):
''' Simple model for sequence to sequence learning. The encoder encodes the input sequence to vector (called context vector) The decoder decodes the context vector in to a sequence of vectors. There is no one on one relation between the input and output sequence elements. The input sequence and output sequence may differ in length. Arguments: output_dim : Required output dimension. hidden_dim : The dimension of the internal representations of the model. output_length : Length of the required output sequence. depth : Used to create a deep Seq2seq model. For example, if depth = 3, there will be 3 LSTMs on the enoding side and 3 LSTMs on the decoding side. You can also specify depth as a tuple. For example, if depth = (4, 5), 4 LSTMs will be added to the encoding side and 5 LSTMs will be added to the decoding side. dropout : Dropout probability in between layers. ''' if isinstance(depth, int): depth = (depth, depth)
if batch_input_shape: shape = batch_input_shape
elif input_shape: shape = (batch_size,) + input_shape
elif input_dim:
if input_length: shape = (batch_size,) + (input_length,) + (input_dim,)
else: shape = (batch_size,) + (None,) + (input_dim,)
else:
raise TypeError
if hidden_dim is None: hidden_dim = output_dim
# 編碼過程 encoder = RecurrentSequential(unroll=unroll, stateful=stateful) encoder.add(LSTMCell(hidden_dim, batch_input_shape=(shape[0], shape[-1])))
for _ in range(1, depth[0]): encoder.add(Dropout(dropout)) encoder.add(LSTMCell(hidden_dim))
# 解碼過程 decoder = RecurrentSequential(unroll=unroll, stateful=stateful, decode=True, output_length=output_length) decoder.add(Dropout(dropout, batch_input_shape=(shape[0], hidden_dim)))
if depth[1] == 1: decoder.add(LSTMCell(output_dim))
else: decoder.add(LSTMCell(hidden_dim))
for _ in range(depth[1] - 2): decoder.add(Dropout(dropout)) decoder.add(LSTMCell(hidden_dim)) decoder.add(Dropout(dropout)) decoder.add(LSTMCell(output_dim)) _input = Input(batch_shape=shape) x = encoder(_input) output = decoder(x)
return Model(_input, output)
seq2seq 模型搭建:
model = SimpleSeq2Seq(input_dim=5, hidden_dim=10, output_length=8, output_dim=8)model.compile(loss='mse', optimizer='rmsprop')
以上便是本節內容。下一講筆者將講解有關注意力機制模型的一些內容。
參考資料:
deeplearningai.com
Sequence to Sequence Learning with Neural Networks
Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation
https://github.com/farizrahman4u/seq2seq/
https://zhuanlan.zhihu.com/p/28054589
往期精彩:
深度學習第45講:GloVe詞向量與相關應用
深度學習第44講:訓練一個word2vec詞向量
深度學習第43講:自然語言處理之word2vec
深度學習第42講:自然語言處理之詞嵌入和詞向量
深度學習第41講:LSTM的numpy和keras實現
深度學習第40講:RNN之長短期記憶網絡LSTM
深度學習第39講:RNN之門控循環單元GRU
深度學習第38講:RNN的 4 種類型
一個數據科學從業者的學習歷程
長按二維碼.關注機器學習實驗室