Python案例如何用BERT进行文本分类

wen python案例 1

本文目录导读:

Python案例如何用BERT进行文本分类

  1. 文章导读目录
  2. 背景与痛点
  3. BERT核心原理(快速科普)
  4. 环境搭建
  5. 数据准备(中文情感分析为例)
  6. 加载预训练模型与分词器
  7. 模型微调:核心代码
  8. 完整案例演示:预测新文本
  9. 常见FAQ问答
  10. SEO友好总结

Python实战案例:如何用BERT进行文本分类(从原理到代码全解析)

文章导读目录

  1. 背景与痛点:为什么传统文本分类方法不够用?
  2. BERT核心原理:一分钟看懂Transformer与预训练机制
  3. 环境搭建:Python包安装与GPU配置要点
  4. 数据准备:中文情感分析数据集清洗与标签处理
  5. 加载预训练模型:使用transformers库加载bert-base-chinese
  6. 模型微调:自定义分类头,冻结部分层,训练循环代码
  7. 完整案例演示:训练日志、准确率指标、预测输出
  8. 常见FAQ问答:解决过拟合、OOM爆显存、长文本截断问题
  9. SEO友好总结:BERT文本分类的落地建议与资源推荐

背景与痛点

传统文本分类常用TF-IDF+朴素贝叶斯或Word2Vec+LSTM,但这类方法无法捕捉上下文语义——苹果很好吃”与“苹果发布了新手机”中的“苹果”词义完全不同,BERT(Bidirectional Encoder Representations from Transformers)通过双向注意力机制大规模预训练,能根据上下文动态理解词义,显著提升分类准确率。

BERT核心原理(快速科普)

BERT基于Transformer的Encoder部分,创新点在于:

  • 双向训练:同时看左边和右边的词语(传统RNN只能从左到右);
  • 预训练+微调:先用海量无标注文本学习语言知识,再针对分类任务做简单调整;
  • 输入表示[CLS]标签的最终隐层向量作为整句语义代表,直接接分类器。

了解这些即可开始实战,无需深究注意力公式。

环境搭建

# 推荐使用Python 3.8+,建议用conda创建虚拟环境
pip install torch transformers pandas scikit-learn

GPU提示:若显存小于6GB,请使用Google Colab的免费GPU(T4),或改用bert-base-uncased(英文)减少显存占用。

数据准备(中文情感分析为例)

我们使用IMDb中文翻译版(或爬取京东评论),格式如下:

text label
物流很快,包装完好,非常满意 1 (正面)
质量太差,用了三天就坏了 0 (负面)

关键代码

import pandas as pd
df = pd.read_csv('sentiment.csv')
# 标签必须从0开始编码
labels = df['label'].tolist()
texts = df['text'].tolist()

加载预训练模型与分词器

from transformers import BertTokenizer, BertForSequenceClassification
model_name = 'bert-base-chinese'  # 中文BERT
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=2)
# 将模型移到GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

重要BertForSequenceClassification自动在BERT后添加了分类线性层,无需手动构建。

模型微调:核心代码

1 数据编码与DataLoader

from torch.utils.data import DataLoader, TensorDataset
def encode_texts(texts, labels, max_len=128):
    inputs = tokenizer(texts, padding=True, truncation=True, 
                       max_length=max_len, return_tensors='pt')
    return TensorDataset(inputs['input_ids'], inputs['attention_mask'], 
                         torch.tensor(labels))
train_dataset = encode_texts(train_texts, train_labels)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)

2 训练循环(仅需微调5~10个epoch)

from torch.optim import AdamW
from tqdm import tqdm
optimizer = AdamW(model.parameters(), lr=2e-5)
model.train()
for epoch in range(5):
    total_loss = 0
    for batch in tqdm(train_loader):
        input_ids, attention_mask, labels = [b.to(device) for b in batch]
        outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        total_loss += loss.item()
    print(f"Epoch {epoch+1}, Loss: {total_loss/len(train_loader):.4f}")

技巧:若数据量<1万,建议冻结BERT前6层(for param in model.bert.encoder.layer[:6].parameters(): param.requires_grad = False)以防止过拟合。

完整案例演示:预测新文本

model.eval()
test_text = ["这个产品真的太好了,下次还会买"]
inputs = tokenizer(test_text, return_tensors='pt', padding=True, truncation=True).to(device)
with torch.no_grad():
    outputs = model(**inputs)
    probs = torch.nn.functional.softmax(outputs.logits, dim=-1)
    pred = torch.argmax(probs, dim=1)
print(f"预测标签: {pred.item()},正面概率: {probs[0][1]:.2f}")

输出示例:预测标签: 1,正面概率: 0.97(说明模型判断为正面)。

常见FAQ问答

Q1:训练时显存溢出(OOM)怎么办?
A:降低batch_size(改为8或4),或使用gradient_accumulation_steps累积梯度,另外max_len不要超过256。

Q2:模型在验证集上准确率低?
A:检查数据标签是否平衡;尝试使用torch.nn.CrossEntropyLossweight参数处理不平衡;或增加训练epoch到10轮。

Q3:长文本如何截断?
A:BERT最大输入长度512,超出的部分可截取开头和结尾(truncation='longest_first'),或使用Longformer替代。

Q4:如何保存和加载模型?
A:model.save_pretrained('./my_bert_model'),加载时用BertForSequenceClassification.from_pretrained('./my_bert_model')

SEO友好总结

本文通过一个完整的Python案例,手把手教会你如何用BERT进行中文文本分类,核心要点:

  • 使用预训练模型避免从头训练;
  • 微调时设置小学习率(2e-5);
  • 通过分词器统一处理输入格式;
  • 注意显存限制与数据平衡。

如果你遇到具体代码问题,欢迎在评论区留言,未来可尝试将BERT替换为RoBERTaDistilBERT(更轻量)以获得更佳效果。

推荐学习资源

  • Hugging Face官方文档:transformers文档(请手动复制到浏览器打开)
  • 吴恩达《BERT情感分类》微调视频教程

(本文已整合Google、Bing搜索结果,并去除重复性内容,保留核心技术细节)

抱歉,评论功能暂时关闭!