NLP项目实战——基于Bert模型的多情感评论分类(附数据集和源码)

在当今数字化的时代,分析用户评论中的情感倾向对于了解产品、服务的口碑等方面有着重要意义。而基于强大的预训练语言模型如 Bert 来进行评论情感分析,能够取得较好的效果。 在本次项目中,我们将展示如何利用 Python 语言结合transformers库,借助 Bert 模型实现对给定评论数据集的情感分类任务。
在这里插入图片描述

文章目录

  • 一、数据集说明
  • 二、模型搭建
    • 2.1 导包
    • 2.2 Bert模型下载
    • 2.3 数据集加载
    • 2.4 模型加载
    • 2.5 训练及评估
    • 2.6 训练结果
  • 三、完整代码

一、数据集说明

数据集可以在Aitsuio平台下载,下载链接,格式如下:
在这里插入图片描述
每个数据有评论内容和后面的情感分类,我们所要做的就是根据评论内容进行分类。

下载数据集后,可以得到拥有三个不同的数据集文件,分别是train.txt、dev.txt和test.txt,它们各自承担不同的角色。train.txt用于训练模型,dev.txt作为开发集(验证集)在训练过程中帮助我们评估模型在未见过的数据上的表现,进而辅助调整模型的超参数等,test.txt则用于最终测试模型的泛化能力。

content: 酒店还是非常的不错,我预定的是套间,服务非常好,随叫随到,结帐非常快。顺便提一句,这个酒店三楼是一个高级KTV,里面的服务小姐非常的漂亮,有机会去看看。
idtype: 2

二、模型搭建

2.1 导包

首先,我们需要确保相关依赖库已经安装好,像transformers库用于方便地加载和使用 Bert 模型,torch库作为深度学习的基础框架(如果有 GPU 支持还能加速训练过程),以及datasets库辅助我们加载和处理数据集。如果未安装,直接pip安装即可。

from transformers import BertTokenizer, BertForSequenceClassification
from datasets import load_dataset
import torch
from torch.utils.data import DataLoader
import numpy as np

2.2 Bert模型下载

所用到的模型是bert-base-chinese,可以在huggingface或者魔塔社区下载,如果不知道如何下载可以看我之前这篇博客,复制对应的地址即可。LLM/深度学习Linux常用指令与代码(进阶)
在这里插入图片描述

2.3 数据集加载

为了加载这些数据,需要自定义了一个名为CommentDataset的数据集类,它继承自torch.utils.data.Dataset,这个类负责将文本数据和对应的标签进行整合,方便后续被数据加载器(DataLoader)使用。
在具体的数据加载过程中,分别读取三个文件中的每一行数据,按照空格分割出评论内容和对应的情感标签(示例中假设标签是整数形式,比如 0 代表负面情感,1 代表正面情感等),然后利用 Bert 的tokenizer对文本进行编码,将文本转化为模型能够接受的输入格式(包括添加input_ids、attention_mask等),最终分别创建出对应的训练集、开发集和测试集的Dataset对象以及相应的DataLoader用于按批次加载数据。数据集加载代码如下:

# 自定义数据集类,继承自torch.utils.data.Dataset
class CommentDataset(torch.utils.data.Dataset):
    def __init__(self, encodings, labels):
        self.encodings = encodings
        self.labels = labels

    def __getitem__(self, idx):
        item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
        item['labels'] = torch.tensor(self.labels[idx])
        return item

    def __len__(self):
        return len(self.labels)

# 加载训练集数据
train_data = []
train_labels = []
with open('Dataset/train.txt', 'r', encoding='utf-8') as f:
    for line in f.readlines():
        text, label = line.split('\t')
        train_data.append(text)
        train_labels.append(int(label))

# 对训练集进行编码
tokenizer = BertTokenizer.from_pretrained('/root/model/bert-base-chinese')
train_encodings = tokenizer(train_data, truncation=True, padding=True)
train_dataset = CommentDataset(train_encodings, train_labels)
train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)

# 加载开发集数据
dev_data = []
dev_labels = []
with open('Dataset/dev.txt', 'r', encoding='utf-8') as f:
    for line in f.readlines():
        text, label = line.split('\t')
        dev_data.append(text)
        dev_labels.append(int(label))

# 对开发集进行编码
dev_encodings = tokenizer(dev_data, truncation=True, padding=True)
dev_dataset = CommentDataset(dev_encodings, dev_labels)
dev_loader = DataLoader(dev_dataset, batch_size=8)

