NLP自然语言处理——使用飞桨实现基于LSTM的情感分析

任务说明: 通过对电影评论历史数据分析,构建深度学习分类模型,最终完成对新的数据样本的识别分类。
任务要求: 运用神经网络算法,创建、训练、评估模型,完成对电影评论的情感分类任务。
数据集说明: IMDB数据集包含来自互联网的50000条严重两极分化的评论,该数据被分为用于训练的25000条评论和用于测试的25000条评论,训练集和测试集都包含50%的正面评价和50%的负面评价。

  • 情绪类别:正面/负面
  • 文件样本格式:标签 + 英文文本 + \n

一、模块导入

import numpy as np
import pandas as pd
import paddle
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import LSTM, Embedding, Dropout, Linear
import paddlenlp

二、加载数据

print('loading dataset...')
train_dataset =  paddle.text.datasets.Imdb(mode='train')  #导入训练集
test_dataset =  paddle.text.datasets.Imdb(mode='test')   #导入测试集
print('loading finished')

三、获取词表

word_dict = train_dataset.word_idx  # 获取数据集的词表
#pad设置, 设置填充词为<pad>,用于后续填充句子,以使批数据训练时句子长度保持一致
#添加'pad'字段到词表最后
word_dict['<pad>'] = len(word_dict) #查看词表前五个词和id
for k in list(word_dict)[:5]:print("{}:{}".format(k.decode('ASCII'), word_dict[k])) #将bytes转化成ASCII字符串,并查看id序号
print("...")
#打印后词表五个词和id号
for k in list(word_dict)[-5:]:#如果字典键的类型不是str,则进行转换print("{}:{}".format(k if isinstance(k, str) else k.decode('ASCII'), word_dict[k])) 
# 查看词表中单词的总个数
print("totally {} words".format(len(word_dict)))

四、构造数据结构


# 读取数据归一化处理
seq_len = 200  #句子的最大长度
def create_padded_dataset(dataset):pad_id = word_dict['<pad>']padded_sents = [] #存放句子id信息的列表valid_length=[]#计算句子转换成id后的长度labels = []  #存放标签id的列表for batch_id, data in enumerate(dataset):sent, label = data[0], data[1]  #获取  数据id和数据标签#对每一个句子长度小于200的进行padding填充,padded_sent = np.concatenate([sent[:seq_len], [pad_id] * (seq_len - len(sent))]).astype('int64')padded_sents.append(padded_sent) #存放句子idvalid_length.append(np.array(len(padded_sent),dtype="int64"))  labels.append(label)#存放标签return np.array(padded_sents),np.array(valid_length) ,np.array(labels)  # 对train、test数据进行实例化
#返回句子和标签
train_sents, train_valid_length,train_labels = create_padded_dataset(train_dataset)
test_sents,test_valid_length, test_labels = create_padded_dataset(test_dataset)# 查看数据大小及举例内容
print(train_sents.shape)
print(train_labels.shape)
print(train_valid_length.shape)
print(test_valid_length.shape)
print(test_sents.shape)
print(test_labels.shape)

(1) ny.concatenate() 详解

在数据处理和机器学习任务中,常常需要合并多个数组或矩阵。NumPy库中的 np.concatenate 函数是一个强大的工具,用于沿指定轴将多个数组合并成一个新的数组。详细介绍如下:

1.函数定义和参数

numpy.concatenate((a1, a2, ...), axis=0, out=None)

np.concatenate 函数接收以下参数:

(a1, a2, …): 数组序列,注意要用 () 或者 [] 符号括起来,否则会报错。
axis: 指定合并的轴,即沿着哪个维度进行合并。默认值为 0,表示沿着第一个维度进行合并。
out: 指定输出数组的可选参数。

2.合并一维数组

import numpy as np
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.concatenate((a, b))
print(c)

输出结果:

[1 2 3 4 5 6]

3.合并二维数组

