用於NLP的Python:使用Keras進行深度學習文本生成

原文連接:http://tecdat.cn/?p=8448

文本生成是NLP的最新應用程序之一。深度學習技術已用於各類文本生成任務,例如寫做詩歌,生成電影腳本甚至創做音樂。可是,在本文中,咱們將看到一個很是簡單的文本生成示例,其中給定輸入的單詞字符串,咱們將預測下一個單詞。咱們將使用莎士比亞著名小說《麥克白》的原始文本,並根據給定的一系列輸入單詞來預測下一個單詞。算法

完成本文以後,您將可以使用所選的數據集執行文本生成。因此,讓咱們開始吧。數組

導入庫和數據集

第一步是導入執行本文中的腳本所需的庫以及數據集。如下代碼導入所需的庫:app

importnumpyasnpfromkeras.modelsimportSequential, load_modelfromkeras.layersimportDense, Embedding, LSTM, Dropoutfromkeras.utilsimportto_categoricalfromrandomimportrandintimportreless

下一步是下載數據集。咱們將使用Python的NLTK庫下載數據集。dom

importnltk nltk.download('gutenberg')fromnltk.corpusimportgutenbergasgut print(gut.fileids())ide

您應該看到如下輸出:函數

['austen-emma.txt', 'austen-persuasion.txt', 'austen-sense.txt', 'bible-kjv.txt', 'blake-poems.txt', 'bryant-stories.txt', 'burgess-busterbrown.txt', 'carroll-alice.txt', 'chesterton-ball.txt', 'chesterton-brown.txt', 'chesterton-thursday.txt', 'edgeworth-parents.txt', 'melville-moby_dick.txt', 'milton-paradise.txt', 'shakespeare-caesar.txt', 'shakespeare-hamlet.txt', 'shakespeare-macbeth.txt', 'whitman-leaves.txt']學習

該文件shakespeare-macbeth.txt包含小說「 Macbeth」的原始文本。要今後文件讀取文本,能夠使用類中的raw方法gutenbergurl

macbeth_text = nltk.corpus.gutenberg.raw('shakespeare-macbeth.txt')spa

讓咱們從數據集中打印出前500個字符:

print(macbeth_text[:500])

這是輸出:

[The TragedieofMacbethbyWilliam Shakespeare1603] Actus Primus. Scoena Prima. ThunderandLightning. Enter three Witches.1.When shall we three meet againe? In Thunder, Lightning,orinRaine?2.When the Hurley-burley's done, When the Battaile's lost,andwonne3.That will be ere the setofSunne1.Where the place?2.Vpon the Heath3.There to meet with Macbeth1.I come, Gray-Malkin All. Padock calls anon: faireisfoule,andfouleisfaire, Houer through

您會看到文本包含許多特殊字符和數字。下一步是清理數據集。

數據預處理

要刪除標點符號和特殊字符,咱們將定義一個名爲的函數preprocess_text()

defpreprocess_text(sen):_# Remove punctuations and numbers_sentence = re.sub('[^a-zA-Z]',' ', sen)_# Single character removal_sentence = re.sub(r"\s+[a-zA-Z]\s+",' ', sentence)_# Removing multiple spaces_sentence = re.sub(r'\s+',' ', sentence)returnsentence.lower()

preprocess_text函數接受文本字符串做爲參數,並以小寫形式返回乾淨的文本字符串。

如今讓咱們清理文本,而後再次打印前500個字符:

macbeth_text = preprocess_text(macbeth_text) macbeth_text[:500]

這是輸出:

the tragedieofmacbethbywilliam shakespeare actus primus scoena prima thunderandlightning enter three witcheswhenshall we three meet againeinthunder lightningorinrainewhenthe hurley burley donewhenthe battaile lostandwonne that will be ere the setofsunne where the place vpon the heath there to meet with macbeth come gray malkin all padock calls anon faireisfouleandfouleisfaire houer through the foggeandfilthie ayre exeunt scena secunda alarum within enter king malcom

將單詞轉換爲數字

深度學習模型基於統計算法。所以,爲了使用深度學習模型,咱們須要將單詞轉換爲數字。