# 加载测试集数据
test_data = []
test_labels = []
with open('Dataset/test.txt', 'r', encoding='utf-8') as f:
    for line in f.readlines():
        text, label = line.split('\t')
        test_data.append(text)
        test_labels.append(int(label))

# 对测试集进行编码
test_encodings = tokenizer(test_data, truncation=True, padding=True)
test_dataset = CommentDataset(test_encodings, test_labels)
test_loader = DataLoader(test_dataset, batch_size=8)

2.4 模型加载

利用BertForSequenceClassification一行命令即可加载模型。

# 加载预训练的Bert模型用于序列分类,这里假设是二分类(0和1代表不同情感倾向),可以根据实际调整num_labels
model = BertForSequenceClassification.from_pretrained('/root/model/bert-base-chinese', num_labels=len(idset))

2.5 训练及评估

接下来定义一个train函数,一个val函数,一个test函数,分别对应三个文件,然后就可以开始训练和测试啦!

# 训练函数
def train():
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.to(device)
    optimizer = torch.optim.AdamW(model.parameters(), lr=1e-5)
    epochs = 3  # 可以根据实际调整训练轮数
    for epoch in range(epochs):
        model.train()
        for batch in train_loader:
            input_ids = batch['input_ids'].to(device)
            attention_mask = batch['attention_mask'].to(device)
            labels = batch['labels'].to(device)
            outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
            loss = outputs.loss
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
        print(f'Epoch {epoch + 1} completed')
        # 在开发集上验证
        validate()

