解密垃圾邮件分类:基于SVM的数据挖掘项目

垃圾邮件(Spam)的泛滥成灾一直是电子邮件系统中的一个严峻问题。随着垃圾邮件技术的不断演变,传统的过滤方法逐渐显得力不从心。因此,本项目旨在利用支持向量机(SVM)这一强大的机器学习工具,实现对垃圾邮件的高效分类,为用户提供更清爽、高效的电子邮件体验。

一、项目目标

本项目的主要目标是构建一个基于SVM的垃圾邮件分类系统。通过对两个不同来源的数据集(trec 和 enron)进行综合分析和处理,我将展示整个数据挖掘项目的过程,包括数据的预处理、特征工程、模型训练与调优,并最终通过实验结果分析验证模型的性能。

二、数据集来源及介绍

我使用了两个不同来源的数据集,其中trec数据集已经经过处理,enron数据集需要进行清洗和整理:

  • trec(Emails for spam or ham classification (Trec 2007) (kaggle.com)
  • enron(MWiechmann/enron_spam_data: The Enron-Spam dataset preprocessed in a single, clean csv file. (github.com)

trec 数据集提供了多样的垃圾邮件和非垃圾邮件样本,而 enron 数据集则包含了来自 enron 公司的电子邮件数据。这两个数据集的结合将有助于提高模型的泛化能力。

三、数据处理与准备

在进行垃圾邮件分类项目之前,我们首先需要对数据进行准备和预处理。

3.1 trec数据集

3.1.1 数据导入与查看

pythonCopy code
trec = pd.read_csv(r"D:\\BUZZ\\\\数据挖掘\\垃圾邮件分类\\email_text.csv")
display(trec)

原因:数据一开始就是预处理过的,因此通过导入数据和查看前几行,我们可以验证数据的完整性,确保没有导入错误或缺失的信息。

3.1.2 缺失值和重复值处理

pythonCopy code
trec.isna().sum()
trec.duplicated().sum()

原因:尽管数据已经被预处理,但为了确保数据的完整性,我们仍然进行了缺失值和重复值的验证。使用isna()方法检查每一列是否存在缺失值,sum()方法得到缺失值的数量。使用duplicated()方法检查是否有重复行,sum()方法计算重复值的数量。

3.2 enron数据集

3.2.1 数据导入与查看

pythonCopy code
enron = pd.read_csv(r"D:\\BUZZ\\\\数据挖掘\\垃圾邮件分类\\enron_spam_data.csv")
display(enron)

原因: enron数据集的导入和查看步骤与trec相似。同样,通过导入数据和查看前几行,我们验证了数据的完整性。

3.2.2 缺失值和重复值处理

pythonCopy code
enron.isna().sum()
enron.duplicated().sum()
enron.dropna(inplace=True)
enron.drop_duplicates(inplace=True)

原因: 与trec不同,enron数据集是原始数据,未经过预处理。我们首先使用**isna()方法检查缺失值,sum()方法得到每列缺失值的数量。然后,使用duplicated()方法检查重复值,sum()方法计算重复值的数量。接着,使用dropna方法删除缺失值,drop_duplicates**方法删除重复值。

3.2.3 数据选择性分析与处理

pythonCopy code
pythonCopy code
# 只分析邮件正文内容,因此不需要其他列
enron.drop(['Message ID', "Subject", "Date"], axis=1, inplace=True)

# 检查缺失值
enron.isna().sum()

# 删除缺失值
enron.dropna(inplace=True)

# 检查重复值
enron.duplicated().sum()

# 删除重复值
enron.drop_duplicates(inplace=True)

# 使用 LabelEncoder 将 "ham" 替换为 0,"spam" 替换为 1
label_encoder = preprocessing.LabelEncoder()
enron['label'] = label_encoder.fit_transform(enron['Spam/Ham'])
enron.drop('Spam/Ham', axis=1, inplace=True)
enron.rename(columns={'Message': 'text'}, inplace=True)

原因: 由于我们只对邮件正文内容进行分析,因此在这一步骤中,我们删除了与正文内容无关的列。然后,我们再次检查并处理缺失值和重复值。最后,使用**LabelEncoder**将"ham"标记为0,"spam"标记为1,为模型训练做准备。

3.3 数据合并、抽样及划分

在这一步中,我首先合并了trec和enron两个数据集,再次检查了合并后的数据集是否有重复值。然后,我进行了随机抽样,保留了原始数据集的10%。最后,我使用**train_test_split**方法将数据集划分为训练集和测试集,其中20%分给测试集,80%分给训练集。这样的划分有助于我们在训练模型时验证其性能。

3.3.1 数据合并与抽样

pythonCopy code
combined = pd.concat([trec, enron], ignore_index=True)
combined.duplicated().sum()
combined = combined.sample(frac=0.1, random_state=1)

原因: 将两个数据集合并为一个可以帮助我们更方便地进行后续的分析和建模。为了减小数据规模,提高模型训练效率,我们使用了**sample**方法对合并后的数据进行了随机抽样。这也有助于避免在处理大规模数据时过度占用计算资源。

3.3.2 数据集划分

pythonCopy code
pythonCopy code
# 合并数据集
combined = pd.concat([trec, enron], ignore_index=True)

# 合并后检查重复值
combined.duplicated().sum()

# 对 combined 数据集进行随机抽样,保留原始数据集的 10%
combined = combined.sample(frac=0.1, random_state=1)
combined

# 分割数据集 (20%分给测试集,80%分给训练集)
x = combined['text']
y = combined['label']
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1)

将数据集划分为训练集和测试集,其中20%分给测试集,80%分给训练集。这样的划分有助于我们在训练模型时验证其性能。


注释解释:

  • 删除缺失值的原因: 电子邮件正文缺失对垃圾邮件分类任务没有直接贡献,且数目较少,因此选择直接删除缺失值。这有助于保持数据集的质量和可用性。
  • 删除重复值的原因:
    1. 过拟合风险: 数据集中存在重复的电子邮件可能导致模型在新数据上的泛化性能下降,因为模型会过度学习这些重复的模式。
    2. 样本偏好: 如果某些电子邮件出现多次,模型可能更倾向于这些样本,引入对特定电子邮件的偏好。删除重复值有助于保持数据集的平衡性。
    3. 简化数据集: 删除重复值可以简化数据集,使数据更干净、易于理解,并减少对计算资源的需求。

这样的处理步骤旨在确保数据的质量,为后续建模和分析提供可靠的基础。

四、 数据特征提取与向量化

在进行垃圾邮件分类的任务中,文本数据需要被转换为机器学习模型可以处理的数值型数据。这一过程通常包括文本的特征提取和向量化,而我们使用了TF-IDF(Term Frequency-Inverse Document Frequency)向量化方法。

4.1 TF-IDF向量化

pythonCopy code
vectorizer = TfidfVectorizer()
x_train_vectorized = vectorizer.fit_transform(x_train)
x_test_vectorized = vectorizer.transform(x_test)

原因: 对于支持向量机(SVM)等基于数值型数据的机器学习模型,文本数据通常需要经过适当的处理和特征提取才能用于训练和预测。TF-IDF向量化是一种常见的文本特征提取方法,它将文本数据转换为稀疏的数值向量,以便机器学习算法能够理解和处理。TF-IDF考虑了单词在文档中的重要性,降低了常见词汇的权重,增加了罕见词汇的权重。

五、 模型训练与调优

5.1 初始化SVM模型

pythonCopy code
svc = SVC()

原因: 在这个项目中,我们选择使用支持向量机(SVM)作为分类模型。通过初始化一个SVM分类器,我们为后续的超参数调优和模型训练做好了准备。

5.2 使用GridSearchCV查找最佳超参数组合

pythonCopy code
param_grid = {'C': [0.1, 1, 10], 'kernel': ['linear', 'rbf'], 'gamma': ['scale', 'auto']}
grid_search = GridSearchCV(svc, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid_search.fit(x_train_vectorized, y_train)

原因: 为了提高模型的性能,我们使用了网格搜索(Grid Search)来搜索最佳的超参数组合。通过定义超参数的范围,GridSearchCV尝试了不同的组合,并使用交叉验证来评估它们的性能。在这里,我们调整了SVM模型的惩罚参数C、核函数(linear或rbf)和gamma参数。

5.3 使用最佳超参数重新训练SVM模型

pythonCopy code
best_svm_gpu = grid_search.best_estimator_
best_svm_gpu.fit(x_train_vectorized, y_train)

原因: 确定了最佳超参数组合后,我们使用这些参数重新训练了SVM模型,以便获得更好的性能。

六、 实验结果分析与总结

6.1 在测试集上计算模型评估指标

为了评估模型的性能,我在测试集上计算了准确率、精确度召回率等指标。这些指标提供了对模型在新数据上表现的全面了解。在垃圾邮件分类任务中,准确率衡量了模型正确分类的比例,精确度度量了垃圾邮件被正确分类的比例,召回率则度量了模型找到所有垃圾邮件的能力。

pythonCopy code
predictions = best_svm_gpu.predict(x_test_vectorized)
accuracy = accuracy_score(y_test, predictions)
precision = precision_score(y_test, predictions)
recall = recall_score(y_test, predictions)

print('准确率: ', accuracy)
print('精确度: ', precision)
print('召回率: ', recall)

结果:

  • 准确率(Accuracy):98.08%
  • 精确度(Precision):97.59%
  • 召回率(Recall):98.89%

6.2 使用自定义输入测试模型

通过输入一条新的邮件内容进行模型测试,查看模型对未见过的数据的分类预测。

pythonCopy code
new_email = '亲爱的朋友,我有一个很好的投资机会给你!'
new_email_vectorized = vectorizer.transform([new_email])
prediction = best_svm_gpu.predict(new_email_vectorized)
print('预测结果:', prediction)

结果: 模型预测结果为1,即该邮件被分类为垃圾邮件。

通过以上实验结果,我们可以得出结论:

  • 模型在测试集上表现良好,具有高准确率(98.08%)和高召回率(98.89%)。
  • 模型对新的、未见过的邮件数据也能做出有效的分类预测,体现了其泛化能力。
  • 该垃圾邮件分类系统可以在实际应用中发挥作用,帮助用户过滤垃圾邮件,提升邮件处理效率。

通过对实验结果的分析,验证了模型的有效性,也为垃圾邮件分类任务提供了可靠的解决方案。在实际应用中,该模型可以作为一个自动化工具,帮助用户识别和处理大量的电子邮件数据。

你可能感兴趣的:(数据挖掘,分类,支持向量机)