NLP_神经概率语言模型(NPLM)

文章目录

  • NPLM的起源
  • NPLM的实现
    • 1.构建实验语料库
    • 2.生成NPLM训练数据
    • 3.定义NPLM
    • 4.实例化NPLM
    • 5.训练NPLM
    • 6.用NPLM预测新词
  • NPLM小结


NPLM的起源

在NPLM之前,传统的语言模型主要依赖于最基本的N-Gram技术,通过统计词汇的共现频率来计算词汇组合的概率。然而,这种方法在处理稀疏数据和长距离依剌时遇到了困难。

NPLM 是一种将词汇映射到连续向量空间的方法,其核心思想是利用神经网络学习词汇的概率分布。和N-Gram一样,NPLM 通过利用前N-1个词来预测第N个词,但是NPLM 构建了一个基于神经网络的语言模型。与传统的N-Gram 语言模型相比 NPLM 优化参数和预测第N个词的方法更加复杂。

得益于神经网络的强大表达能力,NPLM能够更有效地处理稀疏数据和长距离依赖问题。这意味着,NPLM在面对罕见词汇和捕捉距离较远的词之间的依赖关系时表现得更加出色,相较于传统的N-Gram语言模型有着显著的优势。

如下图所示,NPLM的结构包括3个主要部分:输入层、隐藏层和输出层。输入层将词汇映射到连续的词向量空间,隐藏层通过非线性激活函数学习词与词之间的复杂关系,输出层通过softmax函数产生下一个单词的概率分布。
在这里插入图片描述

NPLM的实现

流程如下:
在这里插入图片描述

1.构建实验语料库

# 构建一个非常简单的数据集
sentences = ["我 喜欢 玩具", "我 爱 爸爸", "我 讨厌 挨打"] 
# 将所有句子连接在一起,用空格分隔成多个词,再将重复的词去除,构建词汇表
word_list = list(set(" ".join(sentences).split())) 
# 创建一个字典,将每个词映射到一个唯一的索引
word_to_idx = {word: idx for idx, word in enumerate(word_list)} 
# 创建一个字典,将每个索引映射到对应的词
idx_to_word = {idx: word for idx, word in enumerate(word_list)} 
voc_size = len(word_list) # 计算词汇表的大小
print(' 词汇表:', word_to_idx) # 打印词汇到索引的映射字典
print(' 词汇表大小:', voc_size) # 打印词汇表大小

在这里插入图片描述

2.生成NPLM训练数据

# 构建批处理数据
import torch # 导入 PyTorch 库
import random # 导入 random 库
batch_size = 2 # 每批数据的大小
def make_batch():input_batch = []  # 定义输入批处理列表target_batch = []  # 定义目标批处理列表selected_sentences = random.sample(sentences, batch_size) # 随机选择句子for sen in selected_sentences:  # 遍历每个句子word = sen.split()  # 用空格将句子分隔成多个词# 将除最后一个词以外的所有词的索引作为输入input = [word_to_idx[n] for n in word[:-1]]  # 创建输入数据# 将最后一个词的索引作为目标target = word_to_idx[word[-1]]  # 创建目标数据input_batch.append(input)  # 将输入添加到输入批处理列表target_batch.append(target)  # 将目标添加到目标批处理列表input_batch = torch.LongTensor(input_batch) # 将输入数据转换为张量target_batch = torch.LongTensor(target_batch) # 将目标数据转换为张量return input_batch, target_batch  # 返回输入批处理和目标批处理数据
input_batch, target_batch = make_batch() # 生成批处理数据
print(" 输入批处理数据:",input_batch)  # 打印输入批处理数据
# 将输入批处理数据中的每个索引值转换为对应的原始词
input_words = []
for input_idx in input_batch:input_words.append([idx_to_word[idx.item()] for idx in input_idx])
print(" 输入批处理数据对应的原始词:",input_words)
print(" 目标批处理数据:",target_batch) # 打印目标批处理数据
# 将目标批处理数据中的每个索引值转换为对应的原始词
target_words = [idx_to_word[idx.item()] for idx in target_batch]
print(" 目标批处理数据对应的原始词:",target_words)

