使用RNN完成IMDB电影评论情感分析

使用RNN完成IMDB电影评论情感分析

    • 任务描述
    • 一、环境设置
    • 二、数据准备
    • 2.1 参数设置
    • 2.2 用padding的方式对齐数据
    • 2.3 用Dataset与DataLoader加载
    • 三、模型配置
    • 四、模型训练
    • 五、模型评估
    • 六、模型预测

任务描述

本示例教程演示如何在IMDB数据集上使用RNN网络完成文本分类的任务。IMDB数据集包含对电影评论进行正向和负向标注的数据,共有25000条文本数据作为训练集,25000条文本数据作为测试集。数据集的官方地址为:IMDB Dataset

在这里插入图片描述

一、环境设置

本示例基于飞桨开源框架2.0版本。

import paddle
import numpy as np
import matplotlib.pyplot as plt
import paddle.nn as nn

print(paddle.__version__)  # 查看当前版本

# cpu/gpu环境选择,在 paddle.set_device() 输入对应运行设备。
device = paddle.set_device('gpu')

2.0.1

二、数据准备

由于IMDB是NLP领域中常见的数据集,飞桨框架将其内置,路径为paddle.text.datasets.Imdb。通过mode参数可以控制训练集与测试集。

print('loading dataset...')
train_dataset = paddle.text.datasets.Imdb(mode='train')
test_dataset = paddle.text.datasets.Imdb(mode='test')
print('loading finished')

构建了训练集与测试集后,可以通过word_idx获取数据集的词表。

word_dict = train_dataset.word_idx  # 获取数据集的词表

# add a pad token to the dict for later padding the sequence
word_dict['<pad>'] = len(word_dict)

for k in list(word_dict)[:5]:
    print("{}:{}".format(k.decode('ASCII'), word_dict[k]))

print("...")

for k in list(word_dict)[-5:]:
    print("{}:{}".format(k if isinstance(k, str) else k.decode('ASCII'), word_dict[k]))

print("totally {} words".format(len(word_dict)))

2.1 参数设置

在这里设置词表大小、embedding大小、batch_size等参数。

vocab_size = len(word_dict) + 1
print(vocab_size)
emb_size = 256
seq_len = 200
batch_size = 32
epochs = 2
pad_id = word_dict['<pad>']

classes = ['negative', 'positive']

# 生成句子列表
def ids_to_str(ids):
    words = []
    for k in ids:
        w = list(word_dict)[k]
        words.append(w if isinstance(w, str) else w.decode('ASCII'))
    return " ".join(words)

2.2 用padding的方式对齐数据

文本数据中,每一句话的长度都是不一样的,为了方便后续的神经网络的计算,通常使用padding的方式对齐数据。

# 读取数据归一化处理
def create_padded_dataset(dataset):
    padded_sents = []
    labels = []
    for batch_id, data in enumerate(dataset):
        sent, label = data[0], data[1]
        padded_sent = np.concatenate([sent[:seq_len], [pad_id] * (seq_len - len(sent))]).astype('int32')
        padded_sents.append(padded_sent)
        labels.append(label)
    return np.array(padded_sents), np.array(labels)

# 对train、test数据进行实例化
train_sents, train_labels = create_padded_dataset(train_dataset)
test_sents, test_labels = create_padded_dataset(test_dataset)

# 查看数据大小及举例内容
print(train_sents.shape)
print(train_labels.shape)
print(test_sents.shape)
print(test_labels.shape)

for sent in train_sents[:3]:
    print(ids_to_str(sent))

2.3 用Dataset与DataLoader加载

将前面准备好的训练集与测试集用DatasetDataLoader封装后,完成数据的加载。

class IMDBDataset(paddle.io.Dataset):
    '''
    继承paddle.io.Dataset类进行封装数据
    '''
    def __init__(self, sents, labels):
        self.sents = sents
        self.labels = labels
    
    def __getitem__(self, index):
        data = self.sents[index]
        label = self.labels[index]

        return data, label

    def __len__(self):
        return len(self.sents)
    
train_dataset = IMDBDataset(train_sents, train_labels)
test_dataset = IMDBDataset(test_sents, test_labels)

