基于长短期记忆网络 LSTM 的下一个单词预测

前言

系列专栏:【深度学习:算法项目实战】✨︎
涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对抗网络、门控循环单元、长短期记忆、自然语言处理、深度强化学习、大型语言模型和迁移学习。

下一个单词预测是一个引人入胜的问题,它涉及开发一种模型,能够预测句子中给定单词序列之后最有可能出现的单词。这种预测模型利用算法和语言模式的力量来预测下一个单词,从而实现各种应用,如预测性键盘建议、写作辅助和内容生成。这就像在应用程序中内置了一个功能,可以在您输入或说话时建议下一个单词。下一个单词预测模型可用于信息应用、搜索引擎、虚拟助手和智能手机的自动更正功能等应用中。

在这项任务中,我们将使用一个文本数据集,该数据集基于以杰出侦探夏洛克-福尔摩斯为主角的著名系列丛书。该数据集由阿瑟-柯南-道尔爵士撰写的引人入胜的故事组成,让我们沉浸在惊心动魄的调查和雄辩的散文世界中。这些故事是丰富的文本数据源,使我们能够深入研究福尔摩斯世界中的语言模式和上下文关系。

本文的任务是开发一个强大的下一个单词预测模型,该模型可以准确预测给定单词序列之后最合适的单词。通过分析受福尔摩斯启发的数据集,该模型应能学习到支配单词进展的语言模式和关系。

要构建下一个单词预测模型:

  1. 首先收集各种文本文档数据集、
  2. 通过清理和标记化对数据进行预处理、
  3. 通过创建输入输出对来准备数据、
  4. 设计词嵌入等特征、
  5. 选择合适的模型,如 LSTM 或 GPT、
  6. 在数据集上训练模型,同时调整超参数、
  7. 通过试验不同的技术和架构来改进模型。

通过这种迭代过程,企业可以开发出准确、高效的下一个单词预测模型,并将其应用于各种应用中。

python 复制代码
import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Embedding, LSTM, Dense
python 复制代码
# Read the text file
with open('sherlock-holm.es_stories_plain-text_advs.txt', 'r', encoding='utf-8') as file:
    text = file.read()

现在,让我们对文本进行标记化,创建一个词序列:

python 复制代码
tokenizer = Tokenizer()
tokenizer.fit_on_texts([text])
total_words = len(tokenizer.word_index) + 1

在上述代码中,文本被标记化,这意味着文本被分割成单个单词或标记。创建的 "Tokenizer "对象将处理标记化过程。调用标记化器的 fit_on_texts 方法,将 "文本 "作为输入。该方法会分析文本并建立一个包含唯一单词的词汇表,同时为每个单词分配一个数字索引。然后,total_words 变量被赋值为单词索引的长度加一,代表文本中不同单词的总数。

现在,让我们通过将文本分割成词组序列并从序列中形成 n-gram 来创建输入输出对:

python 复制代码
input_sequences = []
for line in text.split('\n'):
    token_list = tokenizer.texts_to_sequences([line])[0]
    for i in range(1, len(token_list)):
        n_gram_sequence = token_list[:i+1]
        input_sequences.append(n_gram_sequence)

在上述代码中,文本数据使用"\n "字符作为分隔符被分成几行。对于文本中的每一行,标记化器的 text_to_sequences 方法都会根据之前创建的词汇表将该行转换为数字标记序列。然后使用 for 循环对生成的标记列表进行迭代。每次迭代都会提取一个从标记列表开头到当前索引 "i "的标记子序列(或 n-gram)。

这个 n-gram 序列代表输入上下文,最后一个标记是目标词或预测词。然后,这个 n-gram 序列会被添加到 input_sequences 列表中。对文本中的所有行重复这一过程,生成多个输入-输出序列,用于训练下一个单词预测模型。

现在,让我们对输入序列进行等长填充:

