实战项目

第33课:文本分类

文本预处理、TF-IDF、朴素贝叶斯、深度学习初探、模型比较

1. 文本分类流程

原始文本→清洗→分词→特征提取→模型训练→评估

2. 预处理

去除HTML/特殊字符、统一大小写、去停用词。中文:jieba分词。英文:词干化/词形还原。

3. 特征提取

BoW: 忽略词序。TF-IDF: IDF=log(N/df)——少数文档出现的词更有区分力。

N-gram: 捕捉词序但维度爆炸。

4. 朴素贝叶斯

P(c|d) ∝ P(c)ΠP(wᵢ|c)。拉普拉斯平滑P(w|c)=(count(w,c)+α)/(count(c)+α|V|)

为什么文本上效果好?高维空间特征近似独立;只需正确排序不需准确概率。

5. 模型比较

模型准确率速度
朴素贝叶斯良好最快
SVM优秀
逻辑回归良好

线性SVM在文本上通常最好(高维稀疏→线性核足够)

Python代码实现与验证

💡 代码说明:以下代码使用 Python / Scikit-learn 实现,已实机运行验证。

完整代码


import numpy as np
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB, ComplementNB
from sklearn.svm import LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import Pipeline
np.random.seed(42)

cats = ['alt.atheism','soc.religion.christian','comp.graphics','sci.med']
train = fetch_20newsgroups(subset='train', categories=cats, random_state=42)
test = fetch_20newsgroups(subset='test', categories=cats, random_state=42)
print("训练: {} 测试: {} 类别: {}".format(len(train.data),len(test.data),len(train.target_names)))

print("\n=== 模型对比 ===")
models = {
    'MultinomialNB': Pipeline([('tfidf',TfidfVectorizer(max_features=10000)),('nb',MultinomialNB())]),
    'ComplementNB': Pipeline([('tfidf',TfidfVectorizer(max_features=10000)),('nb',ComplementNB())]),
    'LinearSVC': Pipeline([('tfidf',TfidfVectorizer(max_features=10000)),('svm',LinearSVC(max_iter=2000))]),
    'LogisticReg': Pipeline([('tfidf',TfidfVectorizer(max_features=10000)),('lr',LogisticRegression(max_iter=200))]),
}
for name,mdl in models.items():
    s = cross_val_score(mdl, train.data, train.target, cv=5)
    mdl.fit(train.data, train.target)
    print("{}: CV={:.4f} Test={:.4f}".format(name, s.mean(), mdl.score(test.data,test.target)))

print("\n=== N-gram影响 ===")
for ng in [(1,1),(1,2),(1,3)]:
    pipe = Pipeline([('tfidf',TfidfVectorizer(ngram_range=ng,max_features=20000)),('svm',LinearSVC(max_iter=2000))])
    s = cross_val_score(pipe, train.data, train.target, cv=5)
    pipe.fit(train.data, train.target)
    print("ngram={}: CV={:.4f} Test={:.4f}".format(ng, s.mean(), pipe.score(test.data,test.target)))

运行结果

训练: 2257 测试: 1502 类别: 4 === 模型对比 === MultinomialNB: CV=0.9353 Test=0.8702 ComplementNB: CV=0.9628 Test=0.9015 LinearSVC: CV=0.9734 Test=0.9268 LogisticReg: CV=0.9575 Test=0.9028 === N-gram影响 === ngram=(1, 1): CV=0.9730 Test=0.9254 ngram=(1, 2): CV=0.9725 Test=0.9214 ngram=(1, 3): CV=0.9699 Test=0.9201
✅ 验证通过

深入理解:从项目到产品的关键步骤

ML项目成功的关键因素

  1. 定义清晰的目标:业务指标 > ML指标(提升AUC不是目的,提升收入才是)
  2. 数据质量:Garbage in, garbage out。花80%时间在数据上是正常的
  3. 简单优先:简单基线 > 复杂模型(如果简单就够了)
  4. 持续监控:模型上线不是终点,漂移检测和重训练是必须的
  5. 沟通能力:能向非技术人解释模型为什么做某个预测

项目时间分配建议

阶段时间占比关键产出
问题定义10%明确的评估指标和成功标准
数据获取/清洗30%干净可用的数据集
特征工程25%强特征集
模型训练/调优20%最优模型
评估/部署15%上线模型+监控方案

从竞赛到生产的差距

Kaggle竞赛和实际生产的差异:

ML系统技术债

D. Sculley等人在2015年的经典论文中指出,ML系统中只有很小一部分是实际的ML代码,其余都是胶水代码、配置、数据管道、监控等。隐藏的技术债包括:

项目复盘与进阶路线

5个项目的核心收获

  1. 房价预测:回归全流程——EDA→特征工程(对数变换+交叉特征)→多模型比较→融合。关键教训:特征工程比模型选择更重要,对数变换处理右偏目标是标准操作。
  2. 欺诈检测:极度不平衡——SMOTE/类别权重/异常检测框架。关键教训:AUC-PR比AUC-ROC更有意义,监督方法远优于无监督方法。
  3. 客户分群:无监督业务应用——RFM+聚类+画像解读。关键教训:业务可解释性比聚类指标重要,K值选择要考虑运营成本。
  4. 推荐基础:推荐系统经典算法——协同过滤+矩阵分解。关键教训:冷启动是最难的问题,简单方法(SVD)常常足够好。
  5. 文本分类:NLP传统方法——TF-IDF+NB/SVM。关键教训:预处理影响巨大,线性SVM在文本上通常最好。

从竞赛到生产的差距

维度竞赛生产
数据已清洗CSV多源异构、实时流
目标单一指标多目标(精度+延迟+成本)
模型复杂集成简单高效、可维护
评估离线CV在线A/B测试
部署不涉及Docker/K8s/服务化
监控不涉及漂移检测+重训练

继续学习路线

推荐学习资源

类别资源特点
教材ISLR (Python版)统计学习入门经典
教材ESL统计学习圣经(进阶)
课程Andrew Ng ML最佳入门课
课程Stanford CS229更数学化
实践Kaggle Learn动手学ML
文档Scikit-learn最优秀的ML库文档

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

📝 课后练习

  1. 实现文本预处理流程(清洗、分词、停用词)
  2. 比较BoW和TF-IDF
  3. 比较NB/SVM/LR文本分类
  4. 分析N-gram影响
  5. 实现多标签文本分类
📝
文本分类师
完成文本分类项目