乐趣区

关于算法:用于NLP的Python使用Keras进行深度学习文本生成

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

文本生成是 NLP 的 最新利用 之一。深度学习技术已用于各种文本生成工作,例如写作诗歌,生成电影脚本甚至创作音乐。然而,在本文中,咱们将看到一个非常简单的文本生成示例,其中给定输出的单词字符串,咱们将预测下一个单词。咱们将应用莎士比亚驰名小说《麦克白》的原始文本,并依据给定的一系列输出单词来预测下一个单词。

实现本文之后,您将可能应用所选的数据集执行 文本生成

导入库和数据集

第一步是导入执行本文中的脚本所需的库以及数据集。以下代码导入所需的库:

import numpy as np
from keras.models import Sequential, load_model
from keras.layers import Dense, Embedding, LSTM, Dropout

下一步是下载数据集。咱们将应用 Python 的 NLTK 库下载数据集。

download('gutenberg')

您应该看到以下输入:

\['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'\]

该文件蕴含小说“Macbeth”的原始文本。要从此文件读取文本,能够应用类中的 raw 办法:

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

让咱们从数据集中 输入 前 500 个字符:

print(macbeth_text\[:500\])

这是输入:

Actus Primus. Scoena Prima.

Thunder and Lightning. Enter three Witches.

  1. When shall we three meet againe?
In Thunder, Lightning, or in Raine?
  2. When the Hurley-burley's done,
When the Battaile's lost, and wonne

   3. That will be ere the set of Sunne

   1. Where the place?
  2. Vpon the Heath

   3. There to meet with Macbeth

   1. I come, Gray-Malkin

   All. Padock calls anon: faire is foule, and foule is faire,
Houer through

您会看到文本蕴含许多特殊字符和数字。下一步是清理数据集。

数据预处理

要删除标点符号和特殊字符,咱们将定义一个名为的函数preprocess_text()

def preprocess_text(sen):
    # 删除标点符号和数字
    sentence = re.sub('\[^a-zA-Z\]', ' ', sen)
...

    return sentence.lower()

preprocess_text函数承受文本字符串作为参数,并以小写模式返回 清理后的 文本字符串。

当初让咱们清理文本,而后再次 输入 前 500 个字符:

macbeth\_text = preprocess\_text(macbeth_text)
macbeth_text\[:500\]

这是输入:

the tragedie of macbeth by william shakespeare actus primus scoena prima thunder and lightning enter three witches when shall we three meet againe in thunder lightning or in raine when the hurley burley done when the battaile lost and wonne that will be ere the set of sunne where the place vpon the heath there to meet with macbeth come gray malkin all padock calls anon faire is foule and foule is faire houer through the fogge and filthie ayre exeunt scena secunda alarum within enter king malcom

将单词转换为数字

深度学习模型基于统计算法。因而,为了应用深度学习模型,咱们须要将单词转换为数字。

在本文中,咱们将应用一种非常简单的办法,将单词转换为单个整数。在将单词转换为整数之前,咱们须要将文本标记为单个 单词

以下脚本标记咱们数据集中的文本,而后 输入 数据集中的单词总数以及数据集中的惟一单词总数:

from nltk.tokenize import word_tokenize

...

print('Total Words: %d' % n_words)
print('Unique Words: %d' % unique_words)

输入这样:

Total Words: 17250
Unique Words: 3436

咱们的文字总共有 17250 个单词,其中 3436 个单词是惟一的。要将标记化的单词转换为数字,能够应用模块中的 keras.preprocessing.text。您须要调用该fit_on_texts 办法并将其传递给单词列表。将创立一个字典,其中的键将代表单词,而整数将代表字典的相应值。

看上面的脚本:

from keras.preprocessing.text import Tokenizer
...

要拜访蕴含单词及其相应索引的字典,word_index能够应用 tokenizer 对象的属性:

vocab\_size = len(tokenizer.word\_index) + 1
word\_2\_index = tokenizer.word_index

如果您查看字典的长度,它将蕴含 3436 个单词,这是咱们数据集中惟一单词的总数。

当初让咱们从字典中 输入 第 500 个惟一单词及其整数值。

print(macbeth\_text\_words\[500\])
print(word\_2\_index\[macbeth\_text\_words\[500\]\])

这是输入:

comparisons
1456

批改数据形态

LSTM 承受 3 维格局的数据(样本数,工夫步数,每个工夫步的特色)。因为输入将是单个单词,因而输入的形态将是二维的(样本数,语料库中惟一词的数量)。

以下脚本批改了输出序列和相应输入的形态。

input_sequence = \[\]
output_words = \[\]
input\_seq\_length = 100

for i in range(0, n\_words - input\_seq_length , 1):
    in\_seq = macbeth\_text\_words\[i:i + input\_seq_length\]
...

在下面的脚本中,咱们申明两个空列表 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\]

让咱们通过将序列中的整数除以最大整数值来归一化输出序列。以下脚本还将输入转换为二维格局。

以下脚本输入输出和相应输入的形态。

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

输入:

X shape: (17150, 100, 1)
y shape: (17150, 3437)

训练模型

下一步是训练咱们的模型。对于应应用多少层和神经元来训练模型,没有硬性规定。

咱们将创立三个 LSTM 层,每个层具备 800 个神经元。最终将增加具备 1 个神经元的密集层,来预测下一个单词的索引,如下所示:

...
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 字典将返回属于被作为重点字典传入的索引词。

以下脚本随机抉择一个整数序列,而后输入相应的单词序列:

...
print(' '.join(word_sequence))

对于本文中的脚本,以下程序是随机抉择的:

amen when they did say god blesse vs lady consider it not so deepely mac but wherefore could not pronounce amen had most need of blessing and amen stuck in my throat lady these deeds must not be thought after these wayes so it will make vs mad macb me thought heard voyce cry sleep no more macbeth does murther sleepe the innocent sleepe sleepe that knits vp the rauel sleeue of care the death of each dayes life sore labors bath balme of hurt mindes great natures second course chiefe nourisher in life feast lady what doe you meane

接下来,咱们将依照上述单词程序输入接下来的 100 个单词:

for i in range(100):
    int\_sample = np.reshape(random\_seq, (1, len(random_seq), 1))
    int\_sample = int\_sample / float(vocab_size)

...

word_sequence当初,变量蕴含咱们输出的单词序列以及接下来的 100 个预测单词。该 word_sequence 变量蕴含列表模式的单词序列。咱们能够简略地将列表中的单词连接起来取得最终的输入序列,如下所示:

final_output = ""
for word in word_sequence:
...
print(final_output)

这是最终输入:

amen when they did say god blesse vs lady consider it not so deepely mac but wherefore could not pronounce amen had most need of blessing and amen stuck in my throat lady these deeds must not be thought after these wayes so it will make vs mad macb me thought heard voyce cry sleep no more macbeth does murther sleepe the innocent sleepe sleepe that knits vp the rauel sleeue of care the death of each dayes life sore labors bath balme of hurt mindes great natures second course chiefe nourisher in life feast lady what doe you meane and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and and

论断

在本文中,咱们看到了如何通过 Python 的 Keras 库应用深度学习来创立文本生成模型。

退出移动版