python 复制代码
max_sequence_len = max([len(seq) for seq in input_sequences])
input_sequences = np.array(pad_sequences(input_sequences, maxlen=max_sequence_len, padding='pre'))

在上述代码中,输入序列被填充,以确保所有序列具有相同的长度。变量 max_sequence_len 被指定为所有输入序列的最大长度。pad_sequences 函数用于填充或截断输入序列,以匹配最大长度。

pad_sequences 函数接收 input_sequences 列表,将最大长度设置为 max_sequence_len,并使用 padding=pre 参数指定在每个序列的开头添加填充。最后,输入序列被转换成一个 numpy 数组,以便进一步处理。

现在,让我们将序列分为输入和输出:

python 复制代码
X = input_sequences[:, :-1]
y = input_sequences[:, -1]

在上述代码中,输入序列被分成 "X "和 "y "两个数组,以创建用于训练下一个单词预测模型的输入和输出。"X "数组分配了 input_sequences 数组中除最后一列外所有行的值。这意味着 "X "包含了每个序列中除最后一列外的所有词块,代表输入上下文。

另一方面,"y "数组分配的是 input_sequences 数组中最后一列的值,它代表目标词或预测词。

现在,让我们将输出转换为 one-hot 编码向量:

python 复制代码
y = np.array(tf.keras.utils.to_categorical(y, num_classes=total_words))

在上述代码中,我们将输出数组转换为适合训练模型的格式,其中每个目标词都表示为二进制向量。

神经网络

现在,让我们构建一个神经网络架构来训练模型:

python 复制代码
model = Sequential()
model.add(Input(shape=(max_sequence_len-1,)))
model.add(Embedding(total_words, 100,))
model.add(LSTM(150))
model.add(Dense(total_words, activation='softmax'))
print(model.summary())
python 复制代码
Model: "sequential"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ Layer (type)                         ┃ Output Shape                ┃         Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
│ embedding (Embedding)                │ (None, 17, 100)             │         820,000 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ lstm (LSTM)                          │ (None, 150)                 │         150,600 │
├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤
│ dense (Dense)                        │ (None, 8200)                │       1,238,200 │
└──────────────────────────────────────┴─────────────────────────────┴─────────────────┘
 Total params: 2,208,800 (8.43 MB)
 Trainable params: 2,208,800 (8.43 MB)
 Non-trainable params: 0 (0.00 B)
None

上面的代码定义了下一个单词预测模型的模型结构。创建的序列模型是一个线性层栈。添加到模型中的第一层是嵌入层,它负责将输入序列转换为固定大小的密集向量。它需要三个参数:

  1. total_words,表示词汇表中不同单词的总数;
  2. "100",表示词嵌入的维度;
  3. 以及 "input_length",指定输入序列的长度。

下一层是 LSTM 层,这是一种递归神经网络(RNN)层,用于捕捉数据中的顺序依赖关系。它有 150 个单元,这意味着它将学习 150 个内部表示或记忆单元。

最后,添加密集层,这是一个全连接层,用于生成输出预测。它有 "total_words "单元,使用 softmax 激活函数将预测得分转换为概率,表示每个单词成为序列中下一个单词的可能性。

python 复制代码
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=100, verbose=1, batch_size = 64,)
python 复制代码
Epoch 1/100
1505/1505 ━━━━━━━━━━━━━━━━━━━━ 30s 19ms/step - accuracy: 0.0561 - loss: 6.6592
Epoch 2/100
1505/1505 ━━━━━━━━━━━━━━━━━━━━ 28s 19ms/step - accuracy: 0.1005 - loss: 5.7390
Epoch 3/100
1505/1505 ━━━━━━━━━━━━━━━━━━━━ 28s 19ms/step - accuracy: 0.1305 - loss: 5.3347
Epoch 4/100
1505/1505 ━━━━━━━━━━━━━━━━━━━━ 28s 19ms/step - accuracy: 0.1495 - loss: 5.0435
Epoch 5/100
1505/1505 ━━━━━━━━━━━━━━━━━━━━ 29s 19ms/step - accuracy: 0.1625 - loss: 4.7998
...
Epoch 100/100
1505/1505 ━━━━━━━━━━━━━━━━━━━━ 31s 20ms/step - accuracy: 0.8825 - loss: 0.4746

