前言
系列专栏:【深度学习:算法项目实战】✨︎
涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对抗网络、门控循环单元、长短期记忆、自然语言处理、深度强化学习、大型语言模型和迁移学习。
下一个单词预测是一个引人入胜的问题,它涉及开发一种模型,能够预测句子中给定单词序列之后最有可能出现的单词。这种预测模型利用算法和语言模式的力量来预测下一个单词,从而实现各种应用,如预测性键盘建议、写作辅助和内容生成。这就像在应用程序中内置了一个功能,可以在您输入或说话时建议下一个单词。下一个单词预测模型可用于信息应用、搜索引擎、虚拟助手和智能手机的自动更正功能等应用中。
在这项任务中,我们将使用一个文本数据集,该数据集基于以杰出侦探夏洛克-福尔摩斯为主角的著名系列丛书。该数据集由阿瑟-柯南-道尔爵士撰写的引人入胜的故事组成,让我们沉浸在惊心动魄的调查和雄辩的散文世界中。这些故事是丰富的文本数据源,使我们能够深入研究福尔摩斯世界中的语言模式和上下文关系。
本文的任务是开发一个强大的下一个单词预测模型,该模型可以准确预测给定单词序列之后最合适的单词。通过分析受福尔摩斯启发的数据集,该模型应能学习到支配单词进展的语言模式和关系。
要构建下一个单词预测模型:
- 首先收集各种文本文档数据集、
- 通过清理和标记化对数据进行预处理、
- 通过创建输入输出对来准备数据、
- 设计词嵌入等特征、
- 选择合适的模型,如 LSTM 或 GPT、
- 在数据集上训练模型,同时调整超参数、
- 通过试验不同的技术和架构来改进模型。
通过这种迭代过程,企业可以开发出准确、高效的下一个单词预测模型,并将其应用于各种应用中。
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
# Read the text file
with open('sherlock-holm.es_stories_plain-text_advs.txt', 'r', encoding='utf-8') as file:
text = file.read()
现在,让我们对文本进行标记化,创建一个词序列:
tokenizer = Tokenizer()
tokenizer.fit_on_texts([text])
total_words = len(tokenizer.word_index) + 1
在上述代码中,文本被标记化,这意味着文本被分割成单个单词或标记。创建的 “Tokenizer ”对象将处理标记化过程。调用标记化器的 fit_on_texts
方法,将 “文本 ”作为输入。该方法会分析文本并建立一个包含唯一单词的词汇表,同时为每个单词分配一个数字索引。然后,total_words
变量被赋值为单词索引的长度加一,代表文本中不同单词的总数。
现在,让我们通过将文本分割成词组序列并从序列中形成 n-gram 来创建输入输出对:
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
列表中。对文本中的所有行重复这一过程,生成多个输入-输出序列,用于训练下一个单词预测模型。
现在,让我们对输入序列进行等长填充:
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 数组,以便进一步处理。
现在,让我们将序列分为输入和输出:
X = input_sequences[:, :-1]
y = input_sequences[:, -1]
在上述代码中,输入序列被分成 “X ”和 “y ”两个数组,以创建用于训练下一个单词预测模型的输入和输出。"X "数组分配了 input_sequences
数组中除最后一列外所有行的值。这意味着 “X ”包含了每个序列中除最后一列外的所有词块,代表输入上下文。
另一方面,“y ”数组分配的是 input_sequences
数组中最后一列的值,它代表目标词或预测词。
现在,让我们将输出转换为 one-hot 编码向量:
y = np.array(tf.keras.utils.to_categorical(y, num_classes=total_words))
在上述代码中,我们将输出数组转换为适合训练模型的格式,其中每个目标词都表示为二进制向量。
神经网络
现在,让我们构建一个神经网络架构来训练模型:
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())
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
上面的代码定义了下一个单词预测模型的模型结构。创建的序列模型是一个线性层栈。添加到模型中的第一层是嵌入层,它负责将输入序列转换为固定大小的密集向量。它需要三个参数:
- total_words,表示词汇表中不同单词的总数;
- “100”,表示词嵌入的维度;
- 以及 “input_length”,指定输入序列的长度。
下一层是 LSTM 层,这是一种递归神经网络(RNN)层,用于捕捉数据中的顺序依赖关系。它有 150 个单元,这意味着它将学习 150 个内部表示或记忆单元。
最后,添加密集层,这是一个全连接层,用于生成输出预测。它有 “total_words ”单元,使用 softmax
激活函数将预测得分转换为概率,表示每个单词成为序列中下一个单词的可能性。
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=100, verbose=1, batch_size = 64,)
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 以显示训练过程。
模型评估
# evaluate the keras model
_, accuracy = model.evaluate(X, y)
print('Accuracy: %.2f' % (accuracy*100))
3010/3010 ━━━━━━━━━━━━━━━━━━━━ 17s 5ms/step - accuracy: 0.8882 - loss: 0.4568
Accuracy: 88.87
执行代码后,我们就可以使用模型生成下一个单词的预测结果了:
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)
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 编程语言构建下一个单词预测模型。