在本文中,咱們將使用一種很是簡單的方法,將單詞轉換爲單個整數。在將單詞轉換爲整數以前,咱們須要將文本標記爲單個單詞。爲此,能夠使用模塊中的word_tokenize()方法nltk.tokenize

如下腳本標記咱們數據集中的文本,而後打印數據集中的單詞總數以及數據集中的惟一單詞總數:

fromnltk.tokenizeimportword_tokenize macbeth_text_words = (word_tokenize(macbeth_text)) n_words = len(macbeth_text_words) unique_words = len(set(macbeth_text_words)) print('Total Words: %d'% n_words) print('Unique Words: %d'% unique_words)

輸出這樣:

TotalWords: 17250UniqueWords: 3436

咱們的文字總共有17250個單詞,其中3436個單詞是惟一的。要將標記化的單詞轉換爲數字,能夠使用模塊中的Tokenizerkeras.preprocessing.text。您須要調用該fit_on_texts方法並將其傳遞給單詞列表。將建立一個字典,其中的鍵將表明單詞,而整數將表明字典的相應值。

看下面的腳本:

fromkeras.preprocessing.textimportTokenizer tokenizer = Tokenizer(num_words=3437) tokenizer.fit_on_texts(macbeth_text_words)

要訪問包含單詞及其相應索引的字典,word_index能夠使用tokenizer對象的屬性:

vocab_size = len(tokenizer.word_index) +1word_2_index = tokenizer.word_index

若是您檢查字典的長度,它將包含3436個單詞,這是咱們數據集中惟一單詞的總數。

如今讓咱們從word_2_index字典中打印第500個惟一單詞及其整數值。

print(macbeth_text_words[500]) print(word_2_index[macbeth_text_words[500]])

這是輸出:

comparisons1456

修改數據形狀

LSTM接受3維格式的數據(樣本數,時間步數,每一個時間步的特徵)。因爲輸出將是單個單詞,所以輸出的形狀將是二維的(樣本數,語料庫中惟一詞的數量)。

如下腳本修改了輸入序列和相應輸出的形狀。

input_sequence = [] output_words = [] input_seq_length =100foriinrange(0, n_words - input_seq_length ,1): in_seq = macbeth_text_words[i:i + input_seq_length] out_seq = macbeth_text_words[i + input_seq_length] input_sequence.append([word_2_index[word]forwordinin_seq]) output_words.append(word_2_index[out_seq])

在上面的腳本中,咱們聲明兩個空列表input_sequenceoutput_words。將input_seq_length被設置爲100,這意味着咱們的輸入序列將包括100個字。接下來,咱們執行一個循環,在第一次迭代中,將文本中前100個單詞的整數值附加到input_sequence列表中。第101個單詞將追加到output_words列表中。在第二次迭代過程當中,從文本中的第二個單詞開始到第101個單詞結束的單詞序列存儲在input_sequence列表中,第102個單詞存儲在output_words數組中,依此類推。因爲數據集中共有17250個單詞(比單詞總數少100個),所以將總共生成17150個輸入序列。

如今讓咱們輸出input_sequence列表中第一個序列的值:

print(input_sequence[0])

輸出:

[1,869,4,40,60,1358,1359,408,1360,1361,409,265,2,870,31,190,291,76,36,30,190,327,128,8,265,870,83,8,1362,76,1,1363,1364,86,76,1,1365,354,2,871,5,34,14,168,1,292,4,649,77,1,220,41,1,872,53,3,327,12,40,52,1366,1367,25,1368,873,328,355,9,410,2,410,9,355,1369,356,1,1370,2,874,169,103,127,411,357,149,31,51,1371,329,107,12,358,412,875,1372,51,20,170,92,9]

讓咱們經過將序列中的整數除以最大整數值來歸一化輸入序列。如下腳本還將輸出轉換爲二維格式。

X = np.reshape(input_sequence, (len(input_sequence), input_seq_length,1)) X = X / float(vocab_size) y = to_categorical(output_words)

如下腳本打印輸入和相應輸出的形狀。

print("X shape:", X.shape) print("y shape:", y.shape)

輸出:

Xshape: (17150, 100, 1)yshape: (17150, 3437)

訓練模型

下一步是訓練咱們的模型。關於應使用多少層和神經元來訓練模型,沒有硬性規定。

