突破最强分类算法模型,SVM!!

文摘   2024-10-07 15:26   山西  

哈喽,我是cos大壮 !~

今儿和一位同学聊到了SVM,那么,这篇文章详细的再和大家聊聊这个比较基础的算法~

支持向量机 (SVM) 是一种用于分类和回归的机器学习算法。虽然名字听起来复杂,但通过一个简单的例子来解释就容易理解多了。

比如,你是学校的篮球队教练,现在要从班里挑选哪些同学适合打篮球。

  • 你有两类同学:一类是「打篮球的」,另一类是「不打篮球的」。
  • 你的目标是根据每个同学的身高和臂展,找出适合打篮球的同学。

这样大家可以画图看看:

  • 你可以把每个同学的身高和臂展当作坐标,画在一个二维平面上。
  • 「打篮球的」同学可以用红色点表示,「不打篮球的」同学用蓝色点表示。
  • 你的任务是找一条线,把这两类同学分开。
老规矩如果大家伙觉得近期文章还不错!欢迎大家点个赞、转个发,文末赠送《机器学习学习小册》

文末可取本文PDF版本~

SVM怎么工作?

支持向量机会尝试找到一条最佳的线,不仅把两类同学分开,还希望这条线与两类同学的点之间有尽量大的距离。这样,当你遇到一个新同学时,只需要看他是在这条线的哪一侧,就可以判断他是否适合打篮球。

详细步骤:

  1. 画线:SVM 试图在「打篮球的」同学和「不打篮球的」同学之间画一条线。这条线叫做「决策边界」。

  2. 支持向量:有些同学站得离这条线非常近,他们的位置会影响这条线的走向。SVM 会重点关注这些离线最近的点,这些点就是「支持向量」。线的位置和方向是由这些支持向量决定的。

  3. 最大化间隔:SVM 不仅画线,还会确保线和最靠近的同学之间的距离(也就是「间隔」)最大。这能让分类更加稳定和准确。

总的来说,支持向量机的任务就是找到一条最佳的线,把「打篮球的」和「不打篮球的」同学分开,并且确保这条线离两类人都尽量远。这样,未来如果来了新同学,你可以很容易根据他的位置判断他是否适合打篮球。

有这些基础的解释后,再和大家详细聊聊其原理和案例。

支持向量机公式推理

支持向量机(SVM)的核心思想是通过找到一条「最佳分割线」来将不同类别的数据点分开,这条分割线不仅将两类数据分开,还尽量让两类数据离这条线的距离最大。

我们通过详细推导 SVM 的公式来解释其中的数学原理。

1. 超平面定义

假设数据点有两类,分别为 (正类)和 (负类)。我们需要找到一个分割这两类数据的超平面:

其中:

  •  是超平面的法向量,决定超平面的方向;
  •  是偏置,决定超平面到原点的距离;
  •  是数据点的特征向量。

2. 分类条件

假设对于正类的点 ,我们希望满足:

对于负类的点 ,希望满足:

因此,分类的条件可以写成:

这个不等式就是支持向量机的分类条件。

3. 最大化间隔

支持向量机的关键是要最大化间隔,即使得正类和负类的点离超平面的距离尽可能大。间隔的公式为:

因此,我们的目标是最大化间隔,即最小化 。综合分类条件和最大化间隔,SVM 的优化问题可以写为:

同时满足约束条件:

4. 拉格朗日对偶问题

为了求解这个优化问题,使用拉格朗日乘子法。定义拉格朗日函数:

其中, 是拉格朗日乘子。通过对    求偏导,并将其设为 0,可以得到对偶问题的公式:

约束条件为:

通过求解这个对偶问题,找到最优的  后,超平面可以表示为:

完整案例

这里我们基于一个Kaggle数据集来展示如何使用支持向量机进行分类,同时通过多个图形来进行数据分析和结果可视化。

数据集选择

我们可以选择Kaggle上的Breast Cancer Wisconsin (Diagnostic) Data Set,这是一个非常经典的二分类数据集,适合用于支持向量机的演示。

数据集获取:后台回复「数据集」即可获取~

分析步骤

  1. 数据预处理:首先加载数据并进行基本的清理和预处理。
  2. 数据可视化:通过多个图形来分析特征之间的关系以及数据的分布。
  3. 支持向量机实现:根据推导的公式,手动实现支持向量机的分类过程。
  4. 结果分析和可视化:通过图形展示分类结果、支持向量、决策边界等。

这里,咱们手动实现一下SVM,大家利用上面原理和代码进行理解~

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# 加载Kaggle数据集(乳腺癌数据)
data = pd.read_csv('data.csv')
data = data.dropna(axis=1)  # 删除有缺失值的列
data['diagnosis'] = data['diagnosis'].map({'M'1'B'-1})  # 将分类标签转换为 +1 和 -1

# 提取特征和标签
X = data[['radius_mean''texture_mean']].values  # 简化为2维特征
y = data['diagnosis'].values

# 特征之间的散点图
plt.figure(figsize=(8,6))
plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], color='r', label='Malignant')
plt.scatter(X[y == -1][:, 0], X[y == -1][:, 1], color='b', label='Benign')
plt.title('Scatter plot of Features')
plt.xlabel('Radius Mean')
plt.ylabel('Texture Mean')
plt.legend()
plt.show()

