共计 2481 个字符,预计需要花费 7 分钟才能阅读完成。
问题背景
在实际业务中,文本分类被广泛应用于各种场景,比如电商评论的情感分析、客服工单的自动分类、新闻内容的主题划分等。这些场景往往面临以下几个技术挑战:

- 数据多样性:文本数据可能存在拼写错误、方言、缩写等非标准表达。
- 类别不平衡:某些类别的样本数量远多于其他类别,导致模型偏向多数类。
- 高维稀疏性:文本特征通常非常高维且稀疏,尤其是使用词袋模型时。
- 实时性要求:在线服务需要低延迟响应,尤其是在高并发场景下。
模型对比
以下是四种常见文本分类模型的对比表格:
| 模型 | 适用条件 | 优点 | 缺点 |
|---|---|---|---|
| 朴素贝叶斯 | 小规模数据,低计算资源 | 训练速度快,实现简单 | 忽略词序,特征独立性假设过强 |
| SVM | 高维稀疏特征,中等规模数据 | 泛化能力强,适合高维特征 | 核函数选择影响大,调参复杂 |
| LSTM | 序列数据,考虑上下文依赖 | 捕捉长距离依赖,适合变长文本 | 训练时间长,需要大量数据 |
| BERT | 大规模数据,预训练 + 微调 | 上下文感知,迁移学习能力强 | 计算资源消耗大,推理延迟高 |
核心实现
1. Scikit-learn 实现 TF-IDF+SVM pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipeline
# 定义 pipeline
model = Pipeline([('tfidf', TfidfVectorizer(**max_features=10000**)), # 限制特征数量
('svm', LinearSVC(**C=1.0**, **penalty='l2'**, **loss='squared_hinge'**))
])
# 训练模型
model.fit(X_train, y_train)
2. 基于 PyTorch 构建 BiLSTM+Attention
import torch
import torch.nn as nn
class BiLSTM_Attention(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.lstm = nn.LSTM(embed_dim, hidden_dim, bidirectional=True, batch_first=True)
self.attention = nn.Linear(2*hidden_dim, 1)
self.fc = nn.Linear(2*hidden_dim, num_classes)
def forward(self, x):
embedded = self.embedding(x) # [batch, seq_len, embed_dim]
lstm_out, _ = self.lstm(embedded) # [batch, seq_len, 2*hidden_dim]
# 注意力机制
attention_weights = torch.softmax(self.attention(lstm_out), dim=1)
context = torch.sum(attention_weights * lstm_out, dim=1)
return self.fc(context)
3. HuggingFace Transformers 的 BERT 微调
from transformers import BertTokenizer, BertForSequenceClassification
from transformers import Trainer, TrainingArguments
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=num_classes)
# 训练参数设置
training_args = TrainingArguments(
output_dir='./results',
num_train_epochs=3,
per_device_train_batch_size=16,
**learning_rate=2e-5**,
warmup_steps=500,
weight_decay=0.01,
)
# 创建 Trainer
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=val_dataset
)
# 开始训练
trainer.train()
性能优化
- 模型压缩:
- 使用知识蒸馏,让小型模型学习 BERT 的输出分布
-
应用量化技术,将 FP32 转为 INT8 减少模型大小
-
批量推理:
- 合理设置 batch_size,充分利用 GPU 并行计算
-
使用 TensorRT 加速推理过程
-
显存优化:
- 梯度累积:小 batch 多次计算后再更新参数
- 混合精度训练:FP16+FP32 组合减少显存占用
避坑指南
类别不平衡处理
- 过采样少数类或欠采样多数类
- 使用类别权重,在损失函数中给少数类更高权重
OOV 词处理
- 对于预训练模型,添加特殊 [UNK] 标记
- 对非预训练模型,构建字符级或子词级表示
在线服务延迟保障
- 模型轻量化:剪枝、量化
- 异步处理:队列 + 批处理
- 缓存热点查询结果
延伸思考
当标注数据不足时,可以考虑以下半监督学习方法:
- 自训练:用已有模型预测未标注数据,筛选高置信度样本加入训练集
- 一致性正则化:对输入加入噪声,强制模型输出一致
- 预训练 + 微调:利用大规模无监督预训练,小样本微调
在实际项目中,我们需要根据数据规模、计算资源和业务需求,灵活选择最适合的模型和技术方案。从简单的朴素贝叶斯到复杂的 BERT,每种方法都有其适用场景,关键在于理解它们的特性和 trade-off。
正文完
