天天看點

莫煩nlp——了解句子seq2seq了解句子日期轉換執行個體 (沒看代碼)CNN的語言模型

視訊連結:https://mofanpy.com/tutorials/machine-learning/nlp/intro-w2v/

原理我都懂,就當溫故而知新

了解句子

目的:機器通過模型對于一句話的了解轉化成一個向量。

前提:在以前的視訊中,我提到過我們人類了解句子的前提是了解句子中每個詞語的含義,然後将詞語組成句,看似我們已經找到了一條通往了解句子的光明大道。可是即便計算機能夠通過 w2v 拿到對詞語的向量化了解,我們要怎麼使用,才能把它變成對句子的了解呢?

思想:最常見的方案就是使用神經網絡做這樣的複雜乘法運算,讓一個空間(詞語)的向量,在另一個空間(句子)以不同形式表達。這個過程叫做 Encoding,編碼。

莫煩nlp——了解句子seq2seq了解句子日期轉換執行個體 (沒看代碼)CNN的語言模型

這個過程類似壓縮的過程,将大量複雜的資訊,壓縮成少量經典的資訊,通過這個途徑找到資訊的精華部分。一個人說話是存在順序資訊的,如果将詞語的順序颠倒,我們可能會得到完全不同的資訊。模型必須将順序資訊完全考慮起來——循環神經網絡。

用途:循環神經網絡閱讀完整句後,模型擁有了對這句話整體的了解,也就有能力産生出一個基于整句了解的向量。Decoder過程負責将思考怎麼樣在了解的句子的基礎上做任務,比如根據了解的向量生成機器人下一輪對話,生成一張愛心圖案,判斷這句話是積極狀态,又或者判斷要進入到支援莫煩的步驟。

莫煩nlp——了解句子seq2seq了解句子日期轉換執行個體 (沒看代碼)CNN的語言模型

了解上文,生成下文。在翻譯任務中,兩個步驟加起來就等于Seq2Seq架構

日期轉換執行個體 (沒看代碼)

向量表示是深度學習成功的關鍵。對句子的了解,就是在多元空間中給這個句子安排一個合适的位置。将空間資訊轉換成其他資訊,就能完成對這個句子了解後的應用了。

任務

将中文的順序日期,轉成英文的逆序日期。資料區間是20世紀後期到21世紀前期。

沒看代碼原因:

1.使用TensorFlow2版本裡面的第三方庫

import tensorflow_addons as tfa

tfa.seq2seq.BasicDecoder

tfa.seq2seq.sampler.TrainingSampler()

tfa.seq2seq.sampler.GreedyEmbeddingSampler()

還內建了注意力機制

我之前使用pytorch,沒有時間在學tf是怎麼實作了,本來就不是工作任務。确實用到在踏踏實實看。

2.之前我沒用到beam search是以好奇,但莫煩隻是提了一下,沒有實作。不過我以前以為training的時候用,現在知道隻是在預測的時候使用。

很抱歉沒給大家注釋代碼,本人能力有限,torch的seq2seq版本都沒學好。

或者等到transformer或者注意力機制,看看有沒有時間,畢竟transformer就是用來代替RNN的

beam search

每次預測都記錄最優的兩個預測,然後沿着這兩個預測繼續預測, 每次後續的預測都隻挑選下一步最好的兩個預測。 這樣加大了搜尋範圍,使我們有機會接觸到全局較優路徑。

莫煩nlp——了解句子seq2seq了解句子日期轉換執行個體 (沒看代碼)CNN的語言模型
莫煩nlp——了解句子seq2seq了解句子日期轉換執行個體 (沒看代碼)CNN的語言模型

CNN的語言模型

将encoder的LSTM改成CNN,decoder還是使用LSTM。代碼還是不看了,效果沒RNN正确。

這裡隻分析到底怎麼使用CNN的。

思想:

  1. 用N個不同長度時間視窗,以CNN的卷積方法在句子中依次滑動,讓模型擁有N種閱讀的眼界寬度,綜合N種寬度的資訊總結出這句話的内容。
  2. CNN利用不同長度的卷積核去觀察句子中不同長度的局部特征。 然後CNN對句子的了解就是不同長度的局部特征拼湊起來的了解。
  3. 比如:

    卷積核A兩個兩個字一起看;

    卷積核B三個三個字一起看;

    卷積核C四個四個字一起看;

  4. 卷積核ABC利用自己看句子的獨特視角,能夠提煉出對句子不同的了解,然後如果再彙集這些不同了解,就有了一個對句子更加全面的了解。
# 得到[batch, step, emb_dim]
self.enc_embeddings = keras.layers.Embedding(
            input_dim=enc_v_dim, output_dim=emb_dim,  # [enc_n_vocab, emb_dim]
            embeddings_initializer=tf.initializers.RandomNormal(0., 0.1),
        )
#三個對不同長度的局部資訊做卷積 [n, step=8, emb=16, 1]
self.conv2ds = [# n指kernel的長, emb_dim指寬。16為channel,不填充,是以filter隻往下移,不需向右
            keras.layers.Conv2D(16, (n, emb_dim), padding="valid", activation=keras.activations.relu) 
            for n in range(2, 5)]
#然後再用MaxPool2D去将他們歸一化到同一dimension。句子長度為7,壓縮成一個字
self.max_pools = [keras.layers.MaxPool2D((n, 1)) for n in [7, 6, 5]]
self.encoder = keras.layers.Dense(units, activation=keras.activations.relu)            
def encode(self, x):
       embedded = self.enc_embeddings(x)               # [n, step, emb]
       o = tf.expand_dims(embedded, axis=3)            # [n, step=8, emb=16, 1]
       co = [conv2d(o) for conv2d in self.conv2ds]     # [n, 7, 1, 16], [n, 6, 1, 16], [n, 5, 1, 16]
       co = [self.max_pools[i](co[i]) for i in range(len(co))]     # [n, 1, 1, 16] * 3
       co = [tf.squeeze(c, axis=[1, 2]) for c in co]               # [n, 16] * 3
       o = tf.concat(co, axis=1)           # [n, 16*3]
       h = self.encoder(o)                 # [n, units]
       return [h, h]           
           

CNN的局限性

不知道你有沒有思考過,CNN做句向量encoding的時候有一個局限性,它要求有個句子最長的限制,句子如果超過這個長度,那麼就最好截斷它。 因為就像在給圖像做卷積,圖像也是要定長定寬的,不然卷積和池化會有尺度上的問題。這是一個相比RNN的硬傷。之後我們在介紹Transformer類型的語言模型時, 也會介紹到這個硬傷。

繼續閱讀