目录
3.垃圾短信分类的机器学习实现:SVM、朴素贝叶斯与决策树的比较
4.2垃圾短信分类的机器学习实现:SVM、朴素贝叶斯与决策树的比较
1.知识简介
支持向量机(Support Vector Machine,SVM)是一种用于分类和回归的监督学习模型,旨在通过构建一个超平面将不同类别的数据点分隔开,以最大化类别之间的间隔。SVM 主要有以下几个特点和关键点:
1.最大间隔分割:
- SVM 寻找一个超平面,使得不同类别的数据点之间的间隔最大化。最大间隔有助于提高模型的泛化能力,减少过拟合的可能。
2.支持向量:
- 支持向量是靠近决策边界的那些数据点。SVM 仅依赖这些支持向量来构建模型,而不是所有的训练数据,从而降低了计算复杂性并增强了模型的鲁棒性。
3.核函数:
SVM 可以通过核函数将数据映射到高维空间,以处理非线性问题。常用的核函数有:
- 线性核函数:适用于线性可分问题,将输入数据直接映射到高维空间,通过计算样本之间的内积衡量相似度。
- 多项式核函数:通过多项式计算样本间的相似度,能够处理一定程度的非线性问题,但计算复杂度较高。
- 高斯核函数(RBF 核函数):是最常用的核函数之一,通过将数据映射到无穷维的高维空间,适合处理复杂的非线性关系,并具有较好的鲁棒性和泛化能力。
- sigmoid 核函数:使用 sigmoid 函数计算相似度,主要用于二分类问题,在神经网络中也有广泛应用。
核函数的选择对 SVM 的性能至关重要。通常,线性核适用于线性可分问题,高斯核适合于非线性可分问题,多项式核和 sigmoid 核在某些特定问题中也有一定应用。
4.正则化:
- SVM 引入正则化参数(C)在最大化间隔和降低分类错误之间进行权衡,从而防止过拟合。较大的 C 值会减少分类错误,但可能增加过拟合的风险。
5.适用性广泛:
- SVM 既可以用于二分类问题,也可以通过一些方法拓展到多分类问题。在处理高维数据(例如文本分类、基因表达数据分析等)时表现出色,因而被广泛应用于图像识别、生物信息学和文本分类等领域。
6.参数选择:
- SVM 的性能依赖于合适的参数设置,如正则化参数 C 和核函数参数(例如 RBF 核的参数 gamma)。这些参数的合理选择对模型的泛化能力至关重要,通常可以使用交叉验证等方法来确定最优参数组合。
总之,SVM 作为一种有效的分类工具,因其较强的泛化能力和对高维数据的适应性而广泛应用于多个领域。通过选择适当的核函数和优化参数,SVM 能够处理多种线性和非线性分类任务。
2.SVM 支持向量机模型训练与可视化报告
本报告展示了如何使用支持向量机(SVM)对随机生成的数据进行分类,通过使用 Python 编程语言和相关模块(如 scikit-learn
和 matplotlib
),实现数据生成、模型训练、决策边界绘制以及结果的可视化,帮助更好地理解 SVM 在分类问题中的应用。
2.1 导入本项目所需的模块和包
(1)目的
导入实现整个项目所需的模块和库,为后续的数据生成、训练模型和可视化做好准备。确保所有的必要工具在代码中可以正常使用,并支持中文显示。
- 数值计算和数组操作:使用
numpy
进行数值运算和矩阵处理,例如数据的生成、形状变换等。 - 绘制图形和可视化:使用
matplotlib.pyplot
进行数据可视化,帮助理解数据的特征分布和模型的决策边界。 - 支持向量机的训练和预测:使用
svm
模块(来自scikit-learn
),可以快速实现支持向量机的模型构建、训练和预测。 - 生成模拟数据集:使用
make_blobs
生成可控的线性可分的数据集,以帮助演示 SVM 分类的效果。 - 支持中文显示:设置
matplotlib
字体为 SimHei,解决中文乱码问题,并确保坐标轴负号显示正确。
(2)代码实现
# 导入所需模块
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs # 修正了make_blobs拼写错误
# 设置字体为 SimHei,以支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False # 解决坐标轴负号显示问题
(3)代码解释
import numpy as np
:导入numpy
模块,用于处理数据数组和数值计算,特别是在数据生成和形状变换中起到重要作用。import matplotlib.pyplot as plt
:导入matplotlib.pyplot
模块,用于绘制图形,如散点图、超平面等,帮助可视化数据分布和决策边界。from sklearn import svm
:导入svm
模块,svm.SVC
是支持向量机分类器的实现,可以用于构建、训练和预测模型。from sklearn.datasets import make_blobs
:make_blobs
方法用于生成模拟的线性可分数据集,方便我们测试分类器的效果。- 设置
plt.rcParams
字体选项:为了支持中文显示,确保在绘图时不会出现乱码,并且保证负号在坐标轴上能正确显示。
2.2 随机生成线性可分的数据并可视化
(1)目的
生成一组二维线性可分的数据集,数据的特征包括 x1
和 x2
,类别用 y
表示。生成数据后进行可视化,以观察其是否具有线性可分性。
- 数据生成:通过随机生成样本,模拟线性可分的实际场景。这些数据点可以用于训练支持向量机模型,以便学习到一个能够有效划分两类数据的超平面。
- 可视化数据:通过绘制散点图直观地查看数据的分布情况,确定数据是否能够通过直线(或平面)进行分类。可视化的目的是验证数据是否线性可分,从而确定使用线性 SVM 是合适的。
(2)代码实现
# 生成线性可分数据
X, y = make_blobs(n_samples=40, centers=2, random_state=6)
# 可视化数据
plt.figure(figsize=(8, 6)) # 指定图像大小
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', marker='o', edgecolor='k', s=100)
plt.title("Visualization of Generated Data")
plt.xlabel('X1')
plt.ylabel('X2')
plt.grid(True)
plt.show()
(3)代码解释
- 生成数据:
make_blobs(n_samples=40, centers=2, random_state=6)
:生成 40 个样本点,分成两个类别。centers=2
表示有两个不同的类别,random_state=6
用于确保每次运行代码时生成的数据一致。X
是一个二维数组,表示每个数据点的特征(x1
和x2
),y
是一个标签数组,包含每个数据点的类别标签(0
或1
)。
- 可视化数据:
plt.figure(figsize=(8, 6))
:设置图像大小为 8x6 英寸。plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', marker='o', edgecolor='k', s=100)
:绘制数据点的散点图:X[:, 0]
和X[:, 1]
分别为两个特征(x1 和 x2)。c=y
指定颜色依据类别标签来区分,cmap='viridis'
表示选择颜色映射为viridis
。marker='o'
使用圆形标记,edgecolor='k'
设置标记的边框颜色为黑色。s=100
设置数据点的大小。
plt.xlabel
和plt.ylabel
设置了横纵坐标标签,方便理解每个轴代表的含义。plt.grid(True)
打开网格线,使图表更容易阅读。
2.3 训练 SVM 模型
(1)目的
训练一个线性支持向量机模型,以找到能够将两类数据点分开的最优超平面,并得到模型的相关参数。
- 创建 SVM 模型:使用线性核函数(
linear kernel
)来训练支持向量机,目的是找到一个最佳超平面,将数据分为两类。 - 学习模型参数:通过模型的训练来学习到数据的最优决策边界,同时输出模型的权重(
W
)和截距(b
),它们描述了决策边界的数学表达式。 - 识别支持向量:通过输出支持向量,识别哪些样本点对分类器的超平面有关键的影响。
(2)代码实现
clf = svm.SVC(kernel='linear', C=1000) # SVC为SVM的一个分类模型,选择线性核函数
clf.fit(X, y) # 使用数据X和y进行模型训练
print("模型参数W:", clf.coef_) # 输出模型的权重参数W
print("模型参数b:", clf.intercept_) # 输出模型的截距b
print("支持向量为:", clf.support_vectors_) # 输出支持向量的信息
(3)代码解释
- 创建 SVM 模型:
svm.SVC(kernel='linear', C=1000)
:使用线性核函数创建一个支持向量机分类器:kernel='linear'
:指定使用线性核来寻找数据的最优超平面。C=1000
:惩罚系数C
,用于控制误分类的容忍度,值越大越严格。如果C
过大,模型可能会过拟合。
- 训练模型:
clf.fit(X, y)
:使用生成的样本数据进行训练,让模型找到最佳的分类超平面。
- 输出模型参数:
clf.coef_
:模型的权重参数W
,用于描述超平面的方向。clf.intercept_
:模型的截距b
,用于确定超平面的位置。clf.support_vectors_
:输出支持向量,即距离决策边界最近的那些样本点。支持向量对于确定分类器的超平面至关重要。
2.4 使用新数据进行预测
(1)目的
使用训练好的 SVM 模型对新数据点进行预测,判断新数据点所属的类别。通过这一步,可以验证模型的泛化能力和预测效果。
- 测试模型的预测性能:通过给模型输入新的未见过的数据点,观察模型能否正确分类这些数据点。
- 验证模型的决策能力:测试模型对不同位置的数据点的决策,查看其是否符合预期。
(2)代码实现
# 第一个预测点
xpredict = [10, -10] # 定义一个二维数据点
xpredict = np.array(xpredict).reshape(1, -1) # 转换为适合SVM模型输入的形状
print(xpredict, "预测为:", clf.predict(xpredict), "类别") # 输出预测结果
# 第二个预测点
xpredict = [10, -2] # 定义第二个二维数据点
xpredict = np.array(xpredict).reshape(1, -1) # 同样转换为适合模型的输入格式
print(xpredict, "预测为:", clf.predict(xpredict), "类别") # 输出预测结果
(3)代码解释
- 定义预测点:
xpredict = [10, -10]
:定义一个新数据点[10, -10]
,这是一个二维数据。np.array(xpredict).reshape(1, -1)
:将数据点转换为二维数组格式,以适应 SVM 模型输入的要求。SVM 需要输入二维数组,表示多个样本的特征。
- 进行预测:
clf.predict(xpredict)
:使用训练好的模型对新数据点进行预测,输出其所属的类别标签。print(xpredict, "预测为:", clf.predict(xpredict), "类别")
:打印出预测结果,观察模型对这些新数据的分类效果。
2.5 使用 Matplotlib 进行可视化
(1)目的
绘制训练样本点、支持向量、分类超平面及决策边界,以便对支持向量机的分类过程进行直观的展示和理解。
- 展示支持向量和分类边界:通过绘图直观展示 SVM 模型学习到的决策边界以及哪些样本点作为支持向量。
- 帮助理解模型的工作机制:通过可视化决策边界和支持向量,了解模型如何利用这些样本点来确定分类超平面。
- 验证分类结果的正确性:通过观察分类边界和样本点的位置,验证模型是否成功找到有效的超平面分割两类数据。
(2)代码实现
plt.figure(figsize=(12, 8)) # 设置图像大小
scatter = plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired, alpha=0.7, edgecolors='k')
# 添加坐标和分类标签
for i in range(len(X)):
plt.text(X[i, 0] + 0.05, X[i, 1] + 0.05, f'({X[i, 0]:.2f}, {X[i, 1]:.2f})\nLabel: {y[i]}',
fontsize=9, ha='left', va='bottom', color='black',
bbox=dict(facecolor='white', alpha=0.5, edgecolor='none', boxstyle='round,pad=0.3'))
# 绘制决策边界
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)
# 绘制分类边界
contour = ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])
# 绘制支持向量
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], linewidth=1, facecolors='red', label='Support Vectors')
plt.show()
(3)代码解释
- 绘制数据点:
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired, alpha=0.7, edgecolors='k')
:绘制数据点:c=y
指定点的颜色依据类别标签。alpha=0.7
设置透明度,使重叠部分可以看到。edgecolors='k'
设置点的边框颜色为黑色。
- 添加分类标签:
- 使用
plt.text
为每个数据点添加坐标和类别信息,方便查看每个样本点的具体位置和类别。
- 使用
- 绘制决策边界:
ax = plt.gca()
获取当前图形的坐标轴对象。xlim = ax.get_xlim()
和ylim = ax.get_ylim()
获取横纵坐标轴的范围。- 创建网格
XX
和YY
,并计算每个点的决策函数值Z
。 ax.contour(XX, YY, Z, levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])
:绘制三个边界,其中0
表示超平面,-1
和1
表示支持向量边界。
- 标记支持向量:
- 使用
ax.scatter
绘制支持向量,用红色标记支持向量的位置,强调它们对决策边界的影响。
- 使用
以上每个步骤都有了更详细的目的和解释,旨在帮助您全面理解代码的意图、实现过程及其背后的原理。这样可以更好地掌握 SVM 模型的原理和应用场景,以及通过可视化手段理解模型的决策过程。
3.垃圾短信分类的机器学习实现:SVM、朴素贝叶斯与决策树的比较
3.1 加载数据集
(1) 目的
加载垃圾短信数据集,并对数据进行初步处理,以确保数据格式适合后续的分析和建模。
- 数据加载:从 CSV 文件中加载数据集,查看前几行数据以确认加载是否正确。
- 数据预处理:重命名列名并将文本标签转换为数值标签,以便后续的模型训练和预测。
(2) 代码实现
# 数据集在 "E:/AI/Jupyter/data/垃圾短信的数据.csv" 文件中
df = pd.read_csv("E:/AI/Jupyter/data/垃圾短信的数据.csv", encoding='latin-1')
# 数据预处理:重命名列名,保留需要的列
df.columns = ['type', 'text'] # 保留两列:type和text
print(df.head())
# 将标签列转换为数值,spam = 1,ham = 0
df['type'] = df['type'].map({'spam': 1, 'ham': 0})
(3) 代码解释
pd.read_csv
用于加载 CSV 文件中的数据。df.columns = ['type', 'text']
重新命名数据集中的列,以保留“type”(标签)和“text”(短信内容)。df['type'].map({'spam': 1, 'ham': 0})
将类别标签转换为数值标签,其中spam
对应 1,ham
对应 0。
3.2 特征提取
(1) 目的
将文本数据转化为特征矩阵,以便模型能够处理和理解数据。使用 TfidfVectorizer
提取文本中的重要特征。
- 文本向量化:将短信内容转换为特征矩阵,使用 TF-IDF 技术计算单词在每个文档中的重要性。
(2) 代码实现
# 使用 Tfidf 向量化将文本转化为特征矩阵
vectorizer = TfidfVectorizer(stop_words='english', max_df=0.7)
X = vectorizer.fit_transform(df['text'])
y = df['type']
(3) 代码解释
TfidfVectorizer
用于将文本数据转换为 TF-IDF 特征矩阵,去除英语停用词并设置最大文档频率为 0.7,以忽略在大部分文档中出现的常见词。X
是特征矩阵,y
是目标变量(类别标签)。
3.3 数据集划分
(1) 目的
将数据集划分为训练集和测试集,以便训练模型并在独立的数据上进行测试,评估模型的泛化能力。
(2) 代码实现
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
(3) 代码解释
train_test_split
将数据集随机划分为训练集和测试集,test_size=0.2
表示 20% 的数据用于测试。random_state=42
确保数据划分的一致性,使每次运行的结果相同。
3.4 特征选择
(1) 目的
使用卡方检验进行特征选择,以降低特征维度,去除噪声特征,提高模型的训练速度和准确性。
(2) 代码实现
# 使用卡方检验进行特征选择
selector = SelectKBest(score_func=chi2, k=3000) # 选择3000个最佳特征
X_train_selected = selector.fit_transform(X_train, y_train)
X_test_selected = selector.transform(X_test)
(3) 代码解释
SelectKBest(score_func=chi2, k=3000)
使用卡方检验选择 3000 个最佳特征。selector.fit_transform(X_train, y_train)
对训练集进行特征选择,得到降维后的特征矩阵。selector.transform(X_test)
对测试集也进行相同的特征选择。
3.5 模型选择与训练
(1) 目的
训练支持向量机模型,以便能够在测试集上进行预测。
- 训练 SVM 模型:使用线性核的 SVM 进行垃圾短信的分类训练。
(2) 代码实现
# 使用支持向量机(SVM)分类器
svm_model = SVC(kernel='linear', C=1.0, random_state=42)
# 训练SVM模型
svm_model.fit(X_train_selected, y_train)
(3) 代码解释
SVC(kernel='linear', C=1.0)
创建线性核支持向量机模型,其中C
是惩罚参数,用于控制模型的容错度。svm_model.fit(X_train_selected, y_train)
使用训练集训练 SVM 模型。
3.6 性能评估
(1) 目的
使用测试集数据对模型进行预测,并评估其分类性能,通过分类报告、混淆矩阵等指标来分析模型效果。
(2) 代码实现
# 使用测试集数据进行预测
y_pred = svm_model.predict(X_test_selected)
# 计算分类报告、混淆矩阵和准确率
print("SVM Classification Report:")
print(classification_report(y_test, y_pred))
# 绘制混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)
sns.heatmap(conf_matrix, annot=True, fmt="d", cmap="Blues")
plt.xlabel("预测标签")
plt.ylabel("真实标签")
plt.title("SVM 混淆矩阵")
plt.show()
(3) 代码解释
svm_model.predict(X_test_selected)
使用训练好的模型对测试集进行预测。classification_report(y_test, y_pred)
输出分类报告,包含准确率、召回率和 F1 分数等指标。confusion_matrix(y_test, y_pred)
生成混淆矩阵,展示预测结果与真实标签的对应关系。sns.heatmap(conf_matrix)
使用热图可视化混淆矩阵,帮助分析分类的正确性和错误类型。
3.7 与其他模型比较
(1) 目的
使用朴素贝叶斯和决策树模型对数据进行分类,与 SVM 的表现进行对比,找到表现最佳的模型。
(2) 代码实现
# 朴素贝叶斯分类器
nb_model = MultinomialNB()
nb_model.fit(X_train_selected, y_train)
y_pred_nb = nb_model.predict(X_test_selected)
print("Naive Bayes Classification Report:")
print(classification_report(y_test, y_pred_nb))
# 决策树分类器
tree_model = DecisionTreeClassifier(random_state=42)
tree_model.fit(X_train_selected, y_train)
y_pred_tree = tree_model.predict(X_test_selected)
print("Decision Tree Classification Report:")
print(classification_report(y_test, y_pred_tree))
(3) 代码解释
- 朴素贝叶斯:
MultinomialNB()
创建朴素贝叶斯分类器,用于多项式分布特征的分类任务。nb_model.fit(X_train_selected, y_train)
训练模型。nb_model.predict(X_test_selected)
使用测试集进行预测。
- 决策树:
DecisionTreeClassifier(random_state=42)
创建决策树分类器。tree_model.fit(X_train_selected, y_train)
训练模型。tree_model.predict(X_test_selected)
使用测试集进行预测。
3.8 结论与讨论
(1) 目的
比较 SVM、朴素贝叶斯和决策树的分类性能,找出最适合垃圾短信分类的模型。
(2) 代码实现
svm_accuracy = accuracy_score(y_test, y_pred)
nb_accuracy = accuracy_score(y_test, y_pred_nb)
tree_accuracy = accuracy_score(y_test, y_pred_tree)
print(f"SVM 准确率: {svm_accuracy:.2f}")
print(f"Naive Bayes 准确率: {nb_accuracy:.2f}")
print(f"决策树 准确率: {tree_accuracy:.2f}")
if svm_accuracy > max(nb_accuracy, tree_accuracy):
print("SVM 在该数据集上的表现最好。")
elif nb_accuracy > max(svm_accuracy, tree_accuracy):
print("Naive Bayes 在该数据集上的表现最好。")
else:
print("决策树在该数据集上的表现最好。")
(3) 代码解释
accuracy_score(y_test, y_pred)
计算 SVM、朴素贝叶斯和决策树的准确率。- 输出每个模型的准确率并比较,找出最优模型。
4.总体代码和结果
4.1 SVM 支持向量机模型训练与可视化
(1)总体代码
## 步骤一,导入本项目所需要的模块和包
# 导入所需模块
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs # 修正了make_blobs拼写错误
# 设置字体为 SimHei,以支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False # 解决坐标轴负号显示问题
## 步骤二,随机生成数据,随机生成 40 个样本数据,数据分为两类。数据格式为(x1,x2,y),x1、x2 为数据的特征,y 是数据所属类别。
# 生成线性可分数据
X, y = make_blobs(n_samples=40, centers=2, random_state=6) # 修正了参数中的拼写错误
# 可视化数据
plt.figure(figsize=(8, 6)) # 指定图像大小
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', marker='o', edgecolor='k', s=100) # 修正了逗号、括号等错误
plt.title("Visualization of Generated Data") # 补全标题中的引号
plt.xlabel('X1') # 修正X轴标签中的引号
plt.ylabel('X2') # 修正Y轴标签中的引号
plt.grid(True) # 显示网格
plt.show() # 展示图像
## 步骤三,训练 SVM 模型,建立好一个未训练的 SVM 模型,将训练样本传给模型进行训练
clf = svm.SVC(kernel='linear', C=1000) # SVC为SVM的一个分类模型,选择线性核函数
clf.fit(X, y) # 使用数据X和y进行模型训练
print("模型参数W:", clf.coef_) # 输出模型的权重参数W
print("模型参数b:", clf.intercept_) # 输出模型的截距b
print("支持向量为:", clf.support_vectors_) # 输出支持向量的信息
## 步骤四,使用新数据进行预测
# 第一个预测点
xpredict = [10, -10] # 定义一个二维数据点
xpredict = np.array(xpredict).reshape(1, -1) # 转换为适合SVM模型输入的形状
print(xpredict, "预测为:", clf.predict(xpredict), "类别") # 输出预测结果
# 第二个预测点
xpredict = [10, -2] # 定义第二个二维数据点
xpredict = np.array(xpredict).reshape(1, -1) # 同样转换为适合模型的输入格式
print(xpredict, "预测为:", clf.predict(xpredict), "类别") # 输出预测结果
## 步骤五,使用 matplotlib 库进行绘图,通过将间隔、划分超平面和支持向量描绘出来
# 1. 可视化数据点
plt.figure(figsize=(12, 8)) # 设置图像大小
scatter = plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired, alpha=0.7, edgecolors='k') # 绘制散点图
# 2. 在每个数据点上添加坐标和分类标签
for i in range(len(X)):
plt.text(X[i, 0] + 0.05, X[i, 1] + 0.05, f'({X[i, 0]:.2f}, {X[i, 1]:.2f})\nLabel: {y[i]}',
fontsize=9, ha='left', va='bottom', color='black',
bbox=dict(facecolor='white', alpha=0.5, edgecolor='none', boxstyle='round,pad=0.3'))
# 3. 绘制决策边界
ax = plt.gca()
xlim = ax.get_xlim() # 获取X轴范围
ylim = ax.get_ylim() # 获取Y轴范围
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape) # 计算决策函数值
# 4. 绘制分类边界
contour = ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])
# 5. 在决策边界上添加坐标标签
for i, level in enumerate(contour.levels):
for collection in contour.collections:
for path in collection.get_paths():
vertices = path.vertices
mid_point = vertices[len(vertices) // 2] # 取中点
plt.text(mid_point[0], mid_point[1], f'({mid_point[0]:.2f}, {mid_point[1]:.2f})',
fontsize=10, ha='center', va='center')
# 6. 绘制支持向量
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], linewidth=1, facecolors='red', label='Support Vectors')
plt.show() # 显示图像
## 步骤六,生成线性不可分数据
# 导入必要的库和数据生成器
from sklearn.datasets import make_moons
import numpy as np
import matplotlib.pyplot as plt
# 1. 生成线性不可分的数据(使用make_moons生成月牙形数据)
X, y = make_moons(n_samples=100, noise=0.1, random_state=6) # n_samples表示生成的数据点个数,noise增加随机噪声
# 2. 为数据添加一个随机的第三维度
Z = np.random.rand(X.shape[0]) # 生成与数据点个数相同的随机数作为第三维数据
X_3d = np.column_stack((X, Z)) # 合并二维数据X和随机生成的第三维Z,形成三维数据
# 3. 可视化三维数据点
fig = plt.figure(figsize=(14, 8)) # 设置图形的大小
ax = fig.add_subplot(111, projection='3d') # 添加一个3D坐标轴
# 绘制三维散点图
scatter = ax.scatter(X_3d[:, 0], X_3d[:, 1], X_3d[:, 2], c=y, cmap=plt.cm.Paired, alpha=0.7) # 使用颜色区分类别
# 4. 设置坐标轴标签
ax.set_xlabel('X1', fontsize=10) # 设置X轴标签
ax.set_ylabel('X2', fontsize=10) # 设置Y轴标签
ax.set_zlabel('X3', fontsize=10) # 设置Z轴标签
# 5. 调整视角
ax.view_init(elev=40, azim=40) # elev控制垂直角度,azim控制水平角度
# 6. 展示图像
plt.show() #
## 步骤七,对选择后的模型,输出分类结果的评价指标
# 1. 训练支持向量机模型,使用RBF核
clf = svm.SVC(kernel='rbf', C=1) # 选择RBF核函数,惩罚参数C设为1
clf.fit(X_3d, y) # 使用三维数据X_3d和标签y进行训练
# 2. 可视化三维数据点
fig = plt.figure(figsize=(12, 8)) # 设置图形大小
ax = fig.add_subplot(111, projection='3d') # 添加三维坐标轴
scatter = ax.scatter(X_3d[:, 0], X_3d[:, 1], X_3d[:, 2], c=y, cmap=plt.cm.Paired, alpha=0.7) # 绘制三维散点图
# 3. 绘制决策边界(超平面)
xx, yy = np.meshgrid(np.linspace(X_3d[:, 0].min(), X_3d[:, 0].max(), 20),
np.linspace(X_3d[:, 1].min(), X_3d[:, 1].max(), 20)) # 生成网格数据
zz = np.zeros(xx.shape) # 初始化zz为0,用于绘制平面
# 4. 计算决策函数数值
# for i in range(xx.shape[0]):
# for j in range(xx.shape[1]):
# z = np.array([[xx[i, j], yy[i, j], 0]]) # 生成网格中的点,Z值为0,便于绘制
# zz[i, j] = clf.decision_function(z) # 计算决策函数值,填充到zz中
for i in range(xx.shape[0]):
for j in range(xx.shape[1]):
z = np.array([[xx[i, j], yy[i, j], 0]]) # 创建一个包含单个样本的数组
zz[i, j] = clf.decision_function(z)[0] # 从数组中提取第一个标量值
# 5. 绘制决策超平面
ax.contour3D(xx, yy, zz, levels=[0], colors='k', linewidths=2) # 绘制等值为0的决策边界线
# 6. 设置图形标题和标签
ax.set_xlabel('X1', fontsize=10) # 设置X1轴标签
ax.set_ylabel('X2', fontsize=10) # 设置X2轴标签
ax.set_zlabel('X3', fontsize=10) # 设置X3轴标签
# 7. 展示图像
plt.show() # 显示图形
(2)运行结果
模型参数W: [[-0.2539717 -0.83806387]] 模型参数b: [-3.21132826] 支持向量为: [[ 7.27059007 -4.84225716] [ 5.95313618 -6.82945967] [ 7.89359985 -7.41655113]] [[ 10 -10]] 预测为: [1] 类别 [[10 -2]] 预测为: [0] 类别
(3)结果分析
4.2垃圾短信分类的机器学习实现:SVM、朴素贝叶斯与决策树的比较
(1)总体代码
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectKBest, chi2
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
from sklearn.naive_bayes import MultinomialNB
from sklearn.tree import DecisionTreeClassifier
# import matplotlib.pyplot as plt
# import seaborn as sns
# 设置字体为 SimHei,以支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False # 解决坐标轴负号显示问题
# Step 1: 加载数据集
# 假设数据集在 "spam.csv" 文件中
df = pd.read_csv("E:/AI/Jupyter/data/垃圾短信的数据.csv", encoding='latin-1')
# 数据预处理:重命名列名,保留需要的列
df.columns = ['type', 'text'] # 保留两列:type和text
print(df.head())
# 将标签列转换为数值,spam = 1,ham = 0
df['type'] = df['type'].map({'spam': 1, 'ham': 0})
# Step 2: 特征提取
# 使用 Tfidf 向量化将文本转化为特征矩阵
vectorizer = TfidfVectorizer(stop_words='english', max_df=0.7)
X = vectorizer.fit_transform(df['text'])
y = df['type']
# Step 3: 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Step 4: 特征选择
# 使用卡方检验进行特征选择
selector = SelectKBest(score_func=chi2, k=3000) # 选择3000个最佳特征
X_train_selected = selector.fit_transform(X_train, y_train)
X_test_selected = selector.transform(X_test)
# Step 5: 模型选择与训练
# 使用支持向量机(SVM)分类器
svm_model = SVC(kernel='linear', C=1.0, random_state=42)
# 训练SVM模型
svm_model.fit(X_train_selected, y_train)
# Step 6: 性能评估
# 使用测试集数据进行预测
y_pred = svm_model.predict(X_test_selected)
# 计算分类报告、混淆矩阵和准确率
print("SVM Classification Report:")
print(classification_report(y_test, y_pred))
# 绘制混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)
sns.heatmap(conf_matrix, annot=True, fmt="d", cmap="Blues")
plt.xlabel("预测标签")
plt.ylabel("真实标签")
plt.title("SVM 混淆矩阵")
plt.show()
# Step 7: 与其他模型(如朴素贝叶斯和决策树)比较
# 朴素贝叶斯分类器
nb_model = MultinomialNB()
nb_model.fit(X_train_selected, y_train)
y_pred_nb = nb_model.predict(X_test_selected)
print("Naive Bayes Classification Report:")
print(classification_report(y_test, y_pred_nb))
# 决策树分类器
tree_model = DecisionTreeClassifier(random_state=42)
tree_model.fit(X_train_selected, y_train)
y_pred_tree = tree_model.predict(X_test_selected)
print("Decision Tree Classification Report:")
print(classification_report(y_test, y_pred_tree))
# Step 8: 结论与讨论
# 比较不同模型的性能
svm_accuracy = accuracy_score(y_test, y_pred)
nb_accuracy = accuracy_score(y_test, y_pred_nb)
tree_accuracy = accuracy_score(y_test, y_pred_tree)
print(f"SVM 准确率: {svm_accuracy:.2f}")
print(f"Naive Bayes 准确率: {nb_accuracy:.2f}")
print(f"决策树 准确率: {tree_accuracy:.2f}")
if svm_accuracy > max(nb_accuracy, tree_accuracy):
print("SVM 在该数据集上的表现最好。")
elif nb_accuracy > max(svm_accuracy, tree_accuracy):
print("Naive Bayes 在该数据集上的表现最好。")
else:
print("决策树在该数据集上的表现最好。")
# Step 9: 结果分析与讨论
# 从混淆矩阵和分类报告中分析不同模型的表现
# SVM 通常在文本分类任务中表现较好,尤其是垃圾短信分类任务,它能够有效区分两类文本。
# Naive Bayes 在小样本情况下,可能表现更好,因为它假设特征之间相互独立,而在文本分类中这个假设通常是合理的。
# 决策树在文本分类中通常表现较差,容易过拟合,尤其是当特征数量很多时。
(2)运行结果
type text 0 ham Go until jurong point, crazy.. Available only ... 1 ham Ok lar... Joking wif u oni... 2 spam Free entry in 2 a wkly comp to win FA Cup fina... 3 ham U dun say so early hor... U c already then say... 4 ham Nah I don't think he goes to usf, he lives aro... SVM Classification Report: precision recall f1-score support 0 0.98 1.00 0.99 958 1 0.99 0.87 0.92 156 accuracy 0.98 1114 macro avg 0.99 0.93 0.96 1114 weighted avg 0.98 0.98 0.98 1114Naive Bayes Classification Report: precision recall f1-score support 0 0.97 1.00 0.99 958 1 1.00 0.82 0.90 156 accuracy 0.97 1114 macro avg 0.99 0.91 0.94 1114 weighted avg 0.98 0.97 0.97 1114 Decision Tree Classification Report: precision recall f1-score support 0 0.98 0.99 0.98 958 1 0.93 0.87 0.90 156 accuracy 0.97 1114 macro avg 0.95 0.93 0.94 1114 weighted avg 0.97 0.97 0.97 1114 SVM 准确率: 0.98 Naive Bayes 准确率: 0.97 决策树 准确率: 0.97 SVM 在该数据集上的表现最好。
(3)结果分析
1. SVM 模型
- 总体表现:SVM 模型在分类垃圾短信上表现最好,达到了 98% 的准确率。
- 优点:对正常短信(
ham
)的分类非常好,精确率和召回率都非常高。 - 不足:对垃圾短信(
spam
)的召回率稍有不足(87%),意味着部分垃圾短信未被正确识别。
2. 朴素贝叶斯模型
- 总体表现:朴素贝叶斯模型的准确率为 97%,略低于 SVM。
- 特点:对
spam
类别的精确率非常高,但召回率较低(82%),说明有较多的垃圾短信被误分类为正常短信。
3. 决策树模型
- 总体表现:决策树模型的准确率为 97%,与朴素贝叶斯相近。
- 特点:对垃圾短信的召回率为 87%,但在
ham
类别上略有误分类的情况,导致整体的表现略逊于 SVM。
(4)总结
- 最佳模型:SVM 在垃圾短信分类任务中表现最好,具有最高的准确率和较高的精确率和召回率。
- 其他模型:朴素贝叶斯和决策树模型的表现也不错,但相较于 SVM,分类的准确度略有不足,尤其是在垃圾短信的识别方面。