import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
c = np.concatenate((a, b), axis=1#沿着轴1(列)进行合并)
print(c)

输出结果:

[[1 2 5 6][3 4 7 8]]

五、组装成mini-batch

batch_size = 64  #批数据数量
class IMDBDataset(paddle.io.Dataset):'''继承paddle.io.Dataset类进行封装数据'''def __init__(self, sents, valid_lengths,labels):self.sents = sentsself.valid_lengths=valid_lengthsself.labels = labels#根据给定索引获取数据集中的样本#在 paddle.io.DataLoader 中需要使用此函数通过下标获取样本def __getitem__(self, index):data = self.sents[index]valid_length=self.valid_lengths[index]label = self.labels[index]#返回句子id,标签idreturn data,valid_length, labeldef __len__(self):#返回句子个数return len(self.sents)train_dataset = IMDBDataset(train_sents,train_valid_length, train_labels)
test_dataset = IMDBDataset(test_sents,test_valid_length, test_labels)train_loader = paddle.io.DataLoader(train_dataset, #数据集return_list=True, #以list 形式返回shuffle=True,#是否打乱mini-batch的索引顺序batch_size=batch_size,#批数据的数量drop_last=True#去除末尾剩余数据)
test_loader = paddle.io.DataLoader(test_dataset, return_list=True,shuffle=True, batch_size=batch_size, drop_last=True)

如果批次大小(batch_size)增大,通常可以线性增加学习率(learning_rate)。经验法则是,当批次大小增加到原来的k倍时,学习率乘以 k。例如,如果批次大小从 32 增加到 64,学习率可以翻倍。
:以上经验法则仅适用于批次大小相对较小的时候。

六、定义LSTM网络

LSTM网络结构如下:

  • 第一层:word Embedding层;(文本向量化)
  • 第二层:seq2vec层;(序列学习)
  • 第三层:全连接层;(特征学习)
  • 第四层:输出层;(分类)
import paddlenlp as ppnlp
class LSTMModel (nn.Layer):#Layer首字母必须大写def __init__(self,vocab_size,#词表长度num_classes,#分类数emb_dim=128,padding_idx=0,lstm_hidden_size=198,direction='forward',lstm_layers=1,dropout_rate=0.0,pooling_type=None,fc_hidden_size=128):super().__init__()#文本向量化#首先将输入word_id 查表后映射成word embeddingself.embedder=nn.Embedding(num_embeddings=vocab_size,embedding_dim=emb_dim,padding_idx=padding_idx)#序列学习#将word_embedding经过LSTMEncoder变换到文本语义特征空间中self.lstm_encoder=ppnlp.seq2vec.LSTMEncoder(emb_dim,lstm_hidden_size,num_layers=lstm_layers,direction=direction,dropout=dropout_rate,pooling_type=pooling_type)#特征学习self.fc=nn.Linear(self.lstm_encoder.get_output_dim(),fc_hidden_size)#输出层self.output_layer=nn.Linear(fc_hidden_size,num_classes)def forward(self,text,seq_len):embedded_text=self.embedder(text)text_repr=self.lstm_encoder(embedded_text,sequence_length=seq_len)fc_out=paddle.tanh(self.fc(text_repr))logits=self.output_layer(fc_out)probs=F.softmax(logits,axis=-1)return probs

七、模型训练

(1) 定义lstm训练参数

epoch_num=4#迭代次数
batch_size=64#mini_batch样本数量
learning_rate=0.001#学习率(控制参数更新步长)
dropout_rate=0.2#随机让部分神经元失效的比率
embedding_size=256
hidden_size=256
num_layers=1
#词表大小
vocab_size = len(word_dict)
print(vocab_size)

(2) 实例化LSTM模型

model=LSTMModel(vocab_size,num_classes=2,emb_dim=embedding_size,lstm_layers=num_layers,direction='bidirectional',padding_idx=word_dict['<pad>']
)
#指定优化策略,更新模型参数
optimizer=paddle.optimizer.Adam(learning_rate=learning_rate,beta1=0.9,beta2=0.999,parameters=model.parameters())

(3) 定义训练函数

steps=[]
losses=[]
acc=[]
def train(model):model.train()global_step=0for epoch in range(epoch_num):for step,(sentences,valid_length,labels) in enumerate(train_loader):logits=model(sentences,valid_length)# 计算损失loss = F.cross_entropy(input=logits, label=labels, soft_label=False)loss = paddle.mean(loss)ACC = paddle.metric.accuracy(logits, labels)# 后向传播loss.backward()# 更新参数optimizer.step()# 清除梯度optimizer.clear_grad()global_step+=1if global_step % 50 == 0:# 记录当前步骤的loss变化情况steps.append(global_step)losses.append(loss.numpy()[0])acc.append(ACC.numpy()[0])print("epoch %d, step %d, loss %.3f,acc %.4f" % (epoch,global_step, loss.numpy()[0],ACC.numpy()[0]))
train(model)
# 保存模型,包含两部分:模型参数和优化器参数
model_name = "sentiment_classifier"
# 保存训练好的模型参数
paddle.save(model.state_dict(), "checkpoint/{}.pdparams".format(model_name))
# 保存优化器参数,方便后续模型继续训练
paddle.save(optimizer.state_dict(), "checkpoint/{}.pdopt".format(model_name))

八、模型评估

@paddle.no_grad()
#七、模型评估
def evaluate(model):# 开启模型测试模式,在该模式下,网络不会进行梯度更新model.eval()# 定义以上几个统计指标tp, tn, fp, fn = 0, 0, 0, 0total_steps=0for sentences,valid_lens, labels in test_loader:total_steps+=1# 获取模型对当前batch的输出结果logits = model(sentences,valid_lens)# 使用softmax进行归一化probs = F.softmax(logits)eval_acc=paddle.metric.accuracy(probs,labels)# 把输出结果转换为numpy array数组,比较预测结果和对应label之间的关系,并更新tp,tn,fp和fnprobs = probs.numpy()for i in range(len(probs)):# 当样本是的真实标签是正例if labels[i][0] == 1:# 模型预测是正例if probs[i][1] > probs[i][0]:tp += 1# 模型预测是负例else:fn += 1# 当样本的真实标签是负例else:# 模型预测是正例if probs[i][1] > probs[i][0]:fp += 1# 模型预测是负例else:tn += 1if total_steps % 100==0:print(eval_acc.numpy()[0])# 整体准确率accuracy = (tp + tn) / (tp + tn + fp + fn)# 输出最终评估的模型效果print("TP: {}\nFP: {}\nTN: {}\nFN: {}\n".format(tp, fp, tn, fn))print("Accuracy: %.4f" % accuracy)
# 加载训练好的模型进行预测,重新实例化一个模型,然后将训练好的模型参数加载到新模型里面
state_dict=paddle.load('checkpoint/sentiment_classifier.pdparams')
model.load_dict(state_dict)
# 评估模型
evaluate(model)

九、可视化

import matplotlib.pyplot as plt
# 可视化定义
def draw_process(title,color,steps,losses,label):plt.title(title, fontsize=24)    #设置图像标题,fontszie标题字号plt.xlabel("steps", fontsize=20)  #设置横轴标题,字号plt.ylabel(label, fontsize=20)   #设置竖轴标题,字号plt.plot(steps,losses, color=color,label=label)   #根据横轴(inters)、竖轴(data)数据,用指定的颜色(color)及指定的图像描述(label)绘图plt.legend() #显示labelplt.grid()  #显示网格plt.show()   #显示图像
# 可视化查看#绘制损失函数与迭代次数变化图象
draw_process("trainning loss","red",steps,losses,"trainning loss")
#绘制准确率值与迭代次数变化图象
draw_process("trainning acc","green",steps,acc,"trainning acc")
# 筛选出训练过程中损失最小和准确度最高的模型
lowest_loss_idx = losses.index(min(losses))
print(lowest_loss_idx)

损失函数
准确率

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

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

相关文章

LabVIEW条件配置对话框

条件配置对话框&#xff08;Configure Condition Dialog Box&#xff09; 要求&#xff1a;Base Development System 当右键单击**条件禁用结构&#xff08;Conditional Disable Structure&#xff09;**并选择以下选项时&#xff0c;会显示此对话框&#xff1a; Add Subdiagr…

K8S-LLM:用自然语言轻松操作 Kubernetes

在 Kubernetes (K8s) 的日常管理中&#xff0c;复杂的命令行操作常常让开发者感到头疼。无论是部署应用、管理资源还是调试问题&#xff0c;都需要记住大量的命令和参数。Kubernetes 作为容器编排的行业标准&#xff0c;其强大的功能伴随着陡峭的学习曲线和复杂的命令行操作。这…

为什么MoE推理效率更高:精简FFN

MoE全称是“混合专家”,它由多个专家网络和一个门控网络组成……整个MoE完全复用了Transformer的结构,只是将其中的FFN层替换成了MoE层。MoE层里的门控网络其实就是个专家分类器,每次根据输入Token生成专家的概率分布,然后选择排序靠前的K个专家进行Token处理,最后再将K个…

线段树例题题解

卫星覆盖&#xff08;NOI1997&#xff09; 题面&#xff1a; SERCOI&#xff08;Space-Earth Resource Cover-Observe lnstitute&#xff09; 是一个致力于利用卫星技术对空间和地球资源进行覆盖观测的组织。现在他们研制成功一种新型资源观测卫星 -SERCOI-308。这种卫星可以…

uni-app开发-识图小程序-主要功能以及首页实现

目录 一:功能介绍 二:代码实现 一:功能介绍 识图小程序首页主要是识图类型的展示列表,目前只有四种类型的图像识别,分别是车牌,发票,电表,身份证。可以分别识别车牌号码,身份证号码,发票号码,和电表度数。点击对应的类型图标会跳转到识图页面,每个分类上面展示该…

超详细!一文搞定PID!嵌入式STM32-PID位置环和速度环

本文目录 一、知识点1. PID是什么&#xff1f;2. 积分限幅--用于限制无限累加的积分项3. 输出值限幅--用于任何pid的输出4. PID工程 二、各类PID1. 位置式PID&#xff08;用于位置环&#xff09;&#xff08;1&#xff09;公式&#xff08;2&#xff09;代码使用代码 2. 增量式…

STM32 SPI读取SD卡

七个响应类型&#xff1a; R1 Response (Normal Response): R1响应是最基本的响应&#xff0c;包含一个字节的状态位&#xff0c;用于指示命令是否成功执行。常用。最高位为0。最低位为1表示是空闲状态。其他位是各种错误提示。 R1b Response (Normal with Busy): 类似于R1&a…

PostgreSQL的一主两从集群搭建部署 (两同步)

一、实验环境 虚拟机名IP身份简称keep-postgres12-node1192.168.122.87主节点node1keep-postgres12-node2192.168.122.89备节点node2keep-postgres12-node3192.168.122.90备节点node3 二、安装数据库 源码包方式&#xff08;主&#xff09; 1、创建用户 [rootkeep-postgre…

玩转OCR | 腾讯云智能结构化OCR初体验

随着数字化进程的加速&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术已逐渐成为提高企业生产力、优化工作流的重要工具。腾讯云智能结构化OCR凭借其领先的技术、广泛的应用场景和灵活的定制化能力&#xff0c;正在帮助各行业客户更高效地进行文档处理与数据提取。本…

STM32 高级 WIFi案例1:测试AT指令

需求描述 测试AT指令是否能够正常控制ESP32的wifi&#xff0c;比如重启、读取设备信息等。 思路&#xff1a; stm32通过串口usart2向ESP32发布命令。ESP32通过串口1返回信息。 配置&#xff1a; 第一步&#xff1a;对ESP32芯片烧录可以读取stm32命令的固件&#xff08;fac…

MySQL查看日志

目录 1. 日志 1.1 错误日志 1.2 二进制日志 1.2.1 介绍 1.2.2 格式 1.2.3 查看 1.2.4 删除 1.3 查询日志 1.4 慢查询日志 1. 日志 1.1 错误日志 错误日志是 MySQL 中最重要的日志之一&#xff0c;它记录了当 mysqld 启动和停止时&#xff0c;以及服务器在运行过 程…

Spring Boot教程之三十九: 使用 Maven 将 Spring Boot 应用程序 Docker 化

如何使用 Maven 将 Spring Boot 应用程序 Docker 化&#xff1f; Docker是一个开源容器化工具&#xff0c;用于在隔离环境中构建、运行和管理应用程序。它方便开发人员捆绑其软件、库和配置文件。Docker 有助于将一个容器与另一个容器隔离。在本文中&#xff0c;为了将Spring B…

机器人基础-自由度及其简单计算

机器人基础-自由度及其简单计算 1.自由度&#xff08;DOF&#xff09;2.自由度的计算3.自由度计算例题例1.例2.例3. 对于一个机器人的手腕&#xff0c;一般要求实现对空间坐标轴X、Y、Z的旋转运动&#xff0c;分别是翻/回转&#xff08;Roll&#xff09;、俯仰&#xff08;Pitc…

c# WaitSleepJoin状态的线程如何自动恢复

在 C# 中&#xff0c;线程的 ThreadState.WaitSleepJoin 状态表示线程当前处于等待、睡眠或加入&#xff08;比如等待锁、等待事件、或者调用 Thread.Sleep 等&#xff09;。要让一个处于 WaitSleepJoin 状态的线程恢复运行&#xff0c;必须唤醒它或让它不再被阻塞。这通常通过…

初学stm32---高级定时器输出n个pwm波

目录 高级定时器简介&#xff1a;(F1) 高级定时器框图 重复计数器特性 高级定时器输出指定个数PWM实验原理 高级定时器输出指定个数PWM实验配置步骤 相关HAL库函数介绍 关键结构体介绍 高级定时器简介&#xff1a;(F1) 1.高级定时器 &#xff1a;TIM1/TIM8 2.主要特性&…

【每日学点鸿蒙知识】Shape描述、全局loading组件、checkbox样式、H5监听键盘收起、弹窗不关闭

1、HarmonyOS 有没有xml描述的Shape&#xff1f; 有没有xml描述的Shape&#xff1f; 官方文档有对用的Shape的参考文档&#xff0c;参考链接&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-drawing-components-shape-V5 绘制组件的父…

完整的 FFmpeg 命令使用教程

FFmpeg 是一个开源的跨平台音视频处理工具&#xff0c;它能够处理几乎所有的视频、音频格式&#xff0c;并提供了强大的功能如格式转换、视频剪辑、合并、提取音频等。FFmpeg 通过命令行界面&#xff08;CLI&#xff09;操作&#xff0c;尽管有一些图形界面的前端工具&#xff…

Mono里运行C#脚本5—mono_file_map_open

前面介绍了mono_jit_init初始化,这个函数非常长,要理解起来还是比较困难。因此改变另外一种方式,先从底层的函数开始,再慢慢来探索mono的底层实现,以及它的实现原理,运行的细节。 Mono要运行exe文件,这里是运行test-embed.exe文件,那么就得认识这个文件,解释这个文件的…

【MySQL】踩坑笔记——保存带有换行符等特殊字符的数据,需要进行转义保存

问题描述 从DBeaver中导出了部分业务数据的 insert sql&#xff0c;明明在开发、测试环境都可以一把执行通过&#xff0c;却在预发环境执行前的语法检查失败了&#xff0c;提示有SQL语法错误。 这条SQL长这样&#xff0c;default_sql是要在odps上执行的sql语句&#xff0c;提…

matlab中的cell

在MATLAB中&#xff0c;cell 是一种非常重要的数据类型&#xff0c;它能够存储不同类型和大小的数据&#xff0c;这使得它非常灵活&#xff0c;适用于处理复杂的数据结构。 1. 基本介绍 cell 类型的变量可以存储不同类型的数据&#xff0c;如数值、字符、结构体、甚至其他的 …