邮件文本分类: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例

相关推荐
码艺-Alimjan1 小时前
维吾尔语数字转文本
java·javascript·python·算法·go
天空属于哈夫克31 小时前
企业微信 API 自动发送消息:从流程到实战
python·自动化·企业微信
SunnyDays10111 小时前
如何使用 Python 给 PDF 添加附件:文档附件与附件注释
开发语言·python·pdf
步行cgn1 小时前
@Value 详解:Spring 属性注入的核心注解
java·python·spring
SamChan901 小时前
PDF翻译服务端到端基准测试:4款主流方案的吞吐量、延迟、内存占用对比
服务器·网络·python·ai·pdf·wpf
optiz1 小时前
单细胞数据分析--多数据整合harmony聚类
数据挖掘·数据分析·聚类
KKKlucifer2 小时前
多模态数据精准识别:智能分类分级引擎在运营商场景的技术突破
人工智能·分类·数据挖掘
小白说大模型2 小时前
Hermes 全配置指南:从裸版到 AI Agent 天花板
大数据·人工智能·学习·算法·机器学习·数据挖掘
2501_937860942 小时前
Java 文件操作与IO(下):字节流、字符流实战IO读写
java·开发语言·python