邮件文本分类: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 篇文档也能跑)。

二、数据加载

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 向量化器要求输入是可迭代的字符串序列

data_train = data_train["text"].tolist()
target_train = target_train["target"].tolist()

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

四、CountVectorizer 词频向量化

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

from sklearn.feature_extraction.text import CountVectorizer

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

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

# 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。

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)

# 待预测的 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)的权重,突出"有区分度"的关键词。

from sklearn.feature_extraction.text import TfidfVectorizer

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

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

八、Count vs TF-IDF 对比

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

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

九、完整 Pipeline 部署

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

中文场景标准三件套:

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 篇

十三、调参与超参数

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_rangeN-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例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值