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

前言

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

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

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

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

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

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

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

单词预测

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

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

  1. total_words,表示词汇表中不同单词的总数;
  2. “100”,表示词嵌入的维度;
  3. 以及 “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 编程语言构建下一个单词预测模型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/700012.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【精选研报】#2形态识别,均线的收敛与发散

下载地址https://pan.baidu.com/s/1L1wPR7kXCb-ZbrgwFKcIvg?pwd8888

leetcode 所有可能的路径(图的遍历:深度优先和广度优先)

leetcode 链接: 所有可能的路径 1 图的基本概念 1.1 有向图和无向图 左边是有向图,右边是无向图。对于无向图来说,图中的边没有方向,两个节点之间只可能存在一条边,比如 0 和 1 之间的边,因为是无向图&am…

成功解决IndexError: index 0 is out of bounds for axis 1 with size 0

成功解决IndexError: index 0 is out of bounds for axis 1 with size 0 🛠️ 成功解决IndexError: index 0 is out of bounds for axis 1 with size 0摘要引言正文内容(详细介绍)🤔 错误分析:为什么会发生IndexError&…

栈和队列优先级队列适配器原理

栈和队列接口函数 stack 栈接口函数 因为栈的结构限制,栈只能栈顶push和栈顶pop, 所以接口略少 queue 队列接口函数 队列只比栈多了一个接口:back 队列的front相当于栈的top 适配器 栈的类模板 其中第二个参数是Container, 且缺省参数为…

Linux操作系统学习:day02

内容来自:Linux介绍 视频推荐:[Linux基础入门教程-linux命令-vim-gcc/g -动态库/静态库 -makefile-gdb调试]( day02 5、Linux目录结构 操作系统文件结构的开始,只有一个单独的顶级目录结构,叫做根目录。所有一切都从“根”开始…

汇编:数组-寻址取数据

比例因子寻址: 比例因子寻址(也称为比例缩放索引寻址或基址加变址加比例因子寻址)是一种复杂的内存寻址方式,常用于数组和指针操作。它允许通过一个基址寄存器、一个变址寄存器和一个比例因子来计算内存地址。 语法 比例因子寻…

高清实拍类型视频素材去哪里找?高清实拍素材网站分享

在这篇文章中,我将为大家介绍一些高清实拍类型的视频素材资源,这些资源对于我们新媒体创作者来说至关重要。优质的视频素材能显著提升作品的吸引力,因此选择合适的视频素材平台非常关键。下面我将详细介绍几个非常实用的视频素材平台&#xf…

这才是打开Java面试的正确方式,金九银十互联网大厂Java面试八股来袭

前言 秋招过后招聘旺季就到了,不知道大家是否准备好了,面对金九银十的招聘旺季,如果没有精心准备那笔者认为那是对自己不负责任;就我们 Java 程序员来说,多数的公司总体上面试都是以自我介绍项目介绍项目细节/难点提问…

Java-Lambda表达式基本理解及使用

Lambda表达式基本理解及使用 背景Lambda 表达式语法函数式接口常见的函数式接口Function<T, R>Consumer<T>Supplier<T>Predicate<T>UnaryOperator<T>BinaryOperator<T> Lambda表达式的基本使用有返回值函数式接口无返回值函数式接口Lambda…

excel两个数据表格,怎样实现筛选的联动?

如图&#xff0c;想要通过处理器或者像素条件进行筛选&#xff0c;形成一个右边图2的对比表&#xff0c;如何实现实现联动显示呢&#xff1f; 这个在excel里可以借用数据透视表切片器来完成。步骤如下&#xff1a; 1.添加表 选中数据区域中任意一个单元格&#xff0c;点击 插…

Java--数组的声明和创建

1.首先必须声明数组变量&#xff0c;才能在程序中使用数组。下面是声明数组变量的语法&#xff1a; 首选的方法为Java的方法&#xff0c;另一种方法是由C或C引入过来的&#xff0c;日常使用首选Java的方法 dataType[] arrayRefVar; //首选的方法 或 dataType arrayRefVar[]…

多年不见,我美少女又回来了!

各位&#xff0c;可能很多人都不记得我了&#xff0c;上学的时候喜欢记学习笔记&#xff0c;好多学弟学妹们经常来我的博客看笔记&#xff0c;对于学习也有帮助。 时过境迁&#xff0c;生活中的琐事和繁忙的工作&#xff0c;真的自顾不暇… 还记得之前说要转型给大家分享内容运…

【算法与数据结构】【数组篇】【题6-题10】

系列文章 本人系列文章-CSDN博客https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5502 1.数组基本知识点 1.1概念 数组就是一个集合。数组会用一些名为索引的数字来标识每项数据在数组中的位置&#xff0c;且在大多数编程语言中&…

嵌入式系统概述

嵌入式系统是为了特定应用而专门构建的计算机系统&#xff0c;其嵌入式软件的架构设计与嵌入式系统硬件组成紧密相关。 1.嵌入式系统发展历程 嵌入式系统的发展大致经历了五个阶段&#xff1a; 第一阶段&#xff1a;单片微型计算机&#xff08;SCM&#xff09;&#xff0c;及…

鸿蒙开发文件管理:【@ohos.fileio (文件管理)】

文件管理 该模块提供文件存储管理能力&#xff0c;包括文件基本管理、文件目录管理、文件信息统计、文件流式读写等常用功能。 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 impor…

我要成为算法高手-双指针篇

目录 什么是双指针?问题1&#xff1a;移动零问题2&#xff1a;复写零问题3&#xff1a;快乐数问题4&#xff1a;盛最多水的容器问题5&#xff1a;有效三角形个数问题6&#xff1a;查找总价格和为目标值的两个商品(两数之和)问题7&#xff1a;三数之和问题8&#xff1a;四数之和…

【Affine / Perspective Transformation】

文章目录 仿射变换介绍仿射变换 python 实现——cv2.warpAffine透视变换透视变换 python 实现——cv2.warpPerspective牛刀小试各类变换的区别与联系仿射变换和单应性矩阵透视变换和单应性矩阵 仿射变换介绍 仿射变换&#xff08;Affine Transformation&#xff09;&#xff0…

鸿蒙轻内核A核源码分析系列四(2) 虚拟内存

本文我们来熟悉下OpenHarmony鸿蒙轻内核提供的虚拟内存&#xff08;Virtual memory&#xff09;管理模块。 本文中所涉及的源码&#xff0c;以OpenHarmony LiteOS-A内核为例&#xff0c;均可以在开源站点 https://gitee.com/openharmony/kernel_liteos_a 获取。如果涉及开发板…

基于微信小程序的“最多跑一次”警务信息管理系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;ssm 【…

Linux用户,用户组,所有者权限分配,sftp用户权限分配

注意以下命令执行需要在root用户下执行 tenant命令切换至root命令 sudo -do root 删除用户信息 1.不删除用户主目录 userdel user_name 2.删除用户主目录 userdel -r user_name usermod命令修改用户账户权限 更改用户名 sudo usermod -l newusername oldusername 更…