人工智能之语言领域
第五章 文本分类
文章目录
- 人工智能之语言领域
- [前言 文本分类](#前言 文本分类)
- [5.1 文本分类概述](#5.1 文本分类概述)
- [5.1.1 分类任务类型](#5.1.1 分类任务类型)
- [5.1.2 典型应用场景](#5.1.2 典型应用场景)
- [5.2 传统分类模型](#5.2 传统分类模型)
- [5.2.1 朴素贝叶斯(NB)与多项式朴素贝叶斯](#5.2.1 朴素贝叶斯(NB)与多项式朴素贝叶斯)
- [5.2.2 逻辑回归(LR)与支持向量机(SVM)](#5.2.2 逻辑回归(LR)与支持向量机(SVM))
- [逻辑回归(Logistic Regression)](#逻辑回归(Logistic Regression))
- 支持向量机(SVM)
- [5.2.3 模型评估:准确率、召回率、F1值、ROC-AUC](#5.2.3 模型评估:准确率、召回率、F1值、ROC-AUC)
- [5.3 深度学习分类模型](#5.3 深度学习分类模型)
- [5.3.1 CNN 文本分类:局部特征提取](#5.3.1 CNN 文本分类:局部特征提取)
- [5.3.2 RNN 文本分类:序列特征捕捉](#5.3.2 RNN 文本分类:序列特征捕捉)
- [5.3.3 混合模型与实战调参](#5.3.3 混合模型与实战调参)
- [5.4 实战案例:电商评论情感倾向二分类](#5.4 实战案例:电商评论情感倾向二分类)
- 补充:模型选择决策树
- 小结
- 资料关注
前言 文本分类
📌 注意 :本章标题"计算机视觉 详细介绍第5章 文本分类"存在学科混淆。
文本分类(Text Classification)属于自然语言处理(NLP)领域,而非计算机视觉(CV) 。以下内容将按 NLP 中的文本分类 进行详细讲解。
文本分类是 NLP 最基础、应用最广泛的监督学习任务之一,其目标是自动为一段文本分配一个或多个预定义类别标签。从垃圾邮件过滤到新闻推荐,从客服工单路由到情感分析,文本分类无处不在。本章将系统介绍文本分类的任务形式、传统与深度学习模型、评估指标,并通过电商评论情感分析实战案例完整演示端到端流程。
5.1 文本分类概述
5.1.1 分类任务类型
| 类型 | 说明 | 示例 |
|---|---|---|
| 二分类(Binary Classification) | 两个互斥类别 | 垃圾/非垃圾短信 |
| 多分类(Multi-class Classification) | 多个互斥类别 | 新闻分类:体育、财经、科技、娱乐 |
| 多标签分类(Multi-label Classification) | 每个样本可属于多个类别 | 一篇论文同时属于"NLP"和"深度学习" |
文本分类
二分类
多分类
多标签分类
正面 / 负面
体育 / 财经 / 科技
NLP + 深度学习 + 应用
💡 关键区别:
- 多分类 :
softmax输出,概率和为1- 多标签 :
sigmoid输出,每个标签独立预测
5.1.2 典型应用场景
| 场景 | 任务类型 | 价值 |
|---|---|---|
| 垃圾短信/邮件识别 | 二分类 | 提升用户体验,减少骚扰 |
| 新闻自动分类 | 多分类 | 内容聚合、个性化推荐 |
| 用户意图识别 | 多分类 | 智能客服路由(如"查账单"、"改密码") |
| 商品评论情感分析 | 二分类/多分类 | 品牌舆情监控、产品改进 |
| 医疗文献标注 | 多标签 | 辅助科研检索、知识图谱构建 |
5.2 传统分类模型
传统模型依赖手工特征 (如 TF-IDF)+ 浅层分类器,训练快、可解释性强,适合中小规模数据。
5.2.1 朴素贝叶斯(NB)与多项式朴素贝叶斯
核心假设:特征(词)之间条件独立。
- 多项式 NB :适用于离散计数特征(如词频)
- 伯努利 NB :适用于二值特征(词是否出现)
📐 公式(多项式):
P ( y = c ∣ x ) ∝ P ( y = c ) ∏ i = 1 n P ( x i ∣ y = c ) P(y=c|\mathbf{x}) \propto P(y=c) \prod_{i=1}^n P(x_i|y=c) P(y=c∣x)∝P(y=c)i=1∏nP(xi∣y=c)
其中 x_i 是词 i 的出现次数。
python
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
# 构建管道:TF-IDF + NB
nb_pipeline = Pipeline([
('tfidf', TfidfVectorizer(ngram_range=(1, 2), max_features=10000)),
('nb', MultinomialNB(alpha=0.1)) # alpha: 拉普拉斯平滑
])
# 假设 X_train 是分词后的文本列表,y_train 是标签
# nb_pipeline.fit(X_train, y_train)
# predictions = nb_pipeline.predict(X_test)
✅ 优点:训练快、对小数据友好
❌ 缺点:独立性假设过强,忽略词序
5.2.2 逻辑回归(LR)与支持向量机(SVM)
逻辑回归(Logistic Regression)
- 线性模型,输出概率
- 可解释性强(特征权重 = 重要性)
支持向量机(SVM)
- 寻找最大间隔超平面
- 核技巧可处理非线性(但文本常用线性核)
python
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
lr_pipeline = Pipeline([
('tfidf', TfidfVectorizer()),
('lr', LogisticRegression(max_iter=1000))
])
svm_pipeline = Pipeline([
('tfidf', TfidfVectorizer()),
('svm', SVC(kernel='linear', probability=True)) # probability=True 以输出概率
])
📊 实践建议:
- LR:首选基线模型,速度快,支持概率输出
- SVM:在高维稀疏文本上表现优异,但训练慢于 LR
5.2.3 模型评估:准确率、召回率、F1值、ROC-AUC
不同任务关注不同指标:
| 指标 | 公式 | 适用场景 |
|---|---|---|
| 准确率(Accuracy) | (TP+TN)/(TP+TN+FP+FN) | 类别平衡时 |
| 精确率(Precision) | TP/(TP+FP) | 关注"预测为正的有多少真"(如垃圾邮件) |
| 召回率(Recall) | TP/(TP+FN) | 关注"真正的正例有多少被找到"(如疾病诊断) |
| F1值 | 2×(Prec×Rec)/(Prec+Rec) | Precision 与 Recall 的调和平均 |
| ROC-AUC | ROC 曲线下面积 | 评估整体排序能力,不受阈值影响 |
python
from sklearn.metrics import classification_report, roc_auc_score
# 多分类需指定 average
print(classification_report(y_test, y_pred, target_names=['负面', '正面']))
# 二分类 AUC
if len(set(y_test)) == 2:
y_prob = model.predict_proba(X_test)[:, 1]
print("AUC:", roc_auc_score(y_test, y_prob))
⚠️ 注意:类别不平衡时,准确率会失真!应优先看 F1 或 AUC。
5.3 深度学习分类模型
深度学习模型自动学习特征表示,适合大规模数据,性能通常优于传统模型。
5.3.1 CNN 文本分类:局部特征提取
灵感来源:图像 CNN → 将文本视为一维"图像"
- 使用不同尺寸卷积核捕捉 n-gram 特征(如 2-gram, 3-gram)
- Max-Pooling 获取最强特征
词向量矩阵
Conv2D k=2
Conv2D k=3
Conv2D k=4
GlobalMaxPool
GlobalMaxPool
GlobalMaxPool
Concatenate
全连接+Softmax
python
import torch
import torch.nn as nn
class TextCNN(nn.Module):
def __init__(self, vocab_size, embed_dim=128, num_classes=2, kernel_sizes=[2,3,4], num_filters=100):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.convs = nn.ModuleList([
nn.Conv2d(1, num_filters, (k, embed_dim)) for k in kernel_sizes
])
self.dropout = nn.Dropout(0.5)
self.fc = nn.Linear(len(kernel_sizes) * num_filters, num_classes)
def forward(self, x):
# x: [batch, seq_len]
x = self.embedding(x).unsqueeze(1) # [B, 1, L, D]
xs = []
for conv in self.convs:
c = torch.relu(conv(x)).squeeze(3) # [B, F, L-k+1]
p = torch.max_pool1d(c, c.size(2)).squeeze(2) # [B, F]
xs.append(p)
x = torch.cat(xs, 1)
x = self.dropout(x)
return self.fc(x)
✅ 优势:并行计算快,擅长捕捉关键词组合
❌ 劣势:忽略长距离依赖
5.3.2 RNN 文本分类:序列特征捕捉
RNN/LSTM/GRU 按顺序处理文本,保留历史信息。
- LSTM 解决梯度消失,适合长文本
- 通常取最后一个时间步 或所有时间步平均作为句表示
python
class TextRNN(nn.Module):
def __init__(self, vocab_size, embed_dim=128, hidden_dim=128, num_classes=2):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True, bidirectional=True)
self.fc = nn.Linear(hidden_dim * 2, num_classes) # 双向
self.dropout = nn.Dropout(0.5)
def forward(self, x):
x = self.embedding(x) # [B, L, D]
out, (h_n, _) = self.lstm(x) # h_n: [2, B, H]
# 拼接双向最后输出
out = torch.cat([h_n[-2], h_n[-1]], dim=1) # [B, 2*H]
out = self.dropout(out)
return self.fc(out)
✅ 优势:天然处理序列,捕捉上下文
❌ 劣势:训练慢,难以并行
5.3.3 混合模型与实战调参
混合策略常提升性能:
- CNN + RNN:先 CNN 提取局部特征,再 RNN 建模序列
- Attention 机制:聚焦关键 token(如情感词)
调参建议:
| 组件 | 推荐设置 |
|---|---|
| 优化器 | Adam (lr=2e-5 for BERT, lr=1e-3 for CNN/RNN) |
| Batch Size | 16--64(显存允许下越大越好) |
| Dropout | 0.3--0.5 防止过拟合 |
| Early Stopping | 监控验证集 loss,耐心值=3--5 |
5.4 实战案例:电商评论情感倾向二分类
任务描述
- 输入:用户对商品的中文评论(如"质量很好,值得购买!")
- 输出:情感标签(0=负面,1=正面)
- 数据集 :使用公开的 ChnSentiCorp(中文情感分析数据集)
完整代码实现(基于 PyTorch + Transformers)
python
# Step 1: 安装依赖
# pip install transformers datasets torch scikit-learn jieba
# Step 2: 加载数据
from datasets import load_dataset
dataset = load_dataset("seamew/ChnSentiCorp")
train_texts = dataset["train"]["text"]
train_labels = dataset["train"]["label"]
test_texts = dataset["test"]["text"]
test_labels = dataset["test"]["label"]
# Step 3: 使用预训练 BERT(最佳实践)
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments
model_name = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)
# Tokenize
train_encodings = tokenizer(train_texts, truncation=True, padding=True, max_length=128)
test_encodings = tokenizer(test_texts, truncation=True, padding=True, max_length=128)
# 转为 PyTorch Dataset
import torch
class SentimentDataset(torch.utils.data.Dataset):
def __init__(self, encodings, labels):
self.encodings = encodings
self.labels = labels
def __getitem__(self, idx):
item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
item['labels'] = torch.tensor(self.labels[idx])
return item
def __len__(self):
return len(self.labels)
train_dataset = SentimentDataset(train_encodings, train_labels)
test_dataset = SentimentDataset(test_encodings, test_labels)
# Step 4: 训练
training_args = TrainingArguments(
output_dir='./results',
num_train_epochs=3,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
warmup_steps=500,
weight_decay=0.01,
logging_dir='./logs',
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=test_dataset,
)
trainer.train()
# Step 5: 评估
preds = trainer.predict(test_dataset)
y_pred = preds.predictions.argmax(axis=1)
from sklearn.metrics import accuracy_score, f1_score
print("Accuracy:", accuracy_score(test_labels, y_pred))
print("F1:", f1_score(test_labels, y_pred))
结果预期
- 准确率:>95%
- F1值:>95%
💡 若无 GPU,可改用 传统模型(TF-IDF + LR) 作为轻量级方案:
python
# 轻量级替代方案
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.feature_extraction.text import TfidfVectorizer
# 中文需先分词(简化:按字切分)
def char_tokenizer(text):
return list(text)
pipe = Pipeline([
('tfidf', TfidfVectorizer(tokenizer=char_tokenizer, ngram_range=(1,2))),
('lr', LogisticRegression())
])
pipe.fit(train_texts, train_labels)
y_pred = pipe.predict(test_texts)
补充:模型选择决策树
小 <10k
大 >100k
是
否
是
否
数据规模?
传统模型: TF-IDF + LR/SVM
深度学习: BERT/CNN/RNN
需要概率?
LR
SVM
有GPU?
BERT 微调
CNN/RNN with Word2Vec
小结
文本分类是 NLP 的"Hello World"任务,但其技术栈覆盖了从传统机器学习到现代大模型的完整演进:
- 传统模型(NB/LR/SVM)凭借简单高效,仍是工业界常用基线;
- 深度学习模型(CNN/RNN)自动学习特征,在大数据上表现卓越;
- 预训练模型(BERT)已成为当前 SOTA 方案,尤其适合中文等复杂语言。
资料关注
咚咚王
《Python 编程:从入门到实践》
《利用 Python 进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第 3 版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow 机器学习实战指南》
《Sklearn 与 TensorFlow 机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python 深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习 +(迈克尔·尼尔森(Michael+Nielsen)》
《自然语言处理综论 第 2 版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨 +&+ 张孜铭
《AIGC 原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战 AI 大模型》
《AI 3.0》