語言生成實戰:自己訓練能講「人話」的神經網路(下)
- 2019 年 10 月 4 日
- 筆記
在昨天的學習當中,我們了解了培養一個會說話的語言生成模型所需要的如何創建數據集這一模組,今天我們繼續學習構建語言生成模型。
前文鏈接:語言生成實戰:自己訓練能講「人話」的神經網路(上)
2.構建模型
我們將使用長短期記憶網路(LSTM)。LSTM的一個重要優點是能夠理解對整個序列的依賴性,因此,句子的開頭可能會對要預測的第15個單詞產生影響。另一方面,遞歸神經網路(RNNs)只意味著依賴於網路的前一個狀態,只有前一個詞才能幫助預測下一個狀態。如果選擇RNNs,我們很快就會錯過上下文,因此,LSTMs似乎是正確的選擇。
a.模型架構
由於訓練可以非常(非常)(非常)(非常)(非常)(非常)(非常)(不開玩笑)長,我們將構建一個簡單的1嵌入+ 1 LSTM層+ 1密集網路:
def create_model(max_sequence_len, total_words): input_len = max_sequence_len - 1 model = Sequential() # Add Input Embedding Layer model.add(Embedding(total_words, 10, input_length=input_len)) # Add Hidden Layer 1 - LSTM Layer model.add(LSTM(100)) model.add(Dropout(0.1)) # Add Output Layer model.add(Dense(total_words, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam') return model model = create_model(max_sequence_len, total_words) model.summary()
首先,我們添加一個嵌入層。我們將其傳遞到一個有100個神經元LSTM中,添加一個dropout來控制神經元的協同適應,最後是一個緻密層。注意,我們在最後一層應用一個softmax激活函數來獲得輸出屬於每個類的概率。所使用的損失是分類交叉熵,因為它是一個多類分類問題。
模型總結如下:

b.訓練模型
我們現在(終於)準備好訓練模型了!
model.fit(X, y, batch_size=256, epochs=100, verbose=True)
然後將開始訓練模型:
Epoch 1/10 164496/164496 [==============================] - 471s 3ms/step - loss: 7.0687 Epoch 2/10 73216/164496 [============>.................] - ETA: 5:12 - loss: 7.0513
在CPU上,一個時期大約需要8分鐘。在GPU上(例如在Colab中), 您應該修改使用的Keras LSTM網路,因為它不能在GPU上使用。相反,您需要:
# Modify Import from keras.layers import Embedding, LSTM, Dense, Dropout, CuDNNLSTM # In the Moddel ... model.add(CuDNNLSTM(100)) ...
我傾向於在幾個步驟中停止訓練來進行樣本預測,並控制給定幾個交叉熵值的模型的品質。
以下是我的觀察:

3.生成序列
如果你讀過這篇文章,這就是你所期待的:創造新的句子!要生成句子,我們需要對輸入文本應用相同的轉換。我們將建立一個循環,為給定的迭代次數生成下一個單詞:
input_txt = "Machine" for _ in range(10): # Get tokens token_list = tokenizer.texts_to_sequences([input_txt])[0] # Pad the sequence token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre') # Predict the class predicted = model.predict_classes(token_list, verbose=0) output_word = "" # Get the corresponding work for word,index in tokenizer.word_index.items(): if index == predicted: output_word = word break input_txt += " "+output_word
當損失在3.1左右時,以「Google」作為輸入,生成如下句子:
Google是世界範圍內產生的大量數據
這並沒有什麼實際意義,但它成功地將Google與大量數據的概念聯繫起來。這是相當令人印象深刻的,因為它僅僅依賴於單詞的共現,而沒有整合任何語法概念。
如果我們在訓練中再等一段時間,讓損失減小到2.5,然後輸入「Random Forest」:
Random Forest是一個完全託管的服務,旨在支援大量初創企業的願景基礎設施
同樣,生成的內容沒有意義,但語法結構相當正確。
損失在大約50個時期後開始分化,並從未低於2.5。
我想我們已經達到了發展方法的極限:
同樣,生成的東西沒有任何意義,但是語法結構是相當正確的。
這種損失在大約50個時期之後就會出現分歧,而且從未低於2.5。
- 模型仍然很簡單
- 培訓數據不夠清晰
- 數據量非常有限
也就是說,我發現結果非常有趣,例如,經過訓練的模型可以很容易地部署在Flask Web App上。

結論