用于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库使用深度学习来建立文本生成模型。

相关文章
相关标签/搜索