在这里插入图片描述

3.定义NPLM

import torch.nn as nn # 导入神经网络模块
# 定义神经概率语言模型(NPLM)
class NPLM(nn.Module):def __init__(self):super(NPLM, self).__init__() self.C = nn.Embedding(voc_size, embedding_size) # 定义一个词嵌入层# 第一个线性层,其输入大小为 n_step * embedding_size,输出大小为 n_hiddenself.linear1 = nn.Linear(n_step * embedding_size, n_hidden) # 第二个线性层,其输入大小为 n_hidden,输出大小为 voc_size,即词汇表大小self.linear2 = nn.Linear(n_hidden, voc_size) def forward(self, X):  # 定义前向传播过程# 输入数据 X 张量的形状为 [batch_size, n_step]X = self.C(X)  # 将 X 通过词嵌入层,形状变为 [batch_size, n_step, embedding_size]        X = X.view(-1, n_step * embedding_size) # 形状变为 [batch_size, n_step * embedding_size]# 通过第一个线性层并应用 ReLU 激活函数hidden = torch.tanh(self.linear1(X)) # hidden 张量形状为 [batch_size, n_hidden]# 通过第二个线性层得到输出 output = self.linear2(hidden) # output 形状为 [batch_size, voc_size]return output # 返回输出结果

这里定义了一个名为“NPLM”的神经概率语言模型类,它继承自PyTorch的 nn.Module。在这个类中,我们定义了词嵌入层和线性层,如下所示。

  • self.C:一个词嵌入层,用于将输入数据中的每个词转换为固定大小的向量表 3
    示。voc_size 表示词汇表大小,embedding_size 表示词嵌入的维度。
  • self.linear1:第一个线性层,不考虑批次的情况下输入大小为n_step * embedding_size,输出大小为n_hidden。n_step表示时间步数,即每个输入序列的长度;embedding_size表示词嵌入的维度;n_hidden 表示隐藏层的大小。
  • self.linear2:第二个线性层,不考虑批次的情况下输入大小为n_hidden,输出大小为voc_size。n_hidden表示隐藏层的大小,voc_size 表示词汇表大小。

在NPLM 类中,我们还定义了一个名为forward 的方法,用于实现模型的前向传播过程。在这个方法中,首先将输入数据通过词嵌入层self.C,然后X.view(-1, n_step * embedding_size)的目的是在词嵌入维度上展平张量,也就是把每个输入序列的词嵌入串联起来,形成一个大的向量。接着,将该张量传入第一个线性层 self. linear1并应用tanh函数,得到隐藏层的输出。最后,将隐藏层的输出传入第二个线性层 self.linear2,得到最终的输出结果。

4.实例化NPLM

n_step = 2 # 时间步数,表示每个输入序列的长度,也就是上下文长度 
n_hidden = 2 # 隐藏层大小
embedding_size = 2 # 词嵌入大小
model = NPLM() # 创建神经概率语言模型实例
print(' NPLM 模型结构:', model) # 打印模型的结构

在这里插入图片描述

5.训练NPLM

import torch.optim as optim # 导入优化器模块
criterion = nn.CrossEntropyLoss() # 定义损失函数为交叉熵损失
optimizer = optim.Adam(model.parameters(), lr=0.1) # 定义优化器为 Adam,学习率为 0.1
# 训练模型
for epoch in range(5000): # 设置训练迭代次数optimizer.zero_grad() # 清除优化器的梯度input_batch, target_batch = make_batch() # 创建输入和目标批处理数据output = model(input_batch) # 将输入数据传入模型,得到输出结果loss = criterion(output, target_batch) # 计算损失值if (epoch + 1) % 1000 == 0: # 每 1000 次迭代,打印损失值print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))loss.backward() # 反向传播计算梯度optimizer.step() # 更新模型参数

在这里插入图片描述

