邮件文本分类:CountVectorizer / TF-IDF + 朴素贝叶斯

一句话总结: 邮件分类是文本分类的经典场景,TfidfVectorizer(抑制停用词)+ MultinomialNB(多项式朴素贝叶斯)是工业基线三件套。

环境要求

  • Python 3.14+
  • scikit-learn 1.9+
  • pandas 3.0+
  • numpy 2.4+
  • jupyter 1.1+
  • notebook 7.5+
  • nbconvert 7.17+

一、为什么 TF-IDF + 朴素贝叶斯是文本分类默认组合

组件 作用
TfidfVectorizer 将文本转为向量,自动压低停用词权重
MultinomialNB 多项式朴素贝叶斯,假设特征条件独立,文本分类效果稳健
Pipeline 串联向量化 + 分类器,生产部署必备

优势: 训练快、可解释、对小数据集友好(50 篇文档也能跑)。

二、数据加载

python 复制代码
import pandas as pd

data_train = pd.read_csv("email_data_train.csv")       # 仅 "text" 列
target_train = pd.read_csv("email_target_train.csv")   # 仅 "target" 列(0/1)

数据结构: 二分类邮件数据(正常/垃圾,或不同主题),50 篇训练样本。

三、转换为 List 格式

注意: sklearn 向量化器要求输入是可迭代的字符串序列。

python 复制代码
data_train = data_train["text"].tolist()
target_train = target_train["target"].tolist()

大规模数据提示: 百万级文本用 HashingVectorizer 替代,无需存储词表,节省内存。

四、CountVectorizer 词频向量化

核心: 构建词表,每篇文档转成"该词出现次数"的向量。

python 复制代码
from sklearn.feature_extraction.text import CountVectorizer

vectorizer = CountVectorizer()                       # 默认:小写 + 按空格切分
data_train_vectorized = vectorizer.fit_transform(data_train)

输出: 稀疏矩阵 (50, 3225) = 50 篇文档 × 3225 个词。

python 复制代码
# 50 篇文档有 3225 个不同的词
print(vectorizer.get_feature_names_out()[1000:1100])  # 查看部分词表
print(len(vectorizer.get_feature_names_out()))        # 3225

⚠️ sklearn 1.0+: 用 get_feature_names_out() 替代 get_feature_names()(已删除)。

五、训练朴素贝叶斯分类器

MultinomialNB 适用场景: 特征是离散计数(词频、TF-IDF),特别适合文本分类。

核心假设: 特征条件独立(朴素之处)。实践中即使不满足也常常 work。

python 复制代码
from sklearn.naive_bayes import MultinomialNB
from sklearn import set_config
set_config(display='text')   # 关闭 diagram 渲染

classifier = MultinomialNB()
classifier.fit(data_train_vectorized, target_train)

六、预测新文档(关键:fit_transform vs transform)

python 复制代码
# 待预测的 2 篇新邮件
docs = [
    'The graphic designer requires a good processor to work',
    'Flights into space'
]

# ⚠️ 关键:用训练时的 vectorizer 做 transform,不能重新 fit
data_new = vectorizer.transform(docs)
data_pred = classifier.predict(data_new)
# → [0, 1]

核心原则:

阶段 调用的方法 作用
训练 fit_transform 学习词表 + 转换
测试/预测 transform 复用词表

⚠️ 这是文本分类的"高频踩坑点",必须牢记!

七、TF-IDF 向量化(更优)

核心思想: TF-IDF = 词频(TF)× 逆文档频率(IDF)

  • TF: 词在当前文档中出现的频率
  • IDF: 词在多少篇文档中出现过的"倒数",出现越普遍权重越低

优势: 自动降低"全场停用词"(the、is)的权重,突出"有区分度"的关键词。

python 复制代码
from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer()
data_train_vectorized = vectorizer.fit_transform(data_train)

相同接口,效果通常更优。

八、Count vs TF-IDF 对比

维度 CountVectorizer TfidfVectorizer
权重策略 单纯词频 词频 × IDF
停用词 默认不过滤 自动抑制
适用场景 短文本、词频本身有意义 长文档、关键词主导
计算开销 小 略大
与朴素贝叶斯搭配 一般 通常更好

结论: 工业默认组合是 TfidfVectorizer + MultinomialNB。

九、完整 Pipeline 部署

python 复制代码
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB

# Pipeline 串联向量化 + 分类器
pipe = Pipeline([
    ('tfidf', TfidfVectorizer()),
    ('clf', MultinomialNB())
])

pipe.fit(data_train, target_train)
pipe.predict(docs_new)  # 直接用 Pipeline 预测

优势:

  • 训练/预测时自动处理 fit/transform 顺序
  • 一行 pickle 保存,生产部署方便

十、关键要点

  • fit_transform vs transform: 训练用前者,测试/预测用后者(必记)
  • TfidfVectorizer 更优: 与朴素贝叶斯搭配效果更好
  • get_feature_names_out: sklearn 1.0+ 新 API
  • 稀疏矩阵: CSR 格式只存非零值,文本场景省 90% 内存
  • Pipeline 必备: 生产部署的"标配"

十一、进阶路径

阶段 工具
基线 TF-IDF + MultinomialNB
进阶 + N-gram (1,2) + 停用词
工业 + Pipeline + GridSearchCV 调参
深度学习 Word2Vec / BERT Embedding

中文场景标准三件套:

python 复制代码
import jieba

def seg_text(text):
    return " ".join(jieba.lcut(text))

texts_seg = [seg_text(t) for t in texts]
# TfidfVectorizer + MultinomialNB

十二、常见陷阱

  • ❌ 测试集重新 fit_transform: 词表不一致,预测完全错位
  • ❌ 中文未分词: 整句成 1 个 token,模型失效
  • ❌ 忘记用 Pipeline: 手动管 fit/transform 顺序易出错
  • ❌ 调旧版 API: get_feature_names() 在 sklearn ≥ 1.0 已删除
  • ❌ 训练集太小: 50 篇可能欠拟合,工业建议 ≥ 10000 篇

十三、调参与超参数

python 复制代码
from sklearn.model_selection import GridSearchCV

param_grid = {
    'tfidf__ngram_range': [(1, 1), (1, 2)],
    'tfidf__min_df': [1, 2, 5],
    'clf__alpha': [0.1, 0.5, 1.0]   # NB 平滑参数
}

grid = GridSearchCV(pipe, param_grid, cv=5, scoring='accuracy')
grid.fit(data_train, target_train)
print(grid.best_params_)

关键参数:

参数 含义 推荐
ngram_range N-gram 范围 (1, 2) 性价比最高
min_df / max_df 词频阈值 min_df=2 过滤低频噪声
stop_words 停用词 'english' 或自定义列表
alpha (NB) 拉普拉斯平滑 0.1-1.0,小数据集用 1.0

网络取材来源于:ant-exercises-sklearn: scikit-learn 编程练习 100例

相关推荐
默_笙3 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
qq_426003963 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
长沙三为智能科技3 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读3 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
只睡四小时3 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
奇思妙想聪明勤奋的小羊3 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型
lpfasd1233 天前
2026年第38周GitHub趋势周报
python·科技·github
IZero073 天前
Jev 与 Laya
python·语言模型