在上述代码中,模型正在进行编译和训练。编译方法配置模型进行训练。损失参数设置为 categorical_crossentropy,这是多类分类问题常用的损失函数。优化器参数设置为 adam,这是一种在训练过程中调整学习率的优化算法。

度量参数设置为准确度,用于监测训练过程中的准确度。编译模型后,调用 "fit "方法对输入序列 "X "和相应的输出 "y "进行训练。epochs 参数用于指定训练过程在整个数据集上迭代的次数。verbose 参数设置为 1 以显示训练过程。

模型评估

python 复制代码
# evaluate the keras model
_, accuracy = model.evaluate(X, y)
print('Accuracy: %.2f' % (accuracy*100))
python 复制代码
3010/3010 ━━━━━━━━━━━━━━━━━━━━ 17s 5ms/step - accuracy: 0.8882 - loss: 0.4568
Accuracy: 88.87

执行代码后,我们就可以使用模型生成下一个单词的预测结果了:

python 复制代码
seed_text = "I will leave if they"
next_words = 3

for _ in range(next_words):
    token_list = tokenizer.texts_to_sequences([seed_text])[0]
    token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre')
    predicted = np.argmax(model.predict(token_list), axis=-1)
    output_word = ""
    for word, index in tokenizer.word_index.items():
        if index == predicted:
            output_word = word
            break
    seed_text += " " + output_word

print(seed_text)
python 复制代码
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 142ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 16ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 16ms/step
I will leave if they are going to

上述代码根据给定的种子文本生成下一个单词的预测结果。seed_text 变量保存初始文本。next_words 变量决定要生成的预测字数。在 for 循环中,seed_text将使用标记化器转换为标记序列。标记序列会进行填充,以符合最大序列长度。

模型通过调用带有填充标记序列的模型上的预测 方法来预测下一个单词。预测单词是通过使用 np.argmax 找到概率分数最高的单词得到的。然后,将预测的单词添加到 seed_text 中,并重复该过程以获得所需的 next_words 数量。最后,seed_text 将被打印出来,其中包含初始文本和生成的预测词。

这就是如何使用深度学习和 Python 编程语言构建下一个单词预测模型。

相关推荐
PeterClerk1 小时前
PCA算法降维代码示例
人工智能·算法·机器学习·pca
带带老表学爬虫1 小时前
2.opencv保存图片和摄像头读取
人工智能·opencv·计算机视觉
github_zwl1 小时前
昇思25天学习打卡营第6天|linchenfengxue
人工智能·学习·目标跟踪
hf2000122 小时前
实时智能全托管-云器Lakehouse重新定义多维数据分析
大数据·人工智能·数据分析
网恋褙骗八万2 小时前
pytorch跑手写体实验
人工智能·pytorch·python
沐光-NIE2 小时前
配置jupyter时出现问题?怎么办?
python·深度学习·jupyter
灵魂画师向阳2 小时前
AI绘画Stable Diffusion 超高分辨率扩图教程:ControlNet组件-Tile妙用,增强细节保持构图完整!
人工智能·ai作画·stable diffusion·aigc·ai绘画·ai教程·ai绘画教程
交换喜悲2 小时前
目标检测常用涨点方法:注意力机制小结(空间注意力、通道注意力、CBAM等)
开发语言·人工智能·深度学习·目标检测·计算机视觉·maven
2401_857439692 小时前
深度学习在目标检测中的革命性应用与进展
人工智能·深度学习·目标检测
pen-ai2 小时前
【深度学习】C++ onnx Yolov8 目标检测推理
c++·人工智能·深度学习·opencv·yolo·目标检测