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

目录

1.知识简介

[2.SVM 支持向量机模型训练与可视化报告](#2.SVM 支持向量机模型训练与可视化报告)

[2.1 导入本项目所需的模块和包](#2.1 导入本项目所需的模块和包)

(1)目的

(2)代码实现

(3)代码解释

[2.2 随机生成线性可分的数据并可视化](#2.2 随机生成线性可分的数据并可视化)

(1)目的

(2)代码实现

(3)代码解释

[2.3 训练 SVM 模型](#2.3 训练 SVM 模型)

(1)目的

(2)代码实现

(3)代码解释

[2.4 使用新数据进行预测](#2.4 使用新数据进行预测)

(1)目的

(2)代码实现

(3)代码解释

[2.5 使用 Matplotlib 进行可视化](#2.5 使用 Matplotlib 进行可视化)

(1)目的

(2)代码实现

(3)代码解释

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

[3.1 加载数据集](#3.1 加载数据集)

[(1) 目的](#(1) 目的)

[(2) 代码实现](#(2) 代码实现)

[(3) 代码解释](#(3) 代码解释)

[3.2 特征提取](#3.2 特征提取)

[(1) 目的](#(1) 目的)

[(2) 代码实现](#(2) 代码实现)

[(3) 代码解释](#(3) 代码解释)

[3.3 数据集划分](#3.3 数据集划分)

[(1) 目的](#(1) 目的)

[(2) 代码实现](#(2) 代码实现)

[(3) 代码解释](#(3) 代码解释)

[3.4 特征选择](#3.4 特征选择)

[(1) 目的](#(1) 目的)

[(2) 代码实现](#(2) 代码实现)

[(3) 代码解释](#(3) 代码解释)

[3.5 模型选择与训练](#3.5 模型选择与训练)

[(1) 目的](#(1) 目的)

[(2) 代码实现](#(2) 代码实现)

[(3) 代码解释](#(3) 代码解释)

[3.6 性能评估](#3.6 性能评估)

[(1) 目的](#(1) 目的)

[(2) 代码实现](#(2) 代码实现)

[(3) 代码解释](#(3) 代码解释)

[3.7 与其他模型比较](#3.7 与其他模型比较)

[(1) 目的](#(1) 目的)

[(2) 代码实现](#(2) 代码实现)

[(3) 代码解释](#(3) 代码解释)

[3.8 结论与讨论](#3.8 结论与讨论)

[(1) 目的](#(1) 目的)

[(2) 代码实现](#(2) 代码实现)

[(3) 代码解释](#(3) 代码解释)

4.总体代码和结果

[4.1 SVM 支持向量机模型训练与可视化](#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)代码实现

python 复制代码
# 导入所需模块
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)代码实现

python 复制代码
# 生成线性可分数据
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)代码实现

python 复制代码
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)代码实现

python 复制代码
# 第一个预测点
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)代码实现

python 复制代码
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) 代码实现

python 复制代码
# 数据集在 "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) 代码实现

python 复制代码
# 使用 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) 代码实现

python 复制代码
# 将数据集划分为训练集和测试集
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) 代码实现

python 复制代码
# 使用卡方检验进行特征选择
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) 代码实现

python 复制代码
# 使用支持向量机(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) 代码实现

python 复制代码
# 使用测试集数据进行预测
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) 代码实现

python 复制代码
# 朴素贝叶斯分类器
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) 代码实现

python 复制代码
# 朴素贝叶斯分类器
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) 代码解释

  • accuracy_score(y_test, y_pred) 计算 SVM、朴素贝叶斯和决策树的准确率。
  • 输出每个模型的准确率并比较,找出最优模型。

4.总体代码和结果

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

(1)总体代码

python 复制代码
## 步骤一,导入本项目所需要的模块和包
# 导入所需模块
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)总体代码

python 复制代码
# 导入必要的库
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,分类的准确度略有不足,尤其是在垃圾短信的识别方面。
相关推荐
小叮当爱咖啡33 分钟前
ResNet50V2:口腔癌分类
人工智能·分类·数据挖掘
笑非不退1 小时前
机器学习和深度学习区别
机器学习
正义的彬彬侠3 小时前
矩阵的特征值和特征向量
人工智能·线性代数·机器学习·矩阵
赋创小助手3 小时前
下一代性能怪兽RTX 5090最新规格更新与Blackwell架构解析
人工智能·科技·深度学习·机器学习·架构
技术无疆3 小时前
【Python】Daphne:Django 异步服务的桥梁
开发语言·人工智能·后端·python·机器学习·数据挖掘·django
tt5555555555553 小时前
机器学习学习笔记-20240927
笔记·学习·机器学习·计算机视觉
Tunny_yyy4 小时前
李宏毅机器学习2022-HW9--Explainable AI
人工智能·机器学习
深度学习实战训练营6 小时前
FiBiNET模型实现推荐算法
算法·机器学习·推荐算法
拜刊物苏哲7 小时前
【机器学习(七)】分类和回归任务-K-近邻 (KNN)算法-Sentosa_DSML社区版
机器学习·分类·回归·k近邻算法