train_loader = paddle.io.DataLoader(train_dataset, return_list=True,
                                    shuffle=True, 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)

三、模型配置

本示例中使用一个序列特性的RNN网络,在查找到每个词对应的embedding后,取平均作为一个句子的表示。然后用Linear进行线性变换,同时使用Dropout防止过拟合。

class MyRNN(paddle.nn.Layer):
    def __init__(self):
        super(MyRNN, self).__init__()
        self.embedding = nn.Embedding(vocab_size, 256)
        self.rnn = nn.SimpleRNN(256, 256, num_layers=2, direction='forward',dropout=0.5)
        self.linear = nn.Linear(in_features=256*2, out_features=2)
        self.dropout = nn.Dropout(0.5)
    
    def forward(self, inputs):
        emb = self.dropout(self.embedding(inputs))
        output, hidden = self.rnn(emb)
        hidden = paddle.concat((hidden[-2,:,:], hidden[-1,:,:]), axis = 1)
        hidden = self.dropout(hidden)
        return self.linear(hidden) 

四、模型训练

# 可视化定义
def draw_process(title, color, iters, data, label):
    plt.title(title, fontsize=24)
    plt.xlabel("iter", fontsize=20)
    plt.ylabel(label, fontsize=20)
    plt.plot(iters, data, color=color, label=label) 
    plt.legend()
    plt.grid()
    plt.show()

# 对模型进行封装
def train(model):
    model.train()
    opt = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
    steps = 0
    Iters, total_loss, total_acc = [], [], []

    for epoch in range(epochs):
        for batch_id, data in enumerate(train_loader):
            steps +=

 1
            sent = data[0]
            label = data[1]
            
            logits = model(sent)
            loss = paddle.nn.functional.cross_entropy(logits, label)
            acc = paddle.metric.accuracy(logits, label)

            if batch_id % 500 == 0:  # 500个epoch输出一次结果
                Iters.append(steps)
                total_loss.append(loss.numpy()[0])
                total_acc.append(acc.numpy()[0])

                print("epoch: {}, batch_id: {}, loss is: {}".format(epoch, batch_id, loss.numpy()))
            
            loss.backward()
            opt.step()
            opt.clear_grad()

        # evaluate model after one epoch
        model.eval()
        accuracies = []
        losses = []
        
        for batch_id, data in enumerate(test_loader):
            sent = data[0]
            label = data[1]

            logits = model(sent)
            loss = paddle.nn.functional.cross_entropy(logits, label)
            acc = paddle.metric.accuracy(logits, label)
            
            accuracies.append(acc.numpy())
            losses.append(loss.numpy())
        
        avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)

        print("[validation] accuracy: {}, loss: {}".format(avg_acc, avg_loss))
        
        model.train()

        # 保存模型
        paddle.save(model.state_dict(), str(epoch) + "_model_final.pdparams")
    
    # 可视化查看
    draw_process("training loss", "red", Iters, total_loss, "training loss")
    draw_process("training acc", "green", Iters, total_acc, "training acc")
        
model = MyRNN()
train(model)

五、模型评估

model_state_dict = paddle.load('1_model_final.pdparams')  # 导入模型
model = MyRNN()
model.set_state_dict(model_state_dict) 
model.eval()
accuracies = []
losses = []

for batch_id, data in enumerate(test_loader):
    sent = data[0]
    label = data[1]

    logits = model(sent)
    loss = paddle.nn.functional.cross_entropy(logits, label)
    acc = paddle.metric.accuracy(logits, label)
    
    accuracies.append(acc.numpy())
    losses.append(loss.numpy())

avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)
print("[validation] accuracy: {}, loss: {}".format(avg_acc, avg_loss))

六、模型预测

def ids_to_str(ids):
    words = []
    for k in ids:
        w = list(word_dict)[k]
        words.append(w if isinstance(w, str) else w.decode('UTF-8'))
    return " ".join(words)

label_map = {0: "negative", 1: "positive"}

# 导入模型
model_state_dict = paddle.load('1_model_final.pdparams')
model = MyRNN()
model.set_state_dict(model_state_dict) 
model.eval()