# 每个特征的直方图
plt.figure(figsize=(126))

plt.subplot(121)
plt.hist(data['radius_mean'], bins=20, color='c', edgecolor='k')
plt.title('Histogram of Radius Mean')
plt.xlabel('Radius Mean')
plt.ylabel('Frequency')

plt.subplot(122)
plt.hist(data['texture_mean'], bins=20, color='m', edgecolor='k')
plt.title('Histogram of Texture Mean')
plt.xlabel('Texture Mean')
plt.ylabel('Frequency')

plt.tight_layout()
plt.show()

# SVM实现
class SVM:
    def __init__(self, learning_rate=0.001, lambda_param=0.01, n_iters=1000):
        self.lr = learning_rate
        self.lambda_param = lambda_param
        self.n_iters = n_iters
        self.w = None
        self.b = None

    def fit(self, X, y):
        n_samples, n_features = X.shape
        y_ = np.where(y <= 0-11)

        self.w = np.zeros(n_features)
        self.b = 0

        for _ in range(self.n_iters):
            for idx, x_i in enumerate(X):
                condition = y_[idx] * (np.dot(x_i, self.w) - self.b) >= 1
                if condition:
                    self.w -= self.lr * (2 * self.lambda_param * self.w)
                else:
                    self.w -= self.lr * (2 * self.lambda_param * self.w - np.dot(x_i, y_[idx]))
                    self.b -= self.lr * y_[idx]

    def predict(self, X):
        approx = np.dot(X, self.w) - self.b
        return np.sign(approx)

# 训练模型
svm = SVM()
svm.fit(X, y)

# SVM分类结果的决策边界图
def plot_decision_boundary(X, y, model):
    def get_hyperplane_value(x, w, b, offset):
        return (-w[0] * x + b + offset) / w[1]

    plt.figure(figsize=(8,6))
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=y)

    x0_1 = np.amin(X[:, 0])
    x0_2 = np.amax(X[:, 0])

    x1_1 = get_hyperplane_value(x0_1, model.w, model.b, 0)
    x1_2 = get_hyperplane_value(x0_2, model.w, model.b, 0)

    x1_1_m = get_hyperplane_value(x0_1, model.w, model.b, -1)
    x1_2_m = get_hyperplane_value(x0_2, model.w, model.b, -1)

    x1_1_p = get_hyperplane_value(x0_1, model.w, model.b, 1)
    x1_2_p = get_hyperplane_value(x0_2, model.w, model.b, 1)

    plt.plot([x0_1, x0_2], [x1_1, x1_2], "k--")
    plt.plot([x0_1, x0_2], [x1_1_m, x1_2_m], "r--")
    plt.plot([x0_1, x0_2], [x1_1_p, x1_2_p], "b--")

    plt.title('SVM Decision Boundary')
    plt.xlabel('Radius Mean')
    plt.ylabel('Texture Mean')
    plt.show()

plot_decision_boundary(X, y, svm)

# 标注支持向量
def plot_support_vectors(X, y, model):
    # 找到支持向量
    decision_function = np.dot(X, model.w) - model.b
    support_vector_indices = np.where(np.abs(decision_function) < 1 + 1e-5)[0]

    plt.figure(figsize=(8,6))
    plt.scatter(X[:, 0], X[:, 1], marker='o', c=y, label="Data Points")
    
    # 标注支持向量
    plt.scatter(X[support_vector_indices][:, 0], X[support_vector_indices][:, 1],
                color='y', edgecolor='k', s=200, marker='o', label='Support Vectors')
    
    plt.title('Support Vectors Visualization')
    plt.xlabel('Radius Mean')
    plt.ylabel('Texture Mean')
    plt.legend()
    plt.show()

plot_support_vectors(X, y, svm)

图形1特征之间的散点图展示了不同类别数据的分布,红色表示恶性肿瘤,蓝色表示良性肿瘤。这个图形帮助我们了解两类数据在特征空间中的分布情况。

图形2特征直方图分别展示了 radius_mean  texture_mean 特征的分布情况。这个图形展示了每个特征的取值范围和频率,帮助我们了解特征的分布是否有偏差。

图形3SVM 分类结果的决策边界图展示了支持向量机对数据的分类效果。黑色的虚线是决策边界,两侧的红色和蓝色虚线分别代表支持向量间隔。这个图形清晰地展示了分类的边界和不同类别数据的分布。

图形4支持向量可视化图标注了哪些数据点是支持向量(用黄色标记)。这些点是支持向量机分类决策中最重要的点,定义了超平面的位置和方向。

最后

大家有问题可以直接在评论区留言即可~

喜欢本文的朋友可收藏、点赞、转发起来!

需要本文PDF的同学,扫码备注「基础算法」即可~ 
关注本号,带来更多算法干货实例,提升工作学习效率!
最后,给大家准备了《机器学习学习小册》PDF版本16大块的内容,124个问题总结
100个超强算法模型,大家如果觉得有用,可以点击查看~

推荐阅读

原创、超强、精华合集
100个超强机器学习算法模型汇总
机器学习全路线
机器学习各个算法的优缺点
7大方面,30个最强数据集
6大部分,20 个机器学习算法全面汇总
铁汁,都到这了,别忘记点赞呀~

深夜努力写Python
Python、机器学习算法
 最新文章