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

目录

一、项目流程

[1.1 加载预训练模型Bert](#1.1 加载预训练模型Bert)

[1.2 数据预处理](#1.2 数据预处理)

[1.3 模型定义](#1.3 模型定义)

[1.4 模型训练](#1.4 模型训练)

[1.5 模型预测](#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模型 通过官方链接或者代码方式下载:

python 复制代码
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输入的任务。数据清洗过滤无用列,去除不符合的行。

python 复制代码
# 过滤数据
	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])

python 复制代码
	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。

python 复制代码
	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字段。

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

训练代码如下:

python 复制代码
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完成标签映射。

python 复制代码
# 含任务头
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显存利用率过高训练效率很低等问题。上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章!

相关推荐
明月_清风2 小时前
从提示词到脚手架:LLM 开发的三大工程维度对比
人工智能
南湖北漠2 小时前
奇奇怪怪漫画里面的蛞蝓是带壳的那种鼻涕虫
网络·人工智能·计算机网络·其他·安全·生活
小超同学你好2 小时前
Transformer 23. Qwen 3.5 架构介绍:混合线性/全注意力、MoE 与相对 Qwen 1 / 2 / 3 的演进
人工智能·深度学习·语言模型·架构·transformer
Ztopcloud极拓云视角2 小时前
谷歌 Gemma 4 实战部署指南:从开源协议解读到本地推理落地
人工智能
Agent产品评测局3 小时前
企业发票管理自动化落地,验真归档全流程实现方法:2026企业级智能体选型与实测指南
运维·网络·人工智能·ai·chatgpt·自动化
HIT_Weston3 小时前
39、【Agent】【OpenCode】本地代理分析(三)
人工智能·agent·opencode
大虫刷题3 小时前
华为认证(HCIP-AI)五大分类,有何区别及学习难度和从事职业方向
人工智能·学习
源码之屋3 小时前
计算机毕业设计:Python出行数据智能分析与预测平台 Django框架 可视化 数据分析 PyEcharts 交通 深度学习(建议收藏)✅
人工智能·python·深度学习·数据分析·django·汽车·课程设计
AI学长3 小时前
数据集|多种水果目标检测数据集-苹果、西瓜、番茄、菠萝、洋葱(共 5 类)
人工智能·目标检测·计算机视觉·多种水果目标检测数据集