在训练过程中,首先定义损失函数(交叉熵损失函数)和优化器(Adam)。接下来,进行5000次迭代训练,每次迭代中,首先清除优化器的梯度,然后生成输入和目标批处理数据,并将它们转换为张量。接着,将输入数据传入模型,模型进行推理,得到预测值。随后,我们将预测值和目标数据进行比较,计算损失值,执行反向传播和参数更新。每1000 次迭代后,打印当前的损失值——可以看到损失值逐渐减少。

上面这个过程,是非常标准的PyTorch深度学习模型的训练过程。

6.用NPLM预测新词

# 进行预测
input_strs = [['我', '讨厌'], ['我', '喜欢']]  # 需要预测的输入序列
# 将输入序列转换为对应的索引
input_indices = [[word_to_idx[word] for word in seq] for seq in input_strs]
# 将输入序列的索引转换为张量
input_batch = torch.LongTensor(input_indices) 
# 对输入序列进行预测,取输出中概率最大的类别
predict = model(input_batch).data.max(1)[1]  
# 将预测结果的索引转换为对应的词
predict_strs = [idx_to_word[n.item()] for n in predict.squeeze()]  
for input_seq, pred in zip(input_strs, predict_strs):print(input_seq, '->', pred)  # 打印输入序列和预测结果

在这里插入图片描述

至此,一个完整的神经网络语言模型已经搭建完成。这个语言模型的输入是一个句子的前N-1个单词,输出是第N个单词。神经网络包括一个嵌入层,后面跟着一个使用 tanh 激活的线性层。程序使用交叉熵损失函数和Adam 优化器进行训练。最后的线性输出层给出词汇表中所有单词作为下一个单词的概率分布,我们通常选择概率最高的那个单词作为预测的下一个单词。此处在计算交叉熵损失时使用了softmax函数。

NPLM是一种较为简单的神经网络语言模型,它的历史意义在于开创性地把神经网络技术引入了 NLP领域。从此开始,深度学习就登上了 NLP 的舞台。而深度学习在NPLM中的优势主要体现在以下几方面。

  • 可以自动学习复杂的特征表示,减少了手工特征工程的需求。
  • 可以对大量数据进行高效的处理,使得模型能通过大规模语料库更好地学习词与词之间的语义和语法关系。
  • 具有强大的拟合能力,可以捕捉到语言数据中的复杂结构和模式。

具体到 NPLM 本身来说,它也存在一些明显的不足之处。

  • 模型结构简单:NPLM 使用了线性层和激活函数进行前向传播,这使得模型的表达能力受到限制。对于复杂的语言模式和长距离依赖关系,NPLM 可能无法捕捉到足够的信息。
  • 窗口大小固定:NPLM使用窗口大小固定的输入序列,这限制了模型处理不同长度上下文的能力。在实际应用中,语言模型通常需要处理长度可变的文本数据。
  • 缺乏长距离依赖捕捉:由于窗口大小固定,NPLM无法捕捉长距离依赖。在许多 NLP 任务中,捕捉长距离依赖关系对于理解句子结构和语义具有重要意义。
  • 训练效率低:NPLM的训练过程中,全连接层的输出大小等于词汇表的大小。当词汇表非常大时,计算量会变得非常大,导致训练效率降低。
  • 词汇表固定:NPLM 在训练时使用固定词汇表,这意味着模型无法处理训练集中未出现的词汇(未登录词)。这限制了模型在现实应用中的泛化能力。
  • 缺乏位置信息:NPLM不考虑输入序列中单词的顺序,这可能导致模型无法捕捉序列中单词之间的顺序关系。

为了解决这些问题,研究人员提出了一些更先进的神经网络语言模型,如循环神经网络、长短期记忆网络、门控循环单元(GRU)和Transformer等。这些模型能够捕捉长距离依赖,处理变长序列,同时具有更强的表达能力和泛化能力。下面我们就继续讲解 NLP 发展史上的另外一个里程碑——循环神经网络的使用。这里多说一句,其实LSTM和 GRU 都是广义上的循环神经网络。

NPLM小结

NPLM是一种基于神经网络的语言模型,用于估计语言序列的概率分布。它通过学习上下文中的词来预测下一个词,其主要思想是将单词转换为向量形式,并使用这些向量来训练一个神经网络。

