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…

为什么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。这种卫星可以…

超详细!一文搞定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…

玩转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…

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

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

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

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

GPU 进阶笔记(二):华为昇腾 910B GPU

大家读完觉得有意义记得关注和点赞&#xff01;&#xff01;&#xff01; 1 术语 1.1 与 NVIDIA 术语对应关系1.2 缩写2 产品与机器 2.1 GPU 产品2.2 训练机器 底座 CPU功耗操作系统2.3 性能3 实探&#xff1a;鲲鹏底座 8*910B GPU 主机 3.1 CPU3.2 网卡和网络3.3 GPU 信息 3.3…

Excel中一次查询返回多列

使用Excel或wps的时候&#xff0c;有时候需要一次查询返回多列内容&#xff0c;这种情况可以选择多次vlookup或者多次xlookup&#xff0c;但是这种做法费时费力不说&#xff0c;效率还有些低下&#xff0c;特别是要查询的列数过多时。我放了3种查询方法&#xff0c;效果图&…

爱思唯尔word模板

爱思唯尔word模板 有时候并不一定非得latex https://download.csdn.net/download/qq_38998213/90199214 参考文献书签链接

flask后端开发(3):html模板渲染

目录 渲染模板html模板获取路由参数 gitcode地址&#xff1a; https://gitcode.com/qq_43920838/flask_project.git 渲染模板 这样就能够通过html文件来渲染前端&#xff0c;而不是通过return了 html模板获取路由参数

python实战案例笔记:统计出数据中路劲下没有文件的文件夹

数据样例&#xff1a;&#x1f447;有如下excel数据 需求&#xff1a;有如下excel&#xff0c;a.xls&#xff0c;统计出路劲下没有文件的路劲 详细实现代码&#xff1a; import os from openpyxl import Workbook from datetime import datetimedef get_empty_dirs(paths):# …

GXUOJ-算法-第一次作业(整数划分、汉诺塔、排列问题、数塔问题)

1.整数划分 问题描述 GXUOJ | 整数划分 题解 #include<bits/stdc.h> using namespace std; const int N1010,mod1e97;int n; int f[N];int main(){cin>>n;f[0]1;for(int i1;i<n;i){for(int ji;j<n;j){f[j](f[j]f[j-i])%mod;}}cout<<f[n]; } 2.汉诺塔…

新服务器ubuntu系统相关操作

1、查看驱动:驱动版本535.216.01能够支持cuda12.2,下面直接使用默认安装的cuda。 2、赋予用户管理员权限。 首先有超级用户(root)权限来编辑 /etc/sudoers 文件,visudo 是一个命令,用于安全地编辑 /etc/sudoers 文件。运行: sudo visudo 在 visudo 编辑器中,找到类似…

docker-开源nocodb,使用已有数据库

使用已有数据库 创建本地数据库 数据库&#xff1a;nocodb 用户&#xff1a;nocodb 密码&#xff1a;xxxxxx修改docker-compose.yml 默认网关的 IP 地址是 172.17.0.1&#xff08;适用于 bridge 网络模式&#xff09;version: "2.1" services:nocodb:environment:…