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

打印 上一主题 下一主题

主题 894|帖子 894|积分 2682

在当今数字化的时代,分析用户评论中的情绪倾向对于相识产物、服务的口碑等方面有着重要意义。而基于强盛的预训练语言模子如 Bert 来进行评论情绪分析,可以或许取得较好的结果。 在本次项目中,我们将展示如何利用 Python 语言联合transformers库,借助 Bert 模子实现对给定评论数据集的情绪分类任务。

  
  
一、数据集说明

数据集可以在Aitsuio平台下载,下载链接,格式如下:

每个数据有评论内容和后面的情绪分类,我们所要做的就是根据评论内容进行分类。
下载数据集后,可以得到拥有三个差别的数据集文件,分别是train.txt、dev.txt和test.txt,它们各自负担差别的脚色。train.txt用于训练模子,dev.txt作为开辟集(验证集)在训练过程中帮助我们评估模子在未见过的数据上的体现,进而辅助调整模子的超参数等,test.txt则用于最终测试模子的泛化能力。
  1. content: 酒店还是非常的不错,我预定的是套间,服务非常好,随叫随到,结帐非常快。顺便提一句,这个酒店三楼是一个高级KTV,里面的服务小姐非常的漂亮,有机会去看看。
  2. idtype: 2
复制代码
二、模子搭建

2.1 导包

起首,我们需要确保相关依靠库已经安装好,像transformers库用于方便地加载和利用 Bert 模子,torch库作为深度学习的基础框架(如果有 GPU 支持还能加快训练过程),以及datasets库辅助我们加载和处理数据集。如果未安装,直接pip安装即可。
  1. from transformers import BertTokenizer, BertForSequenceClassification
  2. from datasets import load_dataset
  3. import torch
  4. from torch.utils.data import DataLoader
  5. 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用于按批次加载数据。数据集加载代码如下:
  1. # 自定义数据集类,继承自torch.utils.data.Dataset
  2. class CommentDataset(torch.utils.data.Dataset):
  3.     def __init__(self, encodings, labels):
  4.         self.encodings = encodings
  5.         self.labels = labels
  6.     def __getitem__(self, idx):
  7.         item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
  8.         item['labels'] = torch.tensor(self.labels[idx])
  9.         return item
  10.     def __len__(self):
  11.         return len(self.labels)
  12. # 加载训练集数据
  13. train_data = []
  14. train_labels = []
  15. with open('Dataset/train.txt', 'r', encoding='utf-8') as f:
  16.     for line in f.readlines():
  17.         text, label = line.split('\t')
  18.         train_data.append(text)
  19.         train_labels.append(int(label))
  20. # 对训练集进行编码
  21. tokenizer = BertTokenizer.from_pretrained('/root/model/bert-base-chinese')
  22. train_encodings = tokenizer(train_data, truncation=True, padding=True)
  23. train_dataset = CommentDataset(train_encodings, train_labels)
  24. train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
  25. # 加载开发集数据
  26. dev_data = []
  27. dev_labels = []
  28. with open('Dataset/dev.txt', 'r', encoding='utf-8') as f:
  29.     for line in f.readlines():
  30.         text, label = line.split('\t')
  31.         dev_data.append(text)
  32.         dev_labels.append(int(label))
  33. # 对开发集进行编码
  34. dev_encodings = tokenizer(dev_data, truncation=True, padding=True)
  35. dev_dataset = CommentDataset(dev_encodings, dev_labels)
  36. dev_loader = DataLoader(dev_dataset, batch_size=8)
  37. # 加载测试集数据
  38. test_data = []
  39. test_labels = []
  40. with open('Dataset/test.txt', 'r', encoding='utf-8') as f:
  41.     for line in f.readlines():
  42.         text, label = line.split('\t')
  43.         test_data.append(text)
  44.         test_labels.append(int(label))
  45. # 对测试集进行编码
  46. test_encodings = tokenizer(test_data, truncation=True, padding=True)
  47. test_dataset = CommentDataset(test_encodings, test_labels)
  48. test_loader = DataLoader(test_dataset, batch_size=8)
复制代码
2.4 模子加载

利用BertForSequenceClassification一行下令即可加载模子。
  1. # 加载预训练的Bert模型用于序列分类,这里假设是二分类(0和1代表不同情感倾向),可以根据实际调整num_labels
  2. model = BertForSequenceClassification.from_pretrained('/root/model/bert-base-chinese', num_labels=len(idset))
复制代码
2.5 训练及评估

