垃圾邮件(Spam)的泛滥成灾一直是电子邮件系统中的一个严峻问题。随着垃圾邮件技术的不断演变,传统的过滤方法逐渐显得力不从心。因此,本项目旨在利用支持向量机(SVM)这一强大的机器学习工具,实现对垃圾邮件的高效分类,为用户提供更清爽、高效的电子邮件体验。
本项目的主要目标是构建一个基于SVM的垃圾邮件分类系统。通过对两个不同来源的数据集(trec 和 enron)进行综合分析和处理,我将展示整个数据挖掘项目的过程,包括数据的预处理、特征工程、模型训练与调优,并最终通过实验结果分析验证模型的性能。
我使用了两个不同来源的数据集,其中trec数据集已经经过处理,enron数据集需要进行清洗和整理:
trec 数据集提供了多样的垃圾邮件和非垃圾邮件样本,而 enron 数据集则包含了来自 enron 公司的电子邮件数据。这两个数据集的结合将有助于提高模型的泛化能力。
在进行垃圾邮件分类项目之前,我们首先需要对数据进行准备和预处理。
pythonCopy code
trec = pd.read_csv(r"D:\\BUZZ\\\\数据挖掘\\垃圾邮件分类\\email_text.csv")
display(trec)
原因:数据一开始就是预处理过的,因此通过导入数据和查看前几行,我们可以验证数据的完整性,确保没有导入错误或缺失的信息。
pythonCopy code
trec.isna().sum()
trec.duplicated().sum()
原因:尽管数据已经被预处理,但为了确保数据的完整性,我们仍然进行了缺失值和重复值的验证。使用isna()
方法检查每一列是否存在缺失值,sum()
方法得到缺失值的数量。使用duplicated()
方法检查是否有重复行,sum()
方法计算重复值的数量。
pythonCopy code
enron = pd.read_csv(r"D:\\BUZZ\\\\数据挖掘\\垃圾邮件分类\\enron_spam_data.csv")
display(enron)
原因: enron数据集的导入和查看步骤与trec相似。同样,通过导入数据和查看前几行,我们验证了数据的完整性。
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
**方法删除重复值。
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,为模型训练做准备。
在这一步中,我首先合并了trec和enron两个数据集,再次检查了合并后的数据集是否有重复值。然后,我进行了随机抽样,保留了原始数据集的10%。最后,我使用**
train_test_split
**方法将数据集划分为训练集和测试集,其中20%分给测试集,80%分给训练集。这样的划分有助于我们在训练模型时验证其性能。
pythonCopy code
combined = pd.concat([trec, enron], ignore_index=True)
combined.duplicated().sum()
combined = combined.sample(frac=0.1, random_state=1)
原因: 将两个数据集合并为一个可以帮助我们更方便地进行后续的分析和建模。为了减小数据规模,提高模型训练效率,我们使用了**sample
**方法对合并后的数据进行了随机抽样。这也有助于避免在处理大规模数据时过度占用计算资源。
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%分给训练集。这样的划分有助于我们在训练模型时验证其性能。
注释解释:
这样的处理步骤旨在确保数据的质量,为后续建模和分析提供可靠的基础。
在进行垃圾邮件分类的任务中,文本数据需要被转换为机器学习模型可以处理的数值型数据。这一过程通常包括文本的特征提取和向量化,而我们使用了TF-IDF(Term Frequency-Inverse Document Frequency)向量化方法。
pythonCopy code
vectorizer = TfidfVectorizer()
x_train_vectorized = vectorizer.fit_transform(x_train)
x_test_vectorized = vectorizer.transform(x_test)
原因: 对于支持向量机(SVM)等基于数值型数据的机器学习模型,文本数据通常需要经过适当的处理和特征提取才能用于训练和预测。TF-IDF向量化是一种常见的文本特征提取方法,它将文本数据转换为稀疏的数值向量,以便机器学习算法能够理解和处理。TF-IDF考虑了单词在文档中的重要性,降低了常见词汇的权重,增加了罕见词汇的权重。
pythonCopy code
svc = SVC()
原因: 在这个项目中,我们选择使用支持向量机(SVM)作为分类模型。通过初始化一个SVM分类器,我们为后续的超参数调优和模型训练做好了准备。
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参数。
pythonCopy code
best_svm_gpu = grid_search.best_estimator_
best_svm_gpu.fit(x_train_vectorized, y_train)
原因: 确定了最佳超参数组合后,我们使用这些参数重新训练了SVM模型,以便获得更好的性能。
为了评估模型的性能,我在测试集上计算了准确率、精确度和召回率等指标。这些指标提供了对模型在新数据上表现的全面了解。在垃圾邮件分类任务中,准确率衡量了模型正确分类的比例,精确度度量了垃圾邮件被正确分类的比例,召回率则度量了模型找到所有垃圾邮件的能力。
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)
结果:
通过输入一条新的邮件内容进行模型测试,查看模型对未见过的数据的分类预测。
pythonCopy code
new_email = '亲爱的朋友,我有一个很好的投资机会给你!'
new_email_vectorized = vectorizer.transform([new_email])
prediction = best_svm_gpu.predict(new_email_vectorized)
print('预测结果:', prediction)
结果: 模型预测结果为1,即该邮件被分类为垃圾邮件。
通过以上实验结果,我们可以得出结论:
通过对实验结果的分析,验证了模型的有效性,也为垃圾邮件分类任务提供了可靠的解决方案。在实际应用中,该模型可以作为一个自动化工具,帮助用户识别和处理大量的电子邮件数据。