咱們將建立三個LSTM層,每一個層具備800個神經元。最終將添加具備1個神經元的密集層,以預測下一個單詞的索引,以下所示:

model = Sequential() model.add(LSTM(800, input_shape=(X.shape[1], X.shape[2]), return_sequences=True)) model.add(LSTM(800, return_sequences=True)) model.add(LSTM(800)) model.add(Dense(y.shape[1], activation='softmax')) model.summary() model.compile(loss='categorical_crossentropy', optimizer='adam')

因爲輸出單詞能夠是3436個惟一單詞之一,所以咱們的問題是多類分類問題,所以使用categorical_crossentropy損失函數。若是是二進制分類,binary_crossentropy則使用該函數。一旦執行了上面的腳本,能夠看到模型摘要:

Model: "sequential_1"**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**Layer (type) Output Shape Param # =================================================================lstm_1 (LSTM) (None, 100, 800) 2566400**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**lstm_2 (LSTM) (None, 100, 800) 5123200**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**lstm_3 (LSTM) (None, 800) 5123200**_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____****_____**dense_1 (Dense) (None, 3437) 2753037 =================================================================Total params: 15,565,837 Trainable params: 15,565,837 Non-trainable params: 0

要訓練模型,咱們能夠簡單地使用該fit()方法。

model.fit(X, y, batch_size=64, epochs=10, verbose=1)

 

作出預測

爲了進行預測,咱們將從input_sequence列表中隨機選擇一個序列,將其轉換爲3維形狀,而後將其傳遞給predict()訓練模型的方法。而後將索引值傳遞到index_2_word字典,在字典中將單詞index用做鍵。該index_2_word字典將返回屬於被做爲重點字典傳入的索引詞。

如下腳本隨機選擇一個整數序列,而後輸出相應的單詞序列:

random_seq_index = np.random.randint(0, len(input_sequence)-1) random_seq = input_sequence[random_seq_index] index_2_word = dict(map(reversed, word_2_index.items())) word_sequence = [index_2_word[value]forvalueinrandom_seq] print(' '.join(word_sequence))

對於本文中的腳本,如下順序是隨機選擇的:

amenwhenthey did say god blesse vs lady consider itnotso deepely mac but wherefore couldnotpronounce amen had most needofblessingandamen stuckinmy throat lady these deeds mustnotbe thought after these wayes so it will make vs mad macb me thought heard voyce cry sleepnomore macbeth does murther sleepe the innocent sleepe sleepe that knits vp the rauel sleeueofcare the deathofeach dayes life sore labors bath balmeofhurt mindes great natures second course chiefe nourisherinlife feast lady what doe you meane

接下來,咱們將按照上述單詞順序輸出接下來的100個單詞:

foriinrange(100): int_sample = np.reshape(random_seq, (1, len(random_seq),1)) int_sample = int_sample / float(vocab_size) predicted_word_index = model.predict(int_sample, verbose=0) predicted_word_id = np.argmax(predicted_word_index) seq_in = [index_2_word[index]forindexinrandom_seq] word_sequence.append(index_2_word[ predicted_word_id]) random_seq.append(predicted_word_id) random_seq = random_seq[1:len(random_seq)]

word_sequence如今,變量包含咱們輸入的單詞序列以及接下來的100個預測單詞。該word_sequence變量包含列表形式的單詞序列。咱們能夠簡單地將列表中的單詞鏈接起來以得到最終的輸出序列,以下所示:

final_output =""forwordinword_sequence: final_output = final_output +" "+ word print(final_output)

這是最終輸出:

amenwhenthey did say god blesse vs lady consider itnotso deepely mac but wherefore couldnotpronounce amen had most needofblessingandamen stuckinmy throat lady these deeds mustnotbe thought after these wayes so it will make vs mad macb me thought heard voyce cry sleepnomore macbeth does murther sleepe the innocent sleepe sleepe that knits vp the rauel sleeueofcare the deathofeach dayes life sore labors bath balmeofhurt mindes great natures second course chiefe nourisherinlife feast lady what doe you meaneandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandandand

結論

在本文中,咱們看到了如何經過Python的Keras庫使用深度學習來建立文本生成模型。

相關文章
相關標籤/搜索