接下来定义一个train函数,一个val函数,一个test函数,分别对应三个文件,然后就可以开始训练和测试啦!
  1. # 训练函数
  2. def train():
  3.     device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  4.     model.to(device)
  5.     optimizer = torch.optim.AdamW(model.parameters(), lr=1e-5)
  6.     epochs = 3  # 可以根据实际调整训练轮数
  7.     for epoch in range(epochs):
  8.         model.train()
  9.         for batch in train_loader:
  10.             input_ids = batch['input_ids'].to(device)
  11.             attention_mask = batch['attention_mask'].to(device)
  12.             labels = batch['labels'].to(device)
  13.             outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
  14.             loss = outputs.loss
  15.             loss.backward()
  16.             optimizer.step()
  17.             optimizer.zero_grad()
  18.         print(f'Epoch {epoch + 1} completed')
  19.         # 在开发集上验证
  20.         validate()
  21. # 验证函数(在开发集上查看模型表现辅助调参)
  22. def validate():
  23.     device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  24.     model.eval()
  25.     correct = 0
  26.     total = 0
  27.     with torch.no_grad():
  28.         for batch in dev_loader:
  29.             input_ids = batch['input_ids'].to(device)
  30.             attention_mask = batch['attention_mask'].to(device)
  31.             labels = batch['labels'].to(device)
  32.             outputs = model(input_ids, attention_mask=attention_mask)
  33.             _, predicted = torch.max(outputs.logits, dim=1)
  34.             total += labels.size(0)
  35.             correct += (predicted == labels).sum().item()
  36.     print(f'Validation Accuracy: {correct / total}')
  37. # 评估函数
  38. def evaluate():
  39.     device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  40.     model.eval()
  41.     correct = 0
  42.     total = 0
  43.     with torch.no_grad():
  44.         for batch in test_loader:
  45.             input_ids = batch['input_ids'].to(device)
  46.             attention_mask = batch['attention_mask'].to(device)
  47.             labels = batch['labels'].to(device)
  48.             outputs = model(input_ids, attention_mask=attention_mask)
  49.             _, predicted = torch.max(outputs.logits, dim=1)
  50.             total += labels.size(0)
  51.             correct += (predicted == labels).sum().item()
  52.     print(f'Test Accuracy: {correct / total}')
  53. train()
  54. evaluate()
复制代码
2.6 训练结果

可以看到,在test上有94%的精确率,还是非常不错的!
  1. Epoch 1 completed
  2. Validation Accuracy: 0.9435662345874171
  3. Epoch 2 completed
  4. Validation Accuracy: 0.9521024343977237
  5. Epoch 3 completed
  6. Validation Accuracy: 0.9524185899462535
  7. Test Accuracy: 0.9485416172634574
复制代码
三、完整代码

完整代码如下,需要的小伙伴可以自己获取!
  1. 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
  2. from datasets import load_dataset
  3. import torch
  4. from torch.utils.data import DataLoader
  5. import numpy as np
  6. # 自定义数据集类,继承自torch.utils.data.Dataset
  7. class CommentDataset(torch.utils.data.Dataset):
  8.     def __init__(self, encodings, labels):
  9.         self.encodings = encodings
  10.         self.labels = labels
  11.     def __getitem__(self, idx):
  12.         item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
  13.         item['labels'] = torch.tensor(self.labels[idx])
  14.         return item
  15.     def __len__(self):
  16.         return len(self.labels)
  17. # 加载训练集数据
  18. train_data = []
  19. train_labels = []
  20. with open('Dataset/train.txt', 'r', encoding='utf-8') as f:
  21.     for line in f.readlines():
  22.         text, label = line.split('\t')
  23.         train_data.append(text)
  24.         train_labels.append(int(label))
  25. # 对训练集进行编码
  26. tokenizer = BertTokenizer.from_pretrained('/root/model/bert-base-chinese')
  27. train_encodings = tokenizer(train_data, truncation=True, padding=True)
  28. train_dataset = CommentDataset(train_encodings, train_labels)
  29. train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
  30. # 加载开发集数据
  31. dev_data = []
  32. dev_labels = []
  33. with open('Dataset/dev.txt', 'r', encoding='utf-8') as f:
  34.     for line in f.readlines():
  35.         text, label = line.split('\t')
  36.         dev_data.append(text)
  37.         dev_labels.append(int(label))
  38. # 对开发集进行编码
  39. dev_encodings = tokenizer(dev_data, truncation=True, padding=True)
  40. dev_dataset = CommentDataset(dev_encodings, dev_labels)
  41. dev_loader = DataLoader(dev_dataset, batch_size=8)
  42. # 加载测试集数据
  43. test_data = []
  44. test_labels = []
  45. with open('Dataset/test.txt', 'r', encoding='utf-8') as f:
  46.     for line in f.readlines():
  47.         text, label = line.split('\t')
  48.         test_data.append(text)
  49.         test_labels.append(int(label))
  50. # 对测试集进行编码
  51. test_encodings = tokenizer(test_data, truncation=True, padding=True)
  52. test_dataset = CommentDataset(test_encodings, test_labels)
  53. test_loader = DataLoader(test_dataset, batch_size=8)
  54. # 加载预训练的Bert模型用于序列分类,这里假设是二分类(0和1代表不同情感倾向),可以根据实际调整num_labels
  55. model = BertForSequenceClassification.from_pretrained('/root/model/bert-base-chinese', num_labels=len(idset))
  56. # 训练函数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()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

乌市泽哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表