for batch_id, data in enumerate(test_loader):
    sent = data[0]
    results = model(sent)

    predictions = []
    for probs in results:
        # 映射分类label
        idx = np.argmax(probs)
        labels = label_map[idx]
        predictions.append(labels)
    
    for i, pre in enumerate(predictions):
        print(' 数据: {} \n 情感: {}'.format(ids_to_str(sent[0]), pre))
        break
    break

以上是使用RNN完成IMDB电影评论情感分析的示例。通过搭建RNN网络,对文本数据进行预处理、模型训练和评估,最终实现了对电影评论情感的分类。在实际应用中,可以根据需求调整网络结构和超参数,提高模型性能。

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

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

相关文章

react native中使用tailwind并配置自动补全

使用的第三方库是tailwind-react-native-classnames&#xff0c;同类的也有tailwind-rn&#xff0c;但是我更喜欢前者官方demo&#xff1a; import { View, Text } from react-native; import tw from twrnc;const MyComponent () > (<View style{twp-4 android:pt-2 b…

51-12 多模态论文串讲—BLIP 论文精读

视觉语言预训练VLP模型最近在各种多模态下游任务上获得了巨大的成功&#xff0c;目前还有两个主要局限性: (1) 模型角度: 大多数方法要么采用encoder模型&#xff0c;要么采用encoder-decoder模型。然而&#xff0c;基于编码器的模型不太容易直接转换到文本生成任务&#xff0…

爬虫之牛刀小试(四):爬取B站番剧的简介

今天爬取的是b站。 如何爬取b站中的番剧呢&#xff1f; 首先我们来到番剧索引中&#xff0c;随便点开一部动漫&#xff0c;检查代码。 每个作品对应一个链接: https://www.bilibili.com/bangumi/play/ss…&#xff08;ss后面的数字称为ss号&#xff09; 发现关于动漫的信息…

HTML--超链接

超链接 作用&#xff1a;点击跳转到相应位置 a标签 语法&#xff1a; <a href"链接地址">文本或图片</a>范例&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"/><title>跳转到百度</t…

程序员如何弯道超车?周末有奇效

作为一名程序员&#xff0c;不断提升自己的技能和知识是至关重要的。然而&#xff0c;在繁忙的工作日常中&#xff0c;很难有足够的时间和精力来学习新技术或深入研究。因此&#xff0c;周末成为了一个理想的时机&#xff0c;可以专注于个人发展和技能提升。所以程序员如何利用…

部署Tomcat及其负载均衡

简介 在前面已经学习了Nginx服务器的安装配置&#xff0c;本章主要采用案例课的形式介绍Tomcat及NginxTomcat负载均衡群集。Tomcat案例首先介绍其应用场景&#xff0c;然后重点介绍Tomcat的安装配置&#xff0c;NginxTomcat负载均衡群集案例是应用于生产环境下的一套可靠的Web站…

006集 正则表达式 re 应用实例—python基础入门实例

正则表达式指预先定义好一个 “ 字符串模板 ” &#xff0c;通过这个 “ 字符串模 板” 可以匹配、查找和替换那些匹配 “ 字符串模板 ” 的字符串。 Python的中 re 模块&#xff0c;主要是用来处理正则表达式&#xff0c;还可以利用 re 模块通过正则表达式来进行网页数据的爬取…

NUS CS1101S:SICP JavaScript 描述:三、模块化、对象和状态

原文&#xff1a;3 Modularity, Objects, and State 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 变化中安宁 &#xff08;即使它在变化&#xff0c;它仍然保持不变。&#xff09; ——赫拉克利特 变化越大&#xff0c;越是相同。 ——阿方斯卡尔 前面的章节介绍了构…

C++学习笔记——友元、嵌套类、异常

目录 一、友元 一个使用友元的示例代码 输出结果 二、嵌套类 一个使用嵌套类的示例代码 输出结果 三、异常 一个使用异常处理的示例代码 输出结果 四、结论 五、使用它们的注意事项 上一篇文章链接&#xff1a; C中的继承和模板是非常强大和灵活的特性&#xff0c;它…

