当前位置: 首页 > news >正文

项目实战之评论情感分析模型——基于Bert(含任务头)

目录

一、项目流程

1.1 加载预训练模型Bert

1.2 数据预处理

1.3 模型定义

1.4 模型训练

1.5 模型预测

二、总结


BERT 是谷歌于 2018 年提出的基于 Transformer 编码器结构的预训练语言模型。本文基于 BERT 架构,完成从预处理、微调训练到效果评估的全流程实验,经过多轮迭代优化,模型在情感分析任务上精确率达到98.7%,相比 LSTM 模型精确率提高108%

github项目地址:zhanghong203/bert_based_emotion_analysis at master

LSTM项目地址:zhanghong203/emotion_analyse_lm: 基于LSTM的情感分析模型


一、项目流程

实验配置:

显卡: NVIDIA GeForce RTX 3050 LAPTOP GP

模型:google-bert/bert-base-chinese · Hugging Face

数据:评论情感分析数据集

1.1 加载预训练模型Bert

Bert模型 通过官方链接或者代码方式下载:

from transformers import AutoTokenizer, AutoModelForMaskedLM tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese") model = AutoModelForMaskedLM.from_pretrained("bert-base-chinese")

默认huggingface安装目录 ~/.cache/huggingface/hub,可以通过配置环境变量修改

完成Bert模型加载后,通过from_pretrained方法可以从huggingface缓存中读取,同时也可以把模型放置在项目目录下,通过读取绝对路径方式加载。

关于from_pretrained()方法,详细介绍参考链接

from_pretrained 做了啥_from pretrained-CSDN博客


1.2 数据预处理

该过程主要完成数据清洗、对接Bert输入的任务。数据清洗过滤无用列,去除不符合的行。

# 过滤数据 dataset = dataset.remove_columns(['cat']) dataset = dataset.filter(lambda x: x['review'] is not None) dataset = dataset.cast_column('label', ClassLabel(names=['negative', 'positive']))

Bert一般接收参数:(input_ids, token_type_ids,attention_mask,Optional [labels])

def batch_encode(batch): inputs = tokenizer(batch['review'], truncation=True, padding='max_length', max_length=config.MAX_LENGTH) inputs['labels'] = batch['label'] return inputs dataset_dict = dataset_dict.map(batch_encode, batched=True, remove_columns=['review', 'label'])

调用tokenizer()获取前三个字段,为了保证批处理,需要做填充和截断操作。针对带句子分类任务头的Bert还需要labels字段。在后续过程中,为了方便解构,提前将label字段转化成labels,后续添加任务头,不需要再做预处理。

tokenizer方法参考链接


1.3 模型定义

首先,明确设计的任务是对评论进行情感分析,属于二分类任务。通过Bert前向传播,即通过12层隐藏层,只需要将最后一层last_hidden_state(batch_size, sequence_length, hidden_size)(Bert模型第一个token蕴含的向量信息是整个句子信息)接一个线性层。默认hidden_size是768,线性层输出维度设为1。

def forward(self, input_ids, attention_mask, token_type_ids): output = self.bert(input_ids, attention_mask, token_type_ids) last_hidden_state = output.last_hidden_state cls_hidden_state = last_hidden_state[:, 0, :] output = self.linear(cls_hidden_state).squeeze(-1) return output

Bert输出结构参考链接


1.4 模型训练

对于不带任务头的Bert,传入参数不需要携带labels,并且在进行训练时,需要再多一步计算损失;然而针对句子分类任务的Bert,输出包含loss字段。

# 含任务头 model = AutoModelForSequenceClassification.from_pretrained('google-bert/bert-base-chinese').to(device)

训练代码如下:

