文本分类案例

wen java案例 2

本文目录导读:

文本分类案例

  1. 问题定义
  2. 环境准备
  3. 完整代码实现
  4. 关键技巧与总结
  5. 扩展建议

这是一个非常经典且完整的文本分类案例,我将以一个具体的场景——垃圾短信(Spam)与正常短信(Ham)分类为例,使用Python和机器学习库(Scikit-learn)从头到尾演示一遍。

这个案例涵盖了文本分类的核心步骤:数据加载、文本预处理、特征提取(TF-IDF)、模型训练(朴素贝叶斯)、评估与预测。


问题定义

目标:给定一条短信内容,判断它是“垃圾短信”(Spam)还是“正常短信”(Ham)。 数据集:使用公开的 SMS Spam Collection 数据集(通常包含约 5574 条短信)。

环境准备

需要安装以下库:

pip install pandas scikit-learn nltk

完整代码实现

1 导入库与加载数据

import pandas as pd
import re
import nltk
from nltk.corpus import stopwords
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 下载停用词(第一次运行需要取消注释)
# nltk.download('stopwords')
# 加载数据(假设数据文件为 'spam.csv',常见格式:两列:label, message)
df = pd.read_csv('spam.csv', encoding='latin-1')
# 通常数据集会有多余的无名列,只保留前两列
df = df[['v1', 'v2']]
df.columns = ['label', 'message']
# 查看数据分布
print(df['label'].value_counts())
# 输出示例:
# ham   4825
# spam  747

2 文本预处理

我们需要将文本清洗干净:删除标点、数字、转换为小写、去除停用词(如 “the”, “is”, “a” 等)。

nltk.download('stopwords')
stop_words = set(stopwords.words('english'))
def clean_text(text):
    # 1. 只保留字母和空格(去除标点和数字)
    text = re.sub('[^a-zA-Z]', ' ', text)
    # 2. 全部转为小写
    text = text.lower()
    # 3. 分词并去除停用词
    words = text.split()
    words = [w for w in words if w not in stop_words]
    return ' '.join(words)
# 应用清洗函数
df['cleaned_message'] = df['message'].apply(clean_text)
print(df[['message', 'cleaned_message']].head())

3 划分训练集与测试集

# 将标签转换为数值:ham -> 0, spam -> 1
df['label_num'] = df['label'].map({'ham': 0, 'spam': 1})
X = df['cleaned_message']  # 特征:清洗后的文本
y = df['label_num']        # 标签
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

4 特征工程:TF-IDF向量化

文本必须转化为数值向量。TF-IDF(词频-逆文档频率)能有效降低常见词(如 “hello”, “ok”)的权重,突出特定文档中的关键词。

# 初始化 TF-IDF 向量化器
# max_features=5000 表示只取前5000个最重要的词,避免维度爆炸
vectorizer = TfidfVectorizer(max_features=5000)
# 在训练集上学习并转换
X_train_tfidf = vectorizer.fit_transform(X_train)
# 在测试集上仅转换(使用训练集学到的词汇表)
X_test_tfidf = vectorizer.transform(X_test)
print(f"训练集向量形状: {X_train_tfidf.shape}")  # 输出: (4457, 5000)

5 训练模型(朴素贝叶斯)

朴素贝叶斯在文本分类(如垃圾邮件过滤)中表现优异,因为它假设特征之间条件独立,非常适合高维稀疏数据。

model = MultinomialNB()
model.fit(X_train_tfidf, y_train)

6 预测与评估

# 预测测试集
y_pred = model.predict(X_test_tfidf)
# 评估指标
print("准确率:", accuracy_score(y_test, y_pred))
print("\n分类报告:\n", classification_report(y_test, y_pred, target_names=['Ham', 'Spam']))
print("混淆矩阵:\n", confusion_matrix(y_test, y_pred))

典型输出(因为随机拆分,数值可能略有不同):

准确率: 0.9802
分类报告:
               precision    recall  f1-score   support
         Ham       0.98      1.00      0.99       965
        Spam       1.00      0.86      0.92       150
    accuracy                           0.98      1115
   macro avg       0.99      0.93      0.96      1115
weighted avg       0.98      0.98      0.98      1115
混淆矩阵:
 [[962   3]
 [ 21 129]]

解读:模型整体准确率 98%,对于正常短信(Ham)几乎没有误判(965个中只错了3个),对于垃圾短信(Spam)查全率(Recall)86%,意味着有14%的垃圾短信未被识别(漏网之鱼),查准率(Precision)100%,说明模型预测为垃圾短信的案例中,全部是真正的垃圾短信。

7 使用模型进行单条预测

def predict_message(message):
    cleaned = clean_text(message)
    vectorized = vectorizer.transform([cleaned])
    prediction = model.predict(vectorized)[0]
    prob = model.predict_proba(vectorized)[0]  # [ham_prob, spam_prob]
    label = 'Spam' if prediction == 1 else 'Ham'
    return label, prob[1]  # 返回标签和垃圾概率
# 测试几条新的消息
print(predict_message("Congratulations! You've won a $1000 Walmart gift card. Click here to claim now."))
print(predict_message("Hey, are we still meeting for lunch at 12?"))

输出示例

('Spam', 0.9998)
('Ham', 0.0001)

关键技巧与总结

步骤 常用方法 说明
数据清洗 正则表达式、停用词 去除噪音,保留有效词根
特征提取 TF-IDF 比单纯词袋模型(CountVectorizer)效果更好
模型选择 朴素贝叶斯(首选)、SVM、Logistic回归 对于线性可分的高维稀疏数据,朴素贝叶斯速度快且效果好
模型优化 调整max_features、使用n-gram(如2-gram) 捕获短语特征 (“win prize”) 能提升垃圾识别
评估指标 准确率、召回率、F1-score 对于不平衡数据(本例Ham:Spam ≈ 6:1),建议关注Spam类别的召回率

扩展建议

  • 使用词干提取(Stemming)或词形还原(Lemmatization):将“running”变为“run”,进一步统一词形。
  • 引入深度学习方法:使用Word2Vec + 神经网络(LSTM/CNN),处理更复杂的语义,如讽刺、上下文。
  • 处理中文文本:需要分词(如jieba库),停用词为中文常见字词,向量化一样使用TF-IDF。

这个案例可以直接复制到 Jupyter Notebook 或 Python 环境中运行,如果你有特定的数据集(如中文新闻分类、情感分析),核心流程完全一致,只需调整预处理环节即可。

抱歉,评论功能暂时关闭!