C++学习笔记——标准模板库

目录 一、简介 二、STL概述 2.1STL是什么&#xff1f; 2.2STL的优势 三、容器&#xff08;Containers&#xff09; 3.1序列式容器&#xff08;Sequence Containers&#xff09; 3.2关联式容器&#xff08;Associative Containers&#xff09; 3.3容器适配器&#xff08;…

轻松批量重命名不同路径文件:从1到N的单独编号指南

在处理大量文件时&#xff0c;有时要批量重命名这些文件。整理、归档或是进行其他类型的处理。但不同的文件可能位于不同的路径下&#xff0c;增加了批量重命名的复杂性。下面来看云炫文件管理器如何批量重命名不同路径下的文件&#xff0c;从1到N单独编号的方法。 不同路径文件…

考研经验总结——目录

文章目录 一、写作顺序二、个人情况说明三、读评论四、一些小牢骚五、一些注意事项&#xff08;持续更新&#xff09; 一、写作顺序 我将准备从三个阶段开始介绍吧 考研前考研中考研后&#xff08;也就是现在我的这种情况&#xff09; 考研前我会分为&#xff1a;数学、专业…

三轴加速度计LIS2DW12开发(3)----检测活动和静止状态

e2studio开发三轴加速度计LIS2DW12.3--检测活动和静止状态 概述视频教学样品申请源码下载新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置UART配置UART属性配置设置e2studio堆栈e2studio的重定向printf设置R_SCI_UART_Open()函数原型回调函数user_uart_callback ()…

vue3+vite开发生产环境区分

.env.development VITE_APP_TITLE本地.env.production VITE_APP_TITLE生产-ts文件中应用 console.log(import.meta.env.VITE_APP_TITLE)在html中应用&#xff0c;需要安装 html 模板插件 pnpm add vite-plugin-html -Dvite.config.ts中 import { createHtmlPlugin } from v…

python|切片

切片的语法格式 object[start_index:end_index:step] &#xff08;1&#xff09;step步长&#xff1a;有正负&#xff0c;正表示正着走&#xff0c;负表示负着走&#xff0c;步长的绝对值代表一步走的距离。 &#xff08;其中&#xff0c;在深度学习中卷积也有步长的说法&…

从比特币、以太坊生态,到AI与新公链复兴,谁将接棒2024年的主流叙事?

2023年10月份至今&#xff0c;现货比特币ETF一直都是促使市场反弹的核心叙事之一&#xff0c;如今靴子终于落地&#xff0c;那在ETF预期尘埃落定的大背景下&#xff0c;接下来的加密市场有哪些赛道值得关注&#xff1f; 泛比特币生态 2023年比特币生态浪潮中&#xff0c;OKX等赢…

什么是数通技术?以太网交换机在数通技术中的精要

什么是数通技术&#xff1f; 数通技术是指数字通信技术&#xff0c;它涵盖了数字信号处理、数据传输、网络通信等领域。通信工程师在数通技术中负责设计、建设和维护数字通信系统&#xff0c;以实现可靠、高效的信息传输。这涉及到数字信号的编解码、调制解调、数据压缩、网络…

【论文解读】SiamMAE:用于从视频中学习视觉对应关系的 MAE 简单扩展

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://siam-mae-video.github.io/resources/paper.pdf 项目主页&#xff1a;https://siam-mae-video.github.io/ 1.背景 时间是视觉学习背景下的一个特殊维度&#xff0c;它提供了一…

QT上位机开发(加密和解密)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 加密和解密是我们在软件开发中经常遇到的一种情形。最早的时候&#xff0c;加密是用在军事上面。现在由于各个行业、各个公司之间的竞争也非常激烈…

Kafka的安装、管理和配置

Kafka的安装、管理和配置 1.Kafka安装 官网: https://kafka.apache.org/downloads 下载安装包,我这里下载的是https://archive.apache.org/dist/kafka/3.3.1/kafka_2.13-3.3.1.tgz Kafka是Java生态圈下的一员&#xff0c;用Scala编写&#xff0c;运行在Java虚拟机上&#xf…