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

news2025/1/7 20:15:10

在当今数字化的时代,分析用户评论中的情感倾向对于了解产品、服务的口碑等方面有着重要意义。而基于强大的预训练语言模型如 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()

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

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

相关文章

各种数据库类型介绍

1.关系型数据库(Relational Databases, RDBMS) 关系型数据库是基于关系模型组织的数据库,其数据结构以表格的形式存在,表格之间通过外键等关系相互关联。它们支持复杂的SQL(Structured Query Language)查询…

创龙3588——debian根文件系统制作

文章目录 build.sh debian 执行流程build.sh源码流程 30-rootfs.sh源码流程 mk-rootfs-bullseys.sh源码流程 mk-sysroot.sh源码流程 mk-image.sh源码流程 post-build.sh 大致流程系统制作步骤 build.sh debian 执行流程 build.sh 源码 run_hooks() {DIR"$1"shiftf…

倾斜摄影相机在不动产确权登记和权籍调查中的应用

一、项目背景 1.1 项目背景 为贯彻落实中央、国务院关于实施乡村振兴战略、关于“扎实推进房地一体的农村集体建设用地和宅基地使用权确权登记颁证,完善农民闲置宅基地和闲置农房政策,探索宅基地所有权、资格权、使用权‘三权分置’”的要求&#xff0…

在K8S上部署OceanBase的最佳实践

在K8S上部署OceanBase的最佳实践 目录 1. 背景与选型 1.1 为什么选择OB1.2 为什么选择ob-operator实现OB on K8S 2. 部署实操 2.1 环境准备2.2 安装 ob-operator2.3 配置 OB 集群2.4 配置 OBProxy 集群2.5 Headless Service 和 CoreDNS 配置2.6 监控与运维 2.6.1 Promethues部…

【设计模式-1】软件设计模式概述

1. 软件设计模式的产生背景 “设计模式”这个术语最初并不是出现在软件设计中,而是被用于建筑领域的设计中。 1977 年,美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任克里斯托夫亚历山大(Christopher Alexander)在…

Nginx——反向代理(三/五)

目录 1.Nginx 反向代理1.1.Nginx 反向代理概述1.2.Nginx 反向代理的配置语法1.2.1.proxy_pass1.2.2.proxy_set_header1.2.3.proxy_redirect 1.3.Nginx 反向代理实战1.4.Nginx 的安全控制1.4.1.如何使用 SSL 对流量进行加密1.4.2.Nginx 添加 SSL 的支持1.4.3.Nginx 的 SSL 相关指…

win10 VS2019上libtorch库配置过程

win10 VS2019上libtorch库配置过程 0 引言1 获取libtorch2 在VS上配置使用libtorch库3 结语 0 引言 💻💻AI一下💻💻   libtorch库是一个用于深度学习的C库,是PyTorch的官方C前端。它提供了用于构建和训练深度学习模…

Windows 环境配置 HTTPS 服务实战

一、 环境准备 win10以上操作系统安装 Certbot申请阿里云\腾讯云域名安装 nginx 1.3以上版本 二、Certbot 安装及 SSL 证书生成 Certbot 是一个免费、开源工具,用于自动化在Web服务器上获取和更新SSL/TLS证书。它可以通过Let’s Encrypt服务获取免费的SSL/TLS证书…

【C++数据结构——图】最小生成树(头歌实践教学平台习题) 【合集】

目录😋 任务描述 相关知识 带权无向图 建立邻接矩阵 Prim算法 1. 算法基本概念 2. 算法背景与目标 3. 算法具体步骤 4. 算法结束条件与结果 测试说明 通关代码 测试结果 任务描述 本关任务:编写一个程序求图的最小生成树。 相关知识 为了完成…

11.认识异常

本节目标 1.异常概念与体系结构 2.异常的处理方式 3.异常的处理流程 4.自定义异常类 1.异常的概念与体系结构 1.1异常的概念 在Java中,将程序执行过程中发生的不正常行为称为异常,比如: 1.算术异常 System.out.println(10/0);//执行结果 Exception in thread "mai…

基于海思soc的智能产品开发(camera sensor的两种接口)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于嵌入式开发设备来说,除了图像显示,图像输入也是很重要的一部分。说到图像输入,就不得不提到camera。目前ca…

vulnhub靶场-potato(至获取shell)

arp-scan -l 扫描IP 使用御剑端口扫描扫描端口,扫到了80和7120两个端口,其中7120为ssh端口 使用dirb http://192.168.171.134 扫描目录 发现info.php 访问为phpinfo界面 访问192.168.171.134为一个大土豆,没什么用 所以我们从ssh入手 盲…

Flutter:邀请海报,Widget转图片,保存相册

记录下,把页面红色区域内的内容,转成图片后保存到相册的功能 依赖 # 生成二维码 qr_flutter: ^4.1.0 # 保存图片 image_gallery_saver_plus: ^3.0.5view import package:demo/common/index.dart; import package:ducafe_ui_core/ducafe_ui_core.dart; i…

Milvus×合邦电力:向量数据库如何提升15%电价预测精度

01. 全球能源市场化改革下的合邦电力 在全球能源转型和市场化改革的大背景下,电力交易市场正逐渐成为优化资源配置、提升系统效率的关键平台。电力交易通过市场化手段,促进了电力资源的有效分配,为电力行业的可持续发展提供了动力。 合邦电力…

网络层协议之IP数据包层分片随笔

1.全篇内容均在图中,如何分片以及分片举例细节拆解,见下图: 1.1分片公式: 上述公式中有关/8 再*8目的是为了使用8字节对齐,从而使的分片数据包均为8字节整数倍! 1.2.ip层数据包分片计算&图解

TDengine + MQTT :车联网时序数据库如何高效接入

现代新能源汽车,作为一种内部系统极为复杂的交通工具,配备了大量传感器、导航设备、应用软件,这些传感器产生的数据都需要上报到车联网平台当中。对于这些车辆的状态数据(如车速、发动机转速等)、位置数据(…

jenkins入门3 --执行一个小demo

1、新建视图 视图可以理解为是item的集合,这样可以将item分类。新建视频可以选择加入已有的item 2、新建item 1)输入任务名称、选择一个类型,常用的是第一个freestyle project 2)进行item相关配置,general 设置项目名字,描述,参数…

【Vue.js】监听器功能(EventListener)的实际应用【合集】

目录 🤔在实际开发过程中,我遇到了一个颇为棘手的小问题 😋解决这个小问题 问题出现的原因剖析 解决方法阐述 问题成功解决!​ 📖相关知识总结 基本概念 使用方法 实际应用场景 🤔在实际开发过程中…

【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】

目录😋 任务描述 相关知识 一、线性表的基本概念 二、初始化线性表 三、销毁线性表 四、判定是否为空表 五、求线性表的长度 六、输出线性表 七、求线性表中某个数据元素值 八、按元素值查找 九、插入数据元素 十、删除数据元素 测试说明 通关代码 测…

【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】

目录😋 任务描述 相关知识 一、根据键盘输入的一组有序数据建立顺序表 二、顺序表的输出 三、二分查找算法 测试说明 通关代码 测试结果 任务描述 本关任务:实现二分查找的算法。 相关知识 为了完成本关任务,你需要掌握: …