作者|Fernando López 编译|VK 来源|Towards Data Science
“写作没有规定。有时它来得容易而且完美;有时就像在岩石上钻孔,然后用炸药把它炸开一样。”—欧内斯特·海明威
本博客的目的是解释如何通过实现基于LSTMs的强大体系结构来构建文本生成的端到端模型。
博客分为以下几个部分:
介绍
文本预处理
序列生成
模型体系结构
训练阶段
文本生成
完整代码请访问:https://github.com/FernandoLpz/Text-Generation-BiLSTM-PyTorch
介绍
多年来,人们提出了各种各样的建议来建模自然语言,但这是怎么回事呢?“建模自然语言”指的是什么?我们可以认为“建模自然语言”是指对构成语言的语义和语法进行推理,本质上是这样,但它更进一步。
目前,自然语言处理(NLP)领域通过不同的方法和技术处理不同的任务,即对语言进行推理、理解和建模。
自然语言处理(NLP)领域在过去的十年里发展非常迅速。许多模型都从不同的角度提出了解决不同NLP任务的方法。同样,最受欢迎的模型中的共同点是实施基于深度学习的模型。
如前所述,NLP领域解决了大量的问题,特别是在本博客中,我们将通过使用基于深度学习的模型来解决文本生成问题,例如循环神经网络LSTM和Bi-LSTM。同样,我们将使用当今最复杂的框架之一来开发深度学习模型,特别是我们将使用PyTorch的LSTMCell类来开发。
问题陈述
给定一个文本,神经网络将通过字符序列来学习给定文本的语义和句法。随后,将随机抽取一系列字符,并预测下一个字符。
文本预处理
首先,我们需要一个我们要处理的文本。有不同的资源可以在纯文本中找到不同的文本,我建议你看看Gutenberg项目(https://www.gutenberg.org/).。
在这个例子中,我将使用George Bird Grinnell的《Jack Among the Indians》这本书,你可以在这里找到:https://www.gutenberg.org/cache/epub/46205/pg46205.txt。所以,第一章的第一行是:
The train rushed down the hill, with a long shrieking whistle, and then began to go more and more slowly. Thomas had brushed Jack off and thanked him for the coin that he put in his hand, and with the bag in one hand and the stool in the other now went out onto the platform and down the steps, Jack closely following.
如你所见,文本包含大写、小写、换行符、标点符号等。建议你将文本调整为一种形式,使我们能够以更好的方式处理它,这主要降低我们将要开发的模型的复杂性。
我们要把每个字符转换成它的小写形式。另外,建议将文本作为一个字符列表来处理,也就是说,我们将使用一个字符列表,而不是使用“字符串”。将文本作为字符序列的目的是为了更好地处理生成的序列,这些序列将提供给模型(我们将在下一节中详细介绍)。
代码段1-预处理
def read_dataset(file):
letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',' ']
# 打开原始文件
with open(file, 'r') as f:
raw_text = f.readlines()
# 将每一行转换为小写
raw_text = [line.lower() for line in raw_text]
# 创建一个包含整个文本的字符串
text_string = ''
for line in raw_text:
text_string += line.strip()
# 。创建一个字符数组
text = list()
for char in text_string:
text.append(char)
# 去掉所有的符号,只保留字母
text = [char for char in text if char in letters]
return text
如我们所见,在第2行我们定义了要使用的字符,所有其他符号都将被丢弃,我们只保留“空白”符号。
在第6行和第10行中,我们读取原始文件并将其转换为小写形式。
在第14行和第19行的循环中,我们创建了一个代表整本书的字符串,并生成了一个字符列表。在第23行中,我们通过只保留第2行定义的字母来过滤文本列表。
因此,一旦文本被加载和预处理,例如:
text = "The train rushed down the hill."
可以得到这样的字符列表:
text = ['t','h','e',' ','t','r','a','i','n',' ','r','u','s','h','e','d',' ','d','o','w','n',
' ','t','h','e',' ','h','i','l','l']
我们已经有了全文作为字符列表。众所周知,我们不能将原始字符直接引入神经网络,我们需要一个数值表示,因此,我们需要将每个字符转换成一个数值表示。为此,我们将创建一个字典来帮助我们保存等价的“字符索引”和“索引字符”。
代码段2-字典创建