引言
文本分类是NLP最基础也是应用最广泛的任务之一。从情感分析到新闻分类,从垃圾邮件检测到意图识别,文本分类无处不在。本指南将带您从零开始构建一个完整的文本分类系统。
一、任务定义与数据准备
1.1 明确任务类型
二分类:
- 情感分析: 正面/负面
- 垃圾邮件检测: 垃圾/正常
- 输出: 单个标签
多分类:
- 新闻分类: 体育/财经/科技等
- 意图识别: 查询天气/订餐/打车等
- 输出: 互斥的单个标签
多标签分类:
- 文章标签: 可以同时属于多个类别
- 输出: 多个标签
1.2 数据收集
数据来源:
- 公开数据集: IMDB, AG News, 20 Newsgroups等
- 业务数据: 用户评论、客服对话等
- 数据标注: 众包平台(如Amazon MTurk)或内部标注
数据量建议:
- 传统方法: 每类至少1000条
- 深度学习: 每类至少5000条
- 预训练模型微调: 每类可低至100-500条
1.3 数据清洗
- 去除HTML标签和特殊字符
- 统一大小写(根据任务决定)
- 去除或替换URL、邮箱、电话号码
- 处理缺失值和重复数据
- 过滤过短或过长的文本
1.4 数据划分
- 训练集: 70-80%
- 验证集: 10-15%
- 测试集: 10-15%
- 确保各类别分布平衡
二、传统方法
2.1 特征工程
Bag of Words (BoW):
- 将文本表示为词的集合
- 统计每个词的出现次数
- 简单但丢失词序信息
TF-IDF:
- TF: 词频,词在文档中的频率
- IDF: 逆文档频率,降低常见词权重
- TF-IDF = TF × IDF
- 效果优于BoW
N-gram:
- 考虑连续N个词的组合
- Bigram(2-gram): "很好" vs "不好"
- 保留部分词序信息
2.2 分类算法
朴素贝叶斯:
- 基于贝叶斯定理
- 假设特征独立
- 速度快,效果不错
- 适合基线模型
支持向量机(SVM):
- 寻找最优分类超平面
- 配合TF-IDF效果好
- 适合中小规模数据
逻辑回归:
- 线性分类器
- 可解释性强
- 训练快速
三、深度学习方法
3.1 词嵌入
Word2Vec:
- 将词映射到低维稠密向量
- 语义相似的词向量接近
- 两种模型: CBOW和Skip-gram
GloVe:
- 基于词共现矩阵
- 结合全局统计信息
FastText:
- 考虑子词(subword)信息
- 对生僻词和拼写错误更鲁棒
3.2 RNN/LSTM/GRU
架构:
- 输入: 词嵌入序列
- RNN/LSTM/GRU处理序列
- 最后一个时间步的输出用于分类
双向LSTM:
- 正向和反向LSTM
- 捕捉双向上下文信息
- 效果优于单向
3.3 CNN文本分类
TextCNN:
- 多个不同尺寸的卷积核
- 提取不同N-gram特征
- MaxPooling提取关键特征
- 速度快,效果好
3.4 注意力机制
- 让模型关注重要的词
- 提升可解释性
- 与LSTM结合效果显著
四、预训练模型方法
4.1 BERT微调
步骤:
- 1. 选择预训练BERT模型
- 2. 添加分类层(通常是[CLS]的输出)
- 3. 在任务数据上微调
- 4. 使用较小学习率(2e-5到5e-5)
优势:
- 少量数据即可达到好效果
- 捕捉深层语义信息
- 当前最佳方案
4.2 模型选择
- BERT-base: 通用选择,12层
- BERT-large: 更高精度,24层
- RoBERTa: BERT改进版
- ALBERT: 参数更少,速度更快
- DistilBERT: 蒸馏版,速度快
- 中文模型: BERT-wwm, RoBERTa-wwm, MacBERT等
4.3 实现示例(PyTorch)
from transformers import BertForSequenceClassification, BertTokenizer
import torch
# 加载模型和tokenizer
model = BertForSequenceClassification.from_pretrained(
'bert-base-uncased',
num_labels=2 # 二分类
)
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
# 处理输入
text = "This movie is fantastic!"
inputs = tokenizer(
text,
padding='max_length',
truncation=True,
max_length=128,
return_tensors='pt'
)
# 推理
outputs = model(**inputs)
logits = outputs.logits
prediction = torch.argmax(logits, dim=-1)
五、模型训练与调优
5.1 超参数调优
关键超参数:
- 学习率:
- 传统方法: 0.01-0.1
- 深度学习: 0.001-0.01
- BERT微调: 2e-5到5e-5
- Batch Size:
- 传统方法: 32-128
- BERT: 16-32(受显存限制)
- Epochs:
- 传统方法: 10-100
- BERT微调: 3-5(容易过拟合)
5.2 处理类别不平衡
- 过采样: 复制少数类样本
- 欠采样: 减少多数类样本
- 类别权重: 给少数类更大的损失权重
- Focal Loss: 降低易分类样本权重
- 数据增强: 同义词替换、回译等
5.3 正则化
- Dropout: 防止过拟合
- L2正则化: 限制权重大小
- Early Stopping: 验证集不再提升时停止
六、评估与优化
6.1 评估指标
- 准确率(Accuracy): 适合类别平衡数据
- 精确率(Precision): 预测为正的样本中真正的比例
- 召回率(Recall): 实际为正的样本中被找出的比例
- F1-Score: 精确率和召回率的调和平均
- AUC-ROC: 适合二分类,评估整体性能
- 混淆矩阵: 分析各类别的分类情况
6.2 错误分析
- 查看分类错误的样本
- 识别常见错误模式
- 分析是否需要更多某类数据
- 考虑引入新特征或规则
6.3 模型融合
- 投票: 多个模型投票决定
- 加权平均: 按性能加权
- Stacking: 训练元模型融合
七、部署上线
7.1 模型优化
- 模型量化: 减少模型大小
- 模型蒸馏: BERT蒸馏到小模型
- 模型剪枝: 移除不重要的参数
- ONNX导出: 跨平台部署
7.2 服务化
- 使用Flask/FastAPI构建API
- 添加缓存机制
- 批量推理提升吞吐量
- 监控推理延迟和准确率
7.3 持续优化
- 收集线上badcase
- 定期标注补充数据
- 模型定期重训练
- A/B测试验证新模型效果
总结
文本分类从传统机器学习到深度学习再到预训练模型,技术不断进步。实践中建议:
- 从简单方法开始,建立基线
- 数据量充足时,使用BERT微调
- 重视数据质量和错误分析
- 根据业务需求平衡精度和速度