使用Python实现一个简单的文本分类器
在现代人工智能和自然语言处理(NLP)领域,文本分类是一个非常常见且重要的任务。文本分类的目标是将一段文本分配到一个或多个预定义的类别中。例如,垃圾邮件检测、新闻分类、情感分析等都是文本分类的应用场景。
本文将介绍如何使用Python和机器学习技术来构建一个简单的文本分类器。我们将使用scikit-learn
库以及经典的20 Newsgroups
数据集来演示整个流程,并提供完整的代码示例。
环境准备
在开始之前,请确保你已经安装了以下 Python 库:
pip install scikit-learn matplotlib numpy pandas
这些库将用于数据加载、特征提取、模型训练和结果可视化。
项目概述
我们将完成以下步骤:
加载并查看数据集。对文本进行预处理。将文本转换为数值特征向量(TF-IDF)。使用朴素贝叶斯算法训练分类器。评估模型性能。进行预测并展示结果。加载数据集
我们使用 sklearn.datasets.fetch_20newsgroups
提供的 20 Newsgroups 数据集。这是一个常用于文本分类的公开数据集,包含大约 20,000 篇新闻文档,分成 20 个不同的新闻组。
from sklearn.datasets import fetch_20newsgroups# 只选择部分类别以简化问题categories = ['alt.atheism', 'comp.graphics', 'rec.sport.baseball', 'sci.space', 'talk.politics.mideast']# 加载训练集和测试集train_data = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=42)test_data = fetch_20newsgroups(subset='test', categories=categories, shuffle=True, random_state=42)print("训练集样本数:", len(train_data.data))print("测试集样本数:", len(test_data.data))print("类别标签:", train_data.target_names)
输出:
训练集样本数: 2759测试集样本数: 1839类别标签: ['alt.atheism', 'comp.graphics', 'rec.sport.baseball', 'sci.space', 'talk.politics.mideast']
文本预处理与特征提取
由于计算机无法直接处理原始文本,我们需要将其转换为数值形式。一种常见的方法是使用 TF-IDF(Term Frequency-Inverse Document Frequency)向量化器。
from sklearn.feature_extraction.text import TfidfVectorizer# 初始化 TF-IDF 向量化器vectorizer = TfidfVectorizer(stop_words='english')# 拟合并转换训练集文本X_train = vectorizer.fit_transform(train_data.data)y_train = train_data.target# 转换测试集文本X_test = vectorizer.transform(test_data.data)y_test = test_data.targetprint("特征维度:", X_train.shape[1])
输出:
特征维度: 19063
这里可以看到,每个文档被表示为一个长度为 19063 的稀疏向量,对应于所有不同词汇的 TF-IDF 值。
训练分类器
我们使用 Multinomial Naive Bayes 分类器,这是文本分类中常用的模型之一。
from sklearn.naive_bayes import MultinomialNBfrom sklearn.metrics import classification_report, accuracy_score# 初始化并训练模型clf = MultinomialNB()clf.fit(X_train, y_train)# 在测试集上预测y_pred = clf.predict(X_test)# 输出准确率和分类报告print("准确率:", accuracy_score(y_test, y_pred))print(classification_report(y_test, y_pred, target_names=train_data.target_names))
输出示例:
准确率: 0.8956 precision recall f1-score support 0 0.91 0.92 0.92 319 1 0.92 0.94 0.93 389 2 0.90 0.90 0.90 396 3 0.89 0.87 0.88 391 4 0.91 0.90 0.90 344 accuracy 0.90 1839 macro avg 0.90 0.90 0.90 1839weighted avg 0.90 0.90 0.90 1839
从结果可以看出,我们的分类器在测试集上的准确率为约 89.56%,对于一个简单的模型来说表现相当不错。
可视化混淆矩阵
为了更直观地了解分类器的表现,我们可以绘制混淆矩阵。
import seaborn as snsimport matplotlib.pyplot as pltfrom sklearn.metrics import confusion_matrix# 计算混淆矩阵cm = confusion_matrix(y_test, y_pred)# 绘制热力图plt.figure(figsize=(10, 8))sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=train_data.target_names, yticklabels=train_data.target_names)plt.xlabel('预测标签')plt.ylabel('真实标签')plt.title('混淆矩阵')plt.show()
这张热力图可以帮助我们识别哪些类别之间容易混淆。
完整代码整合
以下是上述所有步骤的完整代码:
from sklearn.datasets import fetch_20newsgroupsfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.naive_bayes import MultinomialNBfrom sklearn.metrics import classification_report, accuracy_score, confusion_matriximport seaborn as snsimport matplotlib.pyplot as plt# 1. 加载数据categories = ['alt.atheism', 'comp.graphics', 'rec.sport.baseball', 'sci.space', 'talk.politics.mideast']train_data = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=42)test_data = fetch_20newsgroups(subset='test', categories=categories, shuffle=True, random_state=42)# 2. 特征提取vectorizer = TfidfVectorizer(stop_words='english')X_train = vectorizer.fit_transform(train_data.data)X_test = vectorizer.transform(test_data.data)y_train, y_test = train_data.target, test_data.target# 3. 模型训练clf = MultinomialNB()clf.fit(X_train, y_train)# 4. 预测与评估y_pred = clf.predict(X_test)print("准确率:", accuracy_score(y_test, y_pred))print(classification_report(y_test, y_pred, target_names=train_data.target_names))# 5. 可视化混淆矩阵cm = confusion_matrix(y_test, y_pred)plt.figure(figsize=(10, 8))sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=train_data.target_names, yticklabels=train_data.target_names)plt.xlabel('预测标签')plt.ylabel('真实标签')plt.title('混淆矩阵')plt.show()
总结与拓展
本文介绍了如何使用 Python 构建一个简单的文本分类系统。虽然我们使用的是传统的机器学习方法(如朴素贝叶斯 + TF-IDF),但在许多实际应用中仍然具有很高的实用价值。
拓展建议:
尝试其他分类器:可以尝试支持向量机(SVM)、随机森林(Random Forest)甚至深度学习模型(如 LSTM、BERT)来提升性能。使用交叉验证:对模型进行 K 折交叉验证,提高泛化能力。优化参数:使用GridSearchCV
或 RandomizedSearchCV
来调优模型超参数。部署模型:将训练好的模型封装成 API 接口,供其他系统调用。参考资料
Scikit-learn 官方文档20 Newsgroups DatasetNatural Language Processing with Python (NLTK Book)如果你对 NLP 和文本分类感兴趣,欢迎继续关注本系列文章,后续我们会介绍基于深度学习的文本分类方法,包括使用 PyTorch 和 Transformers 实现 BERT 文本分类器等内容。