【机器学习】任务六:分类算法(支持向量机(SVM)在线性可分与不可分数据中的应用与可视化分析)

发布于:2024-10-10 ⋅ 阅读:(64) ⋅ 点赞:(0)

目录

1.知识简介

2.SVM 支持向量机模型训练与可视化报告

2.1 导入本项目所需的模块和包

(1)目的

(2)代码实现

(3)代码解释

2.2 随机生成线性可分的数据并可视化

(1)目的

(2)代码实现

(3)代码解释

2.3 训练 SVM 模型

(1)目的

(2)代码实现

(3)代码解释

2.4 使用新数据进行预测

(1)目的

(2)代码实现

(3)代码解释

2.5 使用 Matplotlib 进行可视化

(1)目的

(2)代码实现

(3)代码解释

3.垃圾短信分类的机器学习实现:SVM、朴素贝叶斯与决策树的比较

3.1 加载数据集

(1) 目的

(2) 代码实现

(3) 代码解释

3.2 特征提取

(1) 目的

(2) 代码实现

(3) 代码解释

3.3 数据集划分

(1) 目的

(2) 代码实现

(3) 代码解释

3.4 特征选择

(1) 目的

(2) 代码实现

(3) 代码解释

3.5 模型选择与训练

(1) 目的

(2) 代码实现

(3) 代码解释

3.6 性能评估

(1) 目的

(2) 代码实现

(3) 代码解释

3.7 与其他模型比较

(1) 目的

(2) 代码实现

(3) 代码解释

3.8 结论与讨论

(1) 目的

(2) 代码实现

(3) 代码解释

4.总体代码和结果

4.1 SVM 支持向量机模型训练与可视化

(1)总体代码

(2)运行结果

(3)结果分析

4.2垃圾短信分类的机器学习实现:SVM、朴素贝叶斯与决策树的比较

(1)总体代码

(2)运行结果

(3)结果分析

(4)总结


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-learnmatplotlib),实现数据生成、模型训练、决策边界绘制以及结果的可视化,帮助更好地理解 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_blobsmake_blobs 方法用于生成模拟的线性可分数据集,方便我们测试分类器的效果。
  • 设置 plt.rcParams 字体选项:为了支持中文显示,确保在绘图时不会出现乱码,并且保证负号在坐标轴上能正确显示。

2.2 随机生成线性可分的数据并可视化

(1)目的

生成一组二维线性可分的数据集,数据的特征包括 x1x2,类别用 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 是一个二维数组,表示每个数据点的特征(x1x2),y 是一个标签数组,包含每个数据点的类别标签(01)。
  • 可视化数据
    • 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.xlabelplt.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() 获取横纵坐标轴的范围。
    • 创建网格 XXYY,并计算每个点的决策函数值 Z
    • ax.contour(XX, YY, Z, levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--']):绘制三个边界,其中 0 表示超平面,-11 表示支持向量边界。
  • 标记支持向量
    • 使用 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      1114

Naive 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,分类的准确度略有不足,尤其是在垃圾短信的识别方面。

网站公告

今日签到

点亮在社区的每一天
去签到