💥 项目专栏:sklearn实现经典机器学习算法(附代码+原理介绍)
前言
🌟 哈喽,亲爱的小伙伴们,你们知道吗?最近我们的粉丝群里有好多小可爱私信问我一些关于决策树、逻辑回归等机器学习的超级有趣的问题呢!🌈 为了让大家更轻松地理解,我决定开一个超可爱的专栏,叫做 用sklearn玩转机器学习
,特别适合机器学习的小新手哦!
🍬 在这个专栏里,我们会用sklearn这个超级强大的魔法工具来实现各种闪闪发光的机器学习算法!不用担心难度哦,我会用最简单、最可爱的方式,带领大家一起探索算法的神秘世界!✨
🎈 适合哪些小伙伴加入呢?当然是对机器学习感兴趣的小新手们,还有那些刚开始接触sklearn的可爱宝宝们!我们会一起学习如何用sklearn轻松实现那些看起来好厉害的机器学习算法,让新手小白也能快快乐乐地理解它们哦!
🌸 在这个专栏里,大家可以看到用sklearn实现的机器学习算法,我们不仅仅是理论学习哦,每一篇文章都会附带 完整的代码+超级可爱的原理讲解
,让大家在轻松愉快的氛围中一起学习成长呢!🌼 快来加入我们的学习大冒险吧!
🚨 我的项目环境:
- 平台:Windows11
- 语言环境:Python 3.10
- 编译器:Jupyter Lab、PyCharm
- scikit-learn:1.2.1
- Pandas:1.3.5
- Numpy:1.19.3
- Scipy:1.7.3
- Matplotlib:3.1.3
💥 项目专栏:sklearn实现经典机器学习算法(附代码+原理介绍)
一、算法背景
SVC(Support Vector Classification)是支持向量机(Support Vector Machine,SVM)的一种应用,用于解决分类问题。支持向量机是一种强大的监督学习算法,广泛应用于数据分类和回归任务。它的算法背景如下:
-
问题背景:
- 支持向量机最初是在上世纪60年代提出的,最初是用于解决二元分类问题,即将数据点分为两个不同的类别。
-
最大间隔分类:
- SVM的核心思想是寻找一个决策边界(或称为超平面),以最大化两个不同类别之间的间隔(即支持向量之间的距离)。这个超平面被选择为能够最好地将数据点划分为两个不同类别的边界。
-
支持向量:
- 在SVM中,支持向量是离超平面最近的数据点,它们决定了超平面的位置。这些支持向量在分类决策中起到关键作用,因为它们具有最大的间隔,影响超平面的位置。
-
核函数:
- SVM可以使用核函数来处理非线性分类问题。核函数允许将数据从原始特征空间映射到高维特征空间,从而使数据在高维空间中线性可分。常用的核函数包括线性核、多项式核和径向基函数(RBF)核。
-
软间隔分类:
- 在实际应用中,数据往往不是完全线性可分的。SVM引入了软间隔分类,允许一些数据点出现在错误的一侧,并通过参数C来控制间隔和错误之间的权衡。C的值越小,容忍错误的程度越高,C的值越大,容忍错误的程度越低。
-
多类分类:
- 对于多类分类问题,SVM可以使用一对一(One-vs-One)或一对其他(One-vs-Rest)策略来扩展到多类别情况。
总之,SVC是支持向量机的一个重要应用,它通过寻找最大间隔超平面来解决分类问题。SVM以其强大的分类性能和能够处理非线性问题的能力而闻名,广泛应用于机器学习和数据挖掘任务中。
二、算法原理
支持向量机分类器(SVC)是一种强大的监督学习算法,用于解决二元分类问题。它的核心思想是在数据集中找到一个最优的超平面,以最大化不同类别之间的间隔,从而实现高效的分类。下面是SVC算法的详细原理:
-
问题背景:
- SVC主要用于解决二元分类问题,即将数据点分为两个不同的类别。它是支持向量机(SVM)的一种应用。
-
间隔最大化:
- SVC的目标是找到一个决策超平面,以最大化两个不同类别之间的间隔。这个间隔是由支持向量(下面会详细介绍)确定的,是指距离决策超平面最近的数据点到该平面的距离。
-
超平面:
- 在SVC中,超平面是一个(D-1)维空间的子空间,其中D是数据点的特征数目。对于二维特征空间,超平面是一条直线;对于三维特征空间,超平面是一个平面,以此类推。决策超平面被选择为将数据点分为两个类别的边界。
-
支持向量:
- 支持向量是训练数据中距离决策超平面最近的数据点。它们是决策超平面的构建基础,因为它们决定了超平面的位置。在SVC中,只有支持向量的位置对分类决策有影响,其他数据点不会影响决策。
-
软间隔和正则化:
- 在实际应用中,数据通常不是完全线性可分的。SVC引入了软间隔,允许一些数据点出现在错误的一侧。软间隔的程度由超参数C控制,C越大,模型越倾向于正确分类每个数据点,C越小,模型越容忍一些数据点的分类错误。这个超参数C通常需要调整以平衡间隔和分类错误之间的权衡。
-
核函数:
- SVM可以处理非线性问题,通过引入核函数将数据从原始特征空间映射到高维特征空间,从而实现线性可分。常用的核函数包括线性核、多项式核、径向基函数(RBF)核等。选择合适的核函数是非常关键的,因为它可以决定SVC的性能。
-
决策函数:
- 决策函数用于根据数据点的特征值进行分类预测。对于新的数据点,SVC会将其投影到决策超平面上,然后根据投影点的位置来判断其属于哪个类别。
-
训练过程:
- 训练SVC模型的过程是通过求解一个凸优化问题来确定决策超平面和支持向量的位置。这个问题的解决涉及到数学优化和拉格朗日乘子法等数学方法。
总结来说,SVC是通过找到一个最优的决策超平面,以最大化不同类别之间的间隔来解决二元分类问题。它的性能和泛化能力在很多情况下都非常出色,但需要谨慎选择合适的超参数和核函数以获得最佳性能。
三、算法实现
3.1 导包
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
3.2 加载数据集
这行代码使用make_blobs
函数创建了一个包含40个数据点的数据集,这些数据点是可分离的,分为两个中心(centers=2)的类别。以下是对该行代码的解释:
-
make_blobs
: 这是Scikit-Learn库中的一个函数,用于生成模拟数据集。它可以创建包含多个簇的数据集,每个簇可以具有不同的中心点、方差等特性。通常用于用于机器学习的数据集生成。 -
n_samples=40
: 这个参数指定了要生成的数据集的样本数量,这里是40个数据点。 -
centers=2
: 这个参数指定了数据集中的簇的数量,这里是2个簇,意味着生成的数据集将包含两个不同的类别。 -
random_state=6
: 这个参数用于设置随机种子,以确保每次运行代码时都生成相同的随机数据。这对于可重复性和调试非常有用。
综上所述,上述代码行创建了一个包含40个可分离数据点的数据集,其中有两个不同的类别。这个数据集可以用于训练和测试分类模型。
# 创建40个可分离的数据点
X, y = make_blobs(n_samples=40, centers=2, random_state=6)
3.3 划分训练集、测试集
这行代码使用Scikit-Learn中的train_test_split
函数将数据集X
和y
分为训练集和测试集,以进行机器学习模型的训练和评估。以下是对该行代码的解释:
-
X
是包含特征的数据集,y
是包含对应标签或类别的数据集。 -
train_test_split
函数的第一个参数是要划分的特征数据集X
,第二个参数是对应的标签数据集y
。 -
test_size=0.2
:这个参数指定了要分配给测试集的比例。在这里,将数据的20%分配给测试集,而80%将分配给训练集。 -
random_state=42
:这个参数用于设置随机种子,以确保每次运行代码时都会得到相同的划分结果。这对于可重复性和调试很有用。
结果中,X_train
和y_train
包含了80%的数据,用于训练模型,而X_test
和y_test
包含了20%的数据,用于评估模型性能。这个分割过程是为了确保在模型训练和评估过程中使用不同的数据,以验证模型的泛化性能。通常,训练集用于拟合模型,而测试集用于评估模型在未见过的数据上的性能。
# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
3.4 定义模型
这行代码定义了一个支持向量机(SVM)分类器模型,并设置了以下参数:
-
svm.SVC
: 这是Scikit-Learn库中的支持向量机分类器类。 -
kernel="linear"
: 这个参数指定了SVM的核函数,这里使用了线性核函数。线性核函数在特征空间中直接进行线性分类。 -
C=1000
: 这个参数是SVM的正则化参数,也称为惩罚参数。在这里,C的值设置为1000,表示不进行正则化,即允许模型在训练时尽量拟合每一个训练样本,而不考虑分类错误的惩罚。
通过这个定义,创建了一个SVM分类器,它使用线性核函数进行分类,C值设置为1000,意味着不进行正则化。这可以用于拟合一个非常灵活的模型,但也可能导致过拟合,因此需要根据具体问题进行调整。通常,根据数据的性质和分布,可以调整核函数和C值来获得最佳的分类性能。
# 定义SVM模型,不进行正则化(C=1000)
clf = svm.SVC(kernel="linear", C=1000)
以下是以表格形式展示Scikit-Learn中SVC
(支持向量机分类器)类的常用参数,包括参数名称、描述以及可选的值或类型:
参数 | 描述 | 可选的值/类型 |
---|---|---|
C | 正则化参数,控制间隔边界的软硬程度。较小的值增加了容忍分类错误的程度。 | 正浮点数 |
kernel | 核函数类型,用于处理非线性分类问题。 | ‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, 自定义核函数等 |
degree | 多项式核函数的阶数(仅在使用多项式核函数时有效)。 | 正整数 |
gamma | 核函数的系数,影响模型的复杂性。较大的值会导致更复杂的决策边界。 | ‘scale’, ‘auto’, 正浮点数,{‘scale’, ‘auto’}或自定义 |
coef0 | 核函数的独立项,仅对某些核函数类型有效(如多项式和sigmoid核)。 | 浮点数 |
shrinking | 是否使用启发式方法来加速训练。 | 布尔值 |
probability | 是否启用概率估计。当设置为True时,模型可以输出类别的概率估计。 | 布尔值 |
tol | 停止训练的容忍度,指定收敛阈值。 | 正浮点数 |
class_weight | 类别权重,用于处理不平衡类别分布的情况。 | 字典、‘balanced’ 或 None |
verbose | 控制详细程度的整数值,用于记录训练进程。 | 非负整数 |
max_iter | 求解器的最大迭代次数。 | 正整数 |
decision_function_shape | 决策函数的形状,适用于多类问题。 | ‘ovo’(一对一)、‘ovr’(一对其他)或 None |
random_state | 随机数生成器的种子。 | 整数或 None |
这些参数允许您在构建支持向量机分类器时进行调整,以满足您的数据集和问题的特定需求。不同的参数设置可以影响模型的性能和泛化能力,因此在使用时需要根据具体情况进行选择和调整。
3.5 绘制决策边界
# 绘制数据点
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, s=30, cmap=plt.cm.Paired)
# 绘制决策边界
ax = plt.gca()
DecisionBoundaryDisplay.from_estimator(
clf,
X_train,
plot_method="contour",
colors="k",
levels=[-1, 0, 1],
alpha=0.5,
linestyles=["--", "-", "--"],
ax=ax,
)
# 绘制支持向量
ax.scatter(
clf.support_vectors_[:, 0],
clf.support_vectors_[:, 1],
s=100,
linewidth=1,
facecolors="none",
edgecolors="k",
)
# 显示图形
plt.show()
上述代码段用于绘制数据点、决策边界以及支持向量的图形。下面是对这段代码的详细解释:
-
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, s=30, cmap=plt.cm.Paired)
:- 这行代码用于绘制训练集的数据点。
X_train[:, 0]
和X_train[:, 1]
分别表示训练集中的第一个和第二个特征。c=y_train
用于根据训练集的标签y_train
来给数据点着色,不同类别的数据点将具有不同的颜色。 s=30
指定了数据点的大小。cmap=plt.cm.Paired
设置了颜色映射,以便将不同类别的数据点以不同的颜色显示。
- 这行代码用于绘制训练集的数据点。
-
ax = plt.gca()
:- 这行代码获取了当前的轴对象,以便后续的图形绘制。
-
DecisionBoundaryDisplay.from_estimator(...)
:- 这部分代码使用
DecisionBoundaryDisplay
类从已拟合的SVC模型clf
中生成决策边界的图形。它指定了绘制决策边界的方法、颜色、水平线级别、透明度以及线条样式等参数。 - 决策边界用于显示SVC模型的分类边界。
- 这部分代码使用
-
ax.scatter(...)
:- 这行代码用于绘制支持向量。支持向量是SVC模型中的关键元素,它们是离决策边界最近的数据点。
clf.support_vectors_[:, 0]
和clf.support_vectors_[:, 1]
获取了支持向量的坐标。s=100
设置支持向量的大小,facecolors="none"
表示支持向量的填充颜色为空,edgecolors="k"
表示支持向量的边缘颜色为黑色。
-
plt.show()
:- 这行代码用于显示绘制好的图形,将数据点、决策边界和支持向量显示在同一个图形中,以便可视化SVC模型的性能。
综上所述,这段代码用于可视化训练好的SVC模型在训练集上的分类效果,包括数据点、决策边界和支持向量的展示。这有助于理解模型的分类结果以及支持向量在决策边界中的作用。
3.6 评估指标
这段代码用于对训练集和测试集进行预测,并计算并打印出训练集和测试集的分类精度。下面是对这段代码的详细解释:
-
y_train_pred = clf.predict(X_train)
:- 这行代码使用已训练的SVC模型
clf
对训练集X_train
进行预测,将预测结果保存在y_train_pred
变量中。这里模型会根据训练集的特征来预测每个样本的类别标签。
- 这行代码使用已训练的SVC模型
-
y_test_pred = clf.predict(X_test)
:- 同样的,这行代码使用已训练的SVC模型
clf
对测试集X_test
进行预测,将预测结果保存在y_test_pred
变量中。测试集是模型从未见过的数据,用于评估模型的泛化性能。
- 同样的,这行代码使用已训练的SVC模型
-
train_accuracy = accuracy_score(y_train, y_train_pred)
:- 这行代码使用Scikit-Learn中的
accuracy_score
函数来计算训练集的分类精度。y_train
包含了训练集的真实类别标签,而y_train_pred
包含了模型对训练集的预测结果。
- 这行代码使用Scikit-Learn中的
-
test_accuracy = accuracy_score(y_test, y_test_pred)
:- 同样的,这行代码使用
accuracy_score
函数来计算测试集的分类精度。y_test
包含了测试集的真实类别标签,而y_test_pred
包含了模型对测试集的预测结果。
- 同样的,这行代码使用
-
print(f"训练集分类精度: {train_accuracy:.2f}")
和print(f"测试集分类精度: {test_accuracy:.2f}")
:- 这两行代码用于打印训练集和测试集的分类精度。分类精度是模型正确分类的样本比例,以百分比形式显示。
通过计算和打印训练集和测试集的分类精度,可以评估SVC模型在不同数据集上的性能,判断模型是否过拟合或欠拟合,以及是否需要进一步调整模型的超参数。通常情况下,较高的分类精度表示模型性能较好。
# 预测训练集和测试集
y_train_pred = clf.predict(X_train)
y_test_pred = clf.predict(X_test)
# 计算并打印训练集和测试集的分类精度
train_accuracy = accuracy_score(y_train, y_train_pred)
test_accuracy = accuracy_score(y_test, y_test_pred)
print(f"训练集分类精度: {train_accuracy:.2f}")
print(f"测试集分类精度: {test_accuracy:.2f}")
打印结果:
训练集分类精度: 1.00
测试集分类精度: 1.00
最佳参数: {'C': 0.1, 'gamma': 0.001, 'kernel': 'linear'}
最佳分类精度: 1.0
3.7 网格搜索
这段代码演示了如何使用网格搜索(Grid Search)来搜索最佳的超参数组合以优化SVC模型。以下是对这段代码的详细解释:
-
param_grid
:- 这个字典定义了要搜索的超参数的候选值。具体来说,它包括了三个超参数:
C
(正则化参数)、kernel
(核函数类型)、gamma
(核函数的系数)。每个超参数都有一组候选值,用于在网格搜索中进行组合。
- 这个字典定义了要搜索的超参数的候选值。具体来说,它包括了三个超参数:
-
svc = svm.SVC()
:- 这行代码创建了一个SVC分类器对象,此时还未指定超参数的值。
-
GridSearchCV
:- 这是Scikit-Learn中的网格搜索交叉验证类,用于系统地搜索超参数的最佳组合。它接受以下参数:
svc
:要优化的模型对象,这里是SVC分类器。param_grid
:定义了要搜索的超参数的候选值。cv=5
:交叉验证的折数,这里使用5折交叉验证来评估模型性能。n_jobs=-1
:使用所有可用的CPU核心来并行处理网格搜索,加快搜索速度。
- 这是Scikit-Learn中的网格搜索交叉验证类,用于系统地搜索超参数的最佳组合。它接受以下参数:
-
grid_search.fit(X_train, y_train)
:- 这行代码执行网格搜索,用训练集
X_train
和y_train
来寻找最佳的超参数组合。网格搜索将尝试所有可能的超参数组合,并使用交叉验证来评估每个组合的性能。
- 这行代码执行网格搜索,用训练集
-
print("最佳参数:", grid_search.best_params_)
和print("最佳分类精度:", grid_search.best_score_)
:- 这两行代码用于打印出网格搜索找到的最佳超参数组合以及相应的最佳分类精度。
best_params_
属性包含了最佳的超参数值,best_score_
属性包含了最佳的交叉验证分数。
- 这两行代码用于打印出网格搜索找到的最佳超参数组合以及相应的最佳分类精度。
通过执行网格搜索,可以确定最佳的超参数组合,从而改善SVC模型的性能。这对于自动化超参数调整以获得最佳模型非常有用。
# 网格搜索参数
param_grid = {'C': [0.1, 1, 10, 100, 1000],
'kernel': ['linear', 'rbf', 'poly', 'sigmoid'],
'gamma': [0.001, 0.01, 0.1, 1, 'scale', 'auto']}
# 创建一个SVM分类器
svc = svm.SVC()
# 使用网格搜索进行超参数调优
grid_search = GridSearchCV(svc, param_grid, cv=5, n_jobs=-1)
grid_search.fit(X_train, y_train)
# 打印最佳参数和分类精度
print("最佳参数:", grid_search.best_params_)
print("最佳分类精度:", grid_search.best_score_)
完整源码
import matplotlib.pyplot as plt
from sklearn import svm
from sklearn.datasets import make_blobs
from sklearn.inspection import DecisionBoundaryDisplay
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
# 创建40个可分离的数据点
X, y = make_blobs(n_samples=40, centers=2, random_state=6)
# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 定义SVM模型,不进行正则化(C=1000)
clf = svm.SVC(kernel="linear", C=1000)
# 拟合模型
clf.fit(X_train, y_train)
# 绘制数据点
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, s=30, cmap=plt.cm.Paired)
# 绘制决策边界
ax = plt.gca()
DecisionBoundaryDisplay.from_estimator(
clf,
X_train,
plot_method="contour",
colors="k",
levels=[-1, 0, 1],
alpha=0.5,
linestyles=["--", "-", "--"],
ax=ax,
)
# 绘制支持向量
ax.scatter(
clf.support_vectors_[:, 0],
clf.support_vectors_[:, 1],
s=100,
linewidth=1,
facecolors="none",
edgecolors="k",
)
# 显示图形
plt.show()
# 预测训练集和测试集
y_train_pred = clf.predict(X_train)
y_test_pred = clf.predict(X_test)
# 计算并打印训练集和测试集的分类精度
train_accuracy = accuracy_score(y_train, y_train_pred)
test_accuracy = accuracy_score(y_test, y_test_pred)
print(f"训练集分类精度: {train_accuracy:.2f}")
print(f"测试集分类精度: {test_accuracy:.2f}")
# 网格搜索参数
param_grid = {'C': [0.1, 1, 10, 100, 1000],
'kernel': ['linear', 'rbf', 'poly', 'sigmoid'],
'gamma': [0.001, 0.01, 0.1, 1, 'scale', 'auto']}
# 创建一个SVM分类器
svc = svm.SVC()
# 使用网格搜索进行超参数调优
grid_search = GridSearchCV(svc, param_grid, cv=5, n_jobs=-1)
grid_search.fit(X_train, y_train)
# 打印最佳参数和分类精度
print("最佳参数:", grid_search.best_params_)
print("最佳分类精度:", grid_search.best_score_)