优势:
在面对罕见词汇和捕捉距离较远的词之间的依赖关系时表现得更加出色,相较于传统的N-Gram语言模型有着显著的优势。

劣势:
窗口大小固定、缺乏长距离依赖捕捉、在训练时使用固定词汇表


学习的参考资料:
(1)书籍
利用Python进行数据分析
西瓜书
百面机器学习
机器学习实战
阿里云天池大赛赛题解析(机器学习篇)
白话机器学习中的数学
零基础学机器学习
图解机器学习算法

动手学深度学习(pytorch)

(2)机构
光环大数据
开课吧
极客时间
七月在线
深度之眼
贪心学院
拉勾教育
博学谷
慕课网
海贼宝藏

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【自然语言处理】微调 Fine-Tuning 各种经典方法的概念汇总

【自然语言处理】微调 Fine-Tuning 各种经典方法的概念汇总 前言请看此微调 Fine-TuningSFT 监督微调(Supervised Fine-Tuning)概念:监督学习,无监督学习,自监督学习,半监督学习,强化学习的区别…

Jetpack之RadionBtton、Switch、Checkbox组件介绍

Jetpack Compose系列(9) - RadionBtton、Switch、Checkbox组件介绍 RadioButton 跟View体系一样,Compose也有RadioButton单选按钮组件,遵从Material Design风格。 其构造函数如下: Composable fun RadioButton(selected: Boolean,onClick…

uniapp+uView 【详解】录音,自制音频播放器

效果预览 代码实现 <template><view class"btnListBox"><view class"audioBox" v-if"audioLength"><u-row><u-col span"2"><u--text aligncenter :text"currentTime"></u--text>…

YOLOv8改进 | 检测头篇 | 独创RFAHead检测头超分辨率重构检测头(适用Pose、分割、目标检测)

一、本文介绍 本文给大家带来的改进机制是RFAHead,该检测头为我独家全网首发,本文主要利用将空间注意力机制与卷积操作相结合的卷积RFAConv来优化检测头,其核心在于优化卷积核的工作方式,特别是在处理感受野内的空间特征时。RFAConv主要的优点就是增加模型的特征提取能力,…

arcgis各种版本下载

arcgic 下载&#xff01;&#xff01;&#xff01; ArcGIS是一款地理信息系统软件&#xff0c;由美国Esri公司开发。它提供了一系列完整的GIS功能&#xff0c;包括地图制作、空间数据管理、空间分析、空间信息整合、发布与共享等。ArcGIS是一个可扩展的GIS平台&#xff0c;提供…

恒创科技:服务器内存不足影响大吗?

​  服务器在为网站、应用程序和在线服务提供支持方面发挥着关键作用。这些服务器需要提供最佳性能&#xff0c;以确保正常无缝的用户体验&#xff0c;而RAM是显著影响服务器性能的关键配置之一。 RAM 是一种随机存取存储器&#xff0c;计算机和服务器使用它来临时存储正在使…

【AG32VF407】国产MCU+FPGA,更新官方固件解决8Mhz内部晶振不准,Verilog实测7.9Mhz!

视频讲解 [AG32VF407]国产MCUFPGA&#xff0c;更新官方固件解决8Mhz内部晶振不准&#xff0c;Verilog实测7.9Mhz&#xff01; 实验过程 之前出现的双路pll不同频率的测试中&#xff0c;提出了内部晶振输出不准的问题&#xff0c;和官方沟通后得到极大改善&#xff0c;方法如下…

探索Web API SpeechSynthesis:给你的网页增添声音

Web API SpeechSynthesis是一项强大的浏览器功能&#xff0c;它允许开发者将文本转换为语音&#xff0c;并通过浏览器播放出来。本文将深入探讨SpeechSynthesis的控制接口&#xff0c;包括其功能、用法和一个完整的JavaScript示例。 参考资料&#xff1a;SpeechSynthesis - Web…

Python程序设计 函数

简单函数 函数&#xff1a;就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。 函数的使用包含两个步骤&#xff1a; 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用&#xff0c;在开发程序时&#xff0c;使用…

2024年第九届信号与图像处理国际会议(ICSIP 2024)

2024第九届信号与图像处理国际会议&#xff08;ICSIP 2024&#xff09;将于2024年7月12-14日在中国南京召开。ICSIP每年召开一次&#xff0c;在过去的七年中吸引了1200多名与会者&#xff0c;是展示信号和图像处理领域最新进展的领先国际会议之一。本次将汇集来自亚太国家、北美…

LeetCode:13.罗马数字转整数

13. 罗马数字转整数 - 力扣&#xff08;LeetCode&#xff09; 目录 思路&#xff1a; 官解代码&#xff1a; 作者辣眼代码: 每日表情包&#xff1a; 思路&#xff1a; 思路已经很明了了&#xff0c;题目已经给出一般规则和特殊规则&#xff08;而且题目确保给定的是正确的…

活动图(Activity Diagram)

一、定义 动态图。显示人或对象的活动&#xff0c;其方式类似于流程图 二、构成 包含有&#xff1a; 初始节点(开始)最后一个节点(结束)活动转换判定(决策),同步条分岔或汇合泳道 1、 初始节点(开始) 实心圆表示初始节点 2、最后一个节点(结束) 圆圈内加一个实心圆来表…

C语言之字符逆序(牛客网)

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 字符逆序__牛客网 题目&#xff1a; 思路&#xff1a;既然有空格就不能用scanf函数来接收字符了。因为scanf函数遇到空格会停止读取。我们可以用get…

UE5 获得频谱让nigara随音乐律动

参考视频:UE - Niagara实现可视化音乐动态粒子效果 案例演示及教程_哔哩哔哩_bilibili 先创建一个Niagara 在Properties的Sim Target改为GPU,Calculate Bounds Mode改为Fixed模式 生成的数量改为1000 这里的BoxSize可以选择修改,具体作用是粒子初始生成的范围 Drag,阻力,用来限…

Java上(2024尚硅谷)

day01.[环境变量,HelloWorld] 1.会常用的dos命令 2.会安装java所需要的环境(jdk) 3.会配置java的环境变量 4.知道java开发三步骤 5.会java的入门程序(HelloWorld) 6.会三种注释方式 7.知道Java入门程序所需要注意的地方 8.知道println和print的区别第一章 Java概述 1.1 JavaS…

【自定义序列化器】⭐️通过继承JsonSerializer和实现WebMvcConfigurer类完成自定义序列化

目录 前言 解决方案 具体实现 一、自定义序列化器 二、两种方式指定作用域 1、注解 JsonSerialize() 2、实现自定义全局配置 WebMvcConfigurer 三、拓展 WebMvcConfigurer接口 章末 前言 小伙伴们大家好&#xff0c;上次做了自定义对象属性拷贝&#x…

Dijkstra算法(求最短路)

简介&#xff1a; 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的&#xff0c;因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法&#xff0c;解决的是有权图中最短路径问题。 特点&#xff1a; 迪杰斯特拉算法采用的是一种贪心策略&a…

【Java基础】关于Java基础的一些有趣的常识!

前言 今天看到了一篇文章&#xff0c;是关于茶余饭后的Java常识的一些有趣解答&#xff0c;我觉得写的很有趣很易懂&#xff0c;所以截取了其中我觉得比较有趣的问题分享给大家。原文&#xff1a;饭后茶余的java常识 - 知乎 (zhihu.com) 1. Java语言的特点有哪些&#xff1f; …

【并发编程】手写线程池阻塞队列

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程 ⛺️稳重求进&#xff0c;晒太阳 示意图 步骤1&#xff1a;自定义任务队列 变量定义 用Deque双端队列来承接任务用ReentrantLock 来做锁并声明两个条件变量 Condition fullWai…

网站不收录,与服务器不备案有关吗

随着互联网的快速发展&#xff0c;网站已经成为企业、个人和机构宣传和展示自己的重要平台。然而&#xff0c;许多网站在建设完成后却面临着不收录的问题&#xff0c;这给网站的管理者和拥有者带来了很大的困扰。其中&#xff0c;一些人认为&#xff0c;网站不收录的原因与服务…