本次实验的Notebook已经上传到了GitHub上,大家可以自行下载查看。
PPT网址
https://bert-r9hswwn.gamma.site/
情感分析模型微调与评估
本文档展示了如何使用BERT模型进行中文情感分析的微调与评估。包括数据准备、模型微调、模型评估等步骤。
1. 导入所需库
首先,我们需要导入相关的Python库和模块。
import torch
from transformers import AutoTokenizer, AutoModel, AdamW
from torch.utils.data import DataLoader, Dataset, random_split
import pandas as pd
from tqdm import tqdm
import random
from transformers import BertForSequenceClassification
2. 下载预训练的BERT模型
使用 modelscope
下载预训练的中文BERT模型。
from modelscope import snapshot_download
model_dir = snapshot_download('tiansz/bert-base-chinese')
3. 加载预训练模型和分词器
加载预训练的BERT模型和分词器。
tokenizer = AutoTokenizer.from_pretrained(model_dir)
model = BertForSequenceClassification.from_pretrained(model_dir)
注意:加载模型时,会有一些警告提示某些权重未初始化,这是正常的,因为我们需要对模型进行微调。
4. 定义数据集类
定义一个 SentimentDataset
类来处理情感分析的数据集。
class SentimentDataset(Dataset):
def __init__(self, dataframe, tokenizer, max_length=128):
self.dataframe = dataframe
self.tokenizer = tokenizer
self.max_length = max_length
def __len__(self):
return len(self.dataframe)
def __getitem__(self, idx):
text = self.dataframe.iloc[idx]['review'] # 使用标签索引
label = 1 if self.dataframe.iloc[idx]['label'] == 1 else 0 # 使用标签索引
encoding = self.tokenizer(text, padding='max_length', truncation=True, max_length=self.max_length, return_tensors='pt')
return {
'input_ids': encoding['input_ids'].flatten(),
'attention_mask': encoding['attention_mask'].flatten(),
'labels': torch.tensor(label, dtype=torch.long)
}
5. 读取和处理数据
读取训练数据文件,并将其处理为数据集对象。
with open("train.txt", "r", encoding="utf-8") as file:
lines = file.readlines()
data = []
for line in lines:
label, text = line.strip().split("\t")
data.append((int(label), text))
df = pd.DataFrame(data, columns=["label", "review"])
dataset = SentimentDataset(df, tokenizer, max_length=128)
6. 划分训练集和验证集
将数据集划分为训练集和验证集。
train_size = int(0.8 * len(dataset))
val_size = len(dataset) - train_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
创建数据加载器。
train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=8, shuffle=False)
7. 设置训练参数
设置训练参数和设备。
optimizer = AdamW(model.parameters(), lr=5e-5)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
8. 训练模型
开始训练模型。
model.train()
for epoch in range(3):
for batch in tqdm(train_loader, desc="Epoch {}".format(epoch + 1)):
input_ids = batch['input_ids'].to(device)
attention_mask = batch['attention_mask'].to(device)
labels = batch['labels'].to(device)
optimizer.zero_grad()
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
loss = outputs.loss
loss.backward()
optimizer.step()
9. 验证模型
在验证集上评估模型。
model.eval()
total_eval_accuracy = 0
for batch in tqdm(val_loader, desc="Evaluating"):
input_ids = batch['input_ids'].to(device)
attention_mask = batch['attention_mask'].to(device)
labels = batch['labels'].to(device)
with torch.no_grad():
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
logits = outputs.logits
preds = torch.argmax(logits, dim=1)
accuracy = (preds == labels).float().mean()
total_eval_accuracy += accuracy.item()
average_eval_accuracy = total_eval_accuracy / len(val_loader)
print("Validation Accuracy:", average_eval_accuracy)
10. 使用模型进行预测
使用微调后的模型进行情感预测。
def predict_sentiment(sentence):
inputs = tokenizer(sentence, padding='max_length', truncation=True, max_length=128, return_tensors='pt').to(device)
with torch.no_grad():
outputs = model(**inputs)
logits = outputs.logits
probs = torch.softmax(logits, dim=1)
positive_prob = probs[0][1].item() # 1表示正面
return positive_prob
def predict(sentence):
positive_prob = predict_sentiment(sentence)
threshold = 0.5 # 设置阈值
if positive_prob > threshold:
print("正面")
else:
print("负面")
predict("这家菜真好吃!")
11. 测试模型性能
加载测试数据集并评估模型性能。
import torch
from torch.utils.data import Dataset
class TestDataset(Dataset):
def __init__(self, file_path, tokenizer, max_length=128):
self.data = []
with open(file_path, "r", encoding="utf-8") as file:
for line in file:
label, text = line.strip().split("\t")
self.data.append((int(label), text))
self.tokenizer = tokenizer
self.max_length = max_length
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
label, text = self.data[idx]
encoding = self.tokenizer(text, padding='max_length', truncation=True, max_length=self.max_length, return_tensors='pt')
return {
'input_ids': encoding['input_ids'].flatten(),
'attention_mask': encoding['attention_mask'].flatten(),
'labels': torch.tensor(label, dtype=torch.long)
}
test_dataset = TestDataset("test.txt", tokenizer, max_length=128)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=8, shuffle=False)
model.eval()
total_eval_accuracy = 0
for batch in tqdm(test_loader, desc="Evaluating"):
input_ids = batch['input_ids'].to(device)
attention_mask = batch['attention_mask'].to(device)
labels = batch['labels'].to(device)
with torch.no_grad():
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
logits = outputs.logits
preds = torch.argmax(logits, dim=1)
accuracy = (preds == labels).float().mean()
total_eval_accuracy += accuracy.item()
average_eval_accuracy = total_eval_accuracy / len(test_loader)
print("Test Accuracy:", average_eval_accuracy)
12. 流程图
以下是整个流程的序列图:
sequenceDiagram
participant 数据准备
participant 模型微调
participant 模型评估
participant 代码实现
participant 自动生成测试数据
数据准备 -> 模型微调: 准备数据集
模型微调 -> 模型评估: 微调模型
模型评估 -> 代码实现: 评估模型性能
代码实现 -> 自动生成测试数据: 编写评估代码
自动生成测试数据 --> 代码实现: 生成测试数据
代码实现 -> 模型评估: 使用测试数据评估模型性能
通过上述步骤,我们完成了中文情感分析模型的微调和评估过程。