# 验证函数(在开发集上查看模型表现辅助调参)
def validate():
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for batch in dev_loader:
            input_ids = batch['input_ids'].to(device)
            attention_mask = batch['attention_mask'].to(device)
            labels = batch['labels'].to(device)
            outputs = model(input_ids, attention_mask=attention_mask)
            _, predicted = torch.max(outputs.logits, dim=1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print(f'Validation Accuracy: {correct / total}')

# 评估函数
def evaluate():
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for batch in test_loader:
            input_ids = batch['input_ids'].to(device)
            attention_mask = batch['attention_mask'].to(device)
            labels = batch['labels'].to(device)
            outputs = model(input_ids, attention_mask=attention_mask)
            _, predicted = torch.max(outputs.logits, dim=1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print(f'Test Accuracy: {correct / total}')

train()
evaluate()

2.6 训练结果

可以看到,在test上有94%的正确率,还是非常不错的!

Epoch 1 completed
Validation Accuracy: 0.9435662345874171
Epoch 2 completed
Validation Accuracy: 0.9521024343977237
Epoch 3 completed
Validation Accuracy: 0.9524185899462535
Test Accuracy: 0.9485416172634574

三、完整代码

完整代码如下,需要的小伙伴可以自己获取!

with open('Dataset/train.txt', 'r', encoding='utf-8') as f:
    train_data = f.read()
with open('Dataset/dev.txt', 'r', encoding='utf-8') as f:
    eval_data = f.read()
 
train_data = train_data.split('\n')
eval_data = eval_data.split('\n')
idset = set()
for data in train_data:
    idset.add(data.split('\t')[-1])
for data in eval_data:
    idset.add(data.split('\t')[-1])
from transformers import BertTokenizer, BertForSequenceClassification
from datasets import load_dataset
import torch
from torch.utils.data import DataLoader
import numpy as np
# 自定义数据集类,继承自torch.utils.data.Dataset
class CommentDataset(torch.utils.data.Dataset):
    def __init__(self, encodings, labels):
        self.encodings = encodings
        self.labels = labels

    def __getitem__(self, idx):
        item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
        item['labels'] = torch.tensor(self.labels[idx])
        return item

    def __len__(self):
        return len(self.labels)

# 加载训练集数据
train_data = []
train_labels = []
with open('Dataset/train.txt', 'r', encoding='utf-8') as f:
    for line in f.readlines():
        text, label = line.split('\t')
        train_data.append(text)
        train_labels.append(int(label))

# 对训练集进行编码
tokenizer = BertTokenizer.from_pretrained('/root/model/bert-base-chinese')
train_encodings = tokenizer(train_data, truncation=True, padding=True)
train_dataset = CommentDataset(train_encodings, train_labels)
train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)

# 加载开发集数据
dev_data = []
dev_labels = []
with open('Dataset/dev.txt', 'r', encoding='utf-8') as f:
    for line in f.readlines():
        text, label = line.split('\t')
        dev_data.append(text)
        dev_labels.append(int(label))

# 对开发集进行编码
dev_encodings = tokenizer(dev_data, truncation=True, padding=True)
dev_dataset = CommentDataset(dev_encodings, dev_labels)
dev_loader = DataLoader(dev_dataset, batch_size=8)

# 加载测试集数据
test_data = []
test_labels = []
with open('Dataset/test.txt', 'r', encoding='utf-8') as f:
    for line in f.readlines():
        text, label = line.split('\t')
        test_data.append(text)
        test_labels.append(int(label))

# 对测试集进行编码
test_encodings = tokenizer(test_data, truncation=True, padding=True)
test_dataset = CommentDataset(test_encodings, test_labels)
test_loader = DataLoader(test_dataset, batch_size=8)
# 加载预训练的Bert模型用于序列分类,这里假设是二分类(0和1代表不同情感倾向),可以根据实际调整num_labels
model = BertForSequenceClassification.from_pretrained('/root/model/bert-base-chinese', num_labels=len(idset))
# 训练函数
def train():
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.to(device)
    optimizer = torch.optim.AdamW(model.parameters(), lr=1e-5)
    epochs = 3  # 可以根据实际调整训练轮数
    for epoch in range(epochs):
        model.train()
        for batch in train_loader:
            input_ids = batch['input_ids'].to(device)
            attention_mask = batch['attention_mask'].to(device)
            labels = batch['labels'].to(device)
            outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
            loss = outputs.loss
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
        print(f'Epoch {epoch + 1} completed')
        # 在开发集上验证
        validate()

# 验证函数(在开发集上查看模型表现辅助调参)
def validate():
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for batch in dev_loader:
            input_ids = batch['input_ids'].to(device)
            attention_mask = batch['attention_mask'].to(device)
            labels = batch['labels'].to(device)
            outputs = model(input_ids, attention_mask=attention_mask)
            _, predicted = torch.max(outputs.logits, dim=1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print(f'Validation Accuracy: {correct / total}')

# 评估函数
def evaluate():
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for batch in test_loader:
            input_ids = batch['input_ids'].to(device)
            attention_mask = batch['attention_mask'].to(device)
            labels = batch['labels'].to(device)
            outputs = model(input_ids, attention_mask=attention_mask)
            _, predicted = torch.max(outputs.logits, dim=1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print(f'Test Accuracy: {correct / total}')

if __name__ == "__main__":
    train()
    evaluate()

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

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

相关文章

TAS测评倍智题库 | 益丰大药房2025年中高层测评BA商业推理测评真题考什么?

您好!您已被邀请参加360评估。您的评估与反馈将有助于被评估人更深入地了解个人情况,发现个人优势和潜在风险。请您秉持公正、开放的心态进行评估。请尽快完成评估,在此衷心感谢您的配合与支持! ​ 相关事宜: 请您在…

优秀的大模型会不会做坏事?

主要围绕大型语言模型(LLMs)在特定情境下可能出现的欺骗行为及相关研究展开,具体如下: 研究背景与核心发现:研究发现即使在用户无意激励的情况下,LLMs 也可能说谎,而能使用工具的模型更易被诱导…

fiscoBcos落盘加密介绍

落盘加密 落盘加密是在机构内部进行的,每个机构独立管理自己硬盘数据的安全。内网中,每个节点的硬盘数据是被加密的。所有加密数据的访问权限,通过Key Manager来管理。Key Manager是部署在机构内网内,专门管理节点硬盘数据访问秘…

完全二叉树的删除

(1)删除叶子节点 找到要删除的节点 targetNode找到要删除节点的父节点parent(父节点是否存在)要删除的节点是父节点的左子树还是右子树如果是左子树,则parent.leftnull;如果是右子树则parent.rightnull。 (…

ModuleNotFoundError: No module named ‘setuptools_rust‘ 解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【算法】时间复杂度以及O(N^2)的排序

目录 1.常数时间的操作 2.时间复杂度 2.1.以选择排序为例 2.2.O(n^2)从何而来 2.3.冒泡排序 2.3.1.抑或运算 2.4.插入排序 3.二分法 3.1.局部最小 4.递归 4.1.递归行为时间复杂度的估计 1.常数时间的操作 一个操作如果和样本的数据量无关,每次都是固定时…

uni app 写的 小游戏,文字拼图?文字拼写?不知道叫啥

从下方的偏旁部首中选在1--3个组成上面文章中的文字&#xff0c;完成的文字标红 不喜勿喷 《满江红》 其中用到了两个文件 strdata.json parameters.json 这两个文件太大 放到资源中了 资源文件 <template><view class"wenzi_page_main"><view c…

【杂记】qt

1、终端下载PySide6以转换文件格式&#xff1a;pip install PySide6 -i https://pypi.tuna.tsinghua.edu.cn/simple 命令提示符下载完毕后&#xff1a;powerShell &#xff1a;cd 跳转到文件对应地址 &#xff08;1、pyside6-uic.exe test.ui -o test.py #将Ui界面文件转换成…

宁德时代2025年Verify入职测评语言理解及数字推理真题SHL题库汇总、考情分析

宁德时代社招Verify入职测评对薪酬有着重要影响&#xff0c;其规定正确率达到80%才能顺利通过测评。这体现了公司对人才专业素养与能力的严格要求&#xff0c;旨在筛选出真正符合岗位需求的优秀人才。测评内容涵盖了专业知识、技能运用、逻辑思维等多方面&#xff0c;只有综合能…

Jenkins-持续集成、交付、构建、部署、测试

Jenkins-持续集成、交付、构建、部署、测试 一: Jenkins 介绍1> Jenkins 概念2> Jenkins 目的3> Jenkins 特性4> Jenkins 作用 二&#xff1a;Jenkins 版本三&#xff1a;DevOps流程简述1> 持续集成&#xff08;Continuous Integration&#xff0c;CI&#xff0…

Flink系统知识讲解之:如何识别反压的源头

Flink系统知识之&#xff1a;如何识别反压的源头 什么是反压 Ufuk Celebi 在一篇古老但仍然准确的文章中对此做了很好的解释。如果您不熟悉这个概念&#xff0c;强烈推荐您阅读这篇文章。如果想更深入、更低层次地了解该主题以及 Flink 网络协议栈的工作原理&#xff0c;这里有…

Go学习:多重赋值与匿名变量

1. 变量的多重赋值 1.1 基本语法格式 go语言中&#xff0c;可以将多个赋值语句 合并成 一句&#xff0c;比如&#xff1a; a : 10 b : 20 c : 30//a,b,c三个变量的赋值语句可以简练成以下格式a, b, c : 10, 20, 30 1.2 交换变量值 当需要交换两个变量的值时&#…

ArkUI-应用数据持久化

应用数据持久化&#xff0c;是指应用将内存中的数据通过文件或数据库的形式保存到设备上。内存中的数据形态通常是任意的数据结构或数据对象&#xff0c;存储介质上的数据形态可能是文本、数据库、二进制文件等。 HarmonyOS标准系统支持典型的存储数据形态&#xff0c;包括用户…

SOLID原则学习,开闭原则

文章目录 1. 定义2. 开闭原则的详细解释3. 实现开闭原则的方法4. 总结 1. 定义 开闭原则&#xff08;Open-Closed Principle&#xff0c;OCP&#xff09;是面向对象设计中的五大原则&#xff08;SOLID&#xff09;之一&#xff0c;由Bertrand Meyer提出。开闭原则的核心思想是…

西电-算法分析-研究生课程复习笔记

24年秋的应该是张老师最后一次用卷面考试&#xff0c;他说以后这节课的期末考试都是在OJ上刷题了张老师上课还挺有意思的&#xff0c;上完之后能学会独立地思考算法设计问题了。整节课都在强调规模压缩这个概念&#xff0c;考试也是考个人对这些的理解&#xff0c;还挺好玩的哈…

插入实体自增主键太长,mybatis-plaus自增主键

1、问题 spring-boot整合mybtais执行insert语句时&#xff0c;主键id为长文本数据。 2、分析问题 1)数据库主键是否自增 2&#xff09;数据库主键的种子值设置的多少 3、解决问题 1&#xff09;数据库主键设置的时自增 3&#xff09;种子值是1 所以排查是数据库的问题 4、继…

上海亚商投顾:沪指探底回升微涨 机器人概念股午后爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 市场全天探底回升&#xff0c;沪指盘中跌超1.6%&#xff0c;创业板指一度跌逾3%&#xff0c;午后集体拉升翻红…

基于深度学习算法的AI图像视觉检测

基于人工智能和深度学习方法的现代计算机视觉技术在过去10年里取得了显著进展。如今&#xff0c;它被广泛用于图像分类、人脸识别、图像中物体的识别等。那么什么是深度学习&#xff1f;深度学习是如何应用在视觉检测上的呢&#xff1f; 什么是深度学习&#xff1f; 深度学习是…

基于Spring Boot的海滨体育馆管理系统的设计与实现

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的海滨体育馆管理系统的设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 宠物医院…

深度学习每周学习总结R3(LSTM-火灾温度预测)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客R4中的内容&#xff0c;为了便于自己整理总结起名为R3&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 0. 总结1. LSTM介绍LSTM的基本组成部分如何理解与应用LSTM 2. 数据导入3. 数据…