def train_one_epoch(model, dataloader, loss_fn, optimizer, device): total_loss = 0 model.train() for batch in tqdm(dataloader, desc='训练'): inputs = {k: v.to(device) for k, v in batch.items()} labels = inputs.pop('labels').to(dtype=torch.float) outputs = model(**inputs) loss = loss_fn(outputs, labels) loss.backward() optimizer.step() optimizer.zero_grad() total_loss += loss.item() return total_loss / len(dataloader) def train(): # 1.设备 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') print(device) # 2.数据 dataloader = get_loader() # 3.分词器 tokenizer = AutoTokenizer.from_pretrained('google-bert/bert-base-chinese') # 4.模型 model = ReviewAnalyzeModel().to(device) # 5.损失函数 loss_fn = torch.nn.BCEWithLogitsLoss() # 6.优化器 optimizer = torch.optim.Adam(model.parameters(), lr=config.LEARNING_RATE) # train best_loss = float('inf') for epoch in range(config.EPOCHS): print(f'Epoch: {epoch + 1}') loss = train_one_epoch(model, dataloader, loss_fn, optimizer, device) print(f'Loss: {loss:.4f}') # 保存模型 if loss < best_loss: best_loss = loss torch.save(model.state_dict(), config.MODELS_DIR / 'best.pt') print("保存模型")

BertForSequenceClassification模型介绍


1.5 模型预测

1.3小节中的模型,是通过一个线性层得到一个结果,通过sigmoid映射到[0,1];含任务头的Bert模型,输出包含一个logit字段((batch_size, config.num_labels))在预测阶段,logit的形状是(1, 2),可以使用argmax完成标签映射。

# 含任务头 def predict_batch(model, inputs): model.eval() with torch.no_grad(): output = model(**inputs) logits = output.logits # (batch_size, config.num_labels) result = torch.argmax(logits, dim=1) return result.tolist() ------------------------------------------- # 不含任务头 def predict_batch(model, inputs): model.eval() with torch.no_grad(): output = model(**inputs) # output.shape (batch_size) batch_result = torch.sigmoid(output) return batch_result.tolist()

二、总结

本文基于Bert完成从数据预处理到模型预测的全流程,在项目过程中免不了Bert文档的查看,笔者在每个小节都添加了相关API,便于读者理解。此外,下载Bert以及训练有一些小问题没有列举出来,比如访问huggingface超时、GPU显存利用率过高训练效率很低等问题。上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章!

http://www.jsqmd.com/news/603661/

相关文章:

  • 基于51单片机的扫地小车设计与实现:寻迹避障、智能往返清扫功能详解
  • 涨薪技术|Prometheus中配置Alertmanager
  • openpilot技术实战指南:从问题诊断到解决方案的系统方法论
  • Spring Boot 性能优化最佳实践:构建高性能应用
  • Zabbix监控Docker化部署避坑指南:从镜像版本选择到安全加固的完整配置
  • 别再傻傻分不清!Quectel RX500U 5G模组的‘网卡模式’和‘路由模式’到底怎么选?
  • Uni-App水印相机避坑指南:解决canvas绘制白屏、iOS拍照失败和权限获取的那些坑
  • 什么是埋点测试,app埋点测试怎么做?
  • 09-多模型配置指南
  • C++ 移动构造与移动赋值:类成员变量处理方式
  • DFS:带重复项的全排列,程序运行全流程解析
  • 【研报287】小马智行深度报告:Robotaxi赛道的竞争格局
  • 212_视觉处理的基石:深入浅出卷积层(Convolutional Layer)
  • IBM V3700控制器更换实战:从503错误到系统恢复的全过程解析
  • 原木全屋定制工厂:优质厂商选择标准深度解析
  • 从LevelDB到自研PoolEngine:金融C++内存池测试演进史(2003–2024,12次重大架构迭代中的3次致命教训)
  • Venera开源漫画管理工具:从环境搭建到高级功能应用全指南
  • 关于对RNN,LSTM,BiLSTM算法的初步认识
  • XUnity.AutoTranslator:高性能Unity游戏实时翻译架构解析
  • 原型与原型链、原型属性学习笔记
  • STM32定时器级联功能实战:如何构建64位定时器
  • python boto3
  • Win11Debloat:轻松打造极速、纯净Windows 11的终极指南
  • 4大维度掌握AI音乐源分离:Demucs的技术突破与实践指南
  • 告别理论推导!用《有源滤波器的快速实用设计》手把手搞定1kHz带通滤波器(附Multisim仿真)
  • Kubernetes网络入门003篇【20260407】
  • 2026执医考试备考优质机构最新推荐_零基础、在职高效通过首选 - 医考机构品牌测评专家
  • npm国内镜像加速之使用 nrm 工具(灵活切换,适合多环境)
  • Linux新手必看:fdisk磁盘分区从入门到精通(含常见问题解决)
  • 19米LS型螺旋输送机设计【说明书+CAD图纸+开题报告+外文翻译】