线性可分支持向量机代码 举例说明 具体的变量数值变化

### 实现线性可分支持向量机
### 硬间隔最大化策略
class Hard_Margin_SVM:
    ### 线性可分支持向量机拟合方法
    def fit(self, X, y):
        # 训练样本数和特征数
        m, n = X.shape

        # 初始化二次规划相关变量:P/q/G/h
        self.P = matrix(np.identity(n + 1, dtype=np.float))
        self.q = matrix(np.zeros((n + 1,), dtype=np.float))
        self.G = matrix(np.zeros((m, n + 1), dtype=np.float))
        self.h = -matrix(np.ones((m,), dtype=np.float))

        # 将数据转为变量
        self.P[0, 0] = 0
        for i in range(m):
            self.G[i, 0] = -y[i]
            self.G[i, 1:] = -X[i, :] * y[i]
        
        # 构建二次规划求解
        sol = solvers.qp(self.P, self.q, self.G, self.h)

        # 对权重和偏置寻优
        self.w = np.zeros(n,) 
        self.b = sol['x'][0] 
        for i in range(1, n + 1):
            self.w[i - 1] = sol['x'][i]
        return self.w, self.b

    ### 定义模型预测函数
    def predict(self, X):
        return np.sign(np.dot(self.w, X.T) + self.b)

通过一个具体的示例来展示硬间隔支持向量机的代码是如何运行的,并为每个变量提供具体的数据样例。

示例数据和解释

假设我们有如下的二维数据集,其中每个样本有两个特征(即二维坐标),并且样本属于两个类别 y ∈ { − 1 , 1 } y \in \{-1, 1\} y{1,1}。我们将使用硬间隔支持向量机来找到一个最大化分类间隔的超平面。

示例数据

特征矩阵 X X X(每一行是一个样本的坐标):

X = np.array([
    [1, 2],
    [2, 3],
    [3, 3],
    [2, 1],
    [3, 2]
])

标签向量 y y y(每个样本的类别标签):

y = np.array([1, 1, 1, -1, -1])

这个数据集包含 5 个样本,分别对应两个类别(1 和 -1)。前 3 个样本属于类别 + 1 +1 +1,后两个样本属于类别 − 1 -1 1

代码中的每个变量解释

让我们一步步来分析代码中的每个变量。

(1) 训练样本数和特征数
m, n = X.shape

X.shape 返回 m m m n n n,分别表示样本数量和特征数量:

  • m = 5 m = 5 m=5 表示有 5 个样本。
  • n = 2 n = 2 n=2 表示每个样本有 2 个特征(二维数据)。
(2) 初始化二次规划相关矩阵
self.P = matrix(np.identity(n + 1, dtype=np.float))
self.q = matrix(np.zeros((n + 1,), dtype=np.float))
self.G = matrix(np.zeros((m, n + 1), dtype=np.float))
self.h = -matrix(np.ones((m,), dtype=np.float))

我们将定义二次规划问题的参数矩阵:

  • self.P:用于构建目标函数的二次项 1 2 w T P w \frac{1}{2} w^T P w 21wTPw,在支持向量机中,目标是最小化 1 2 ∥ w ∥ 2 \frac{1}{2} \|w\|^2 21w2,因此 P P P 是一个 ( n + 1 ) × ( n + 1 ) (n+1) \times (n+1) (n+1)×(n+1) 的单位矩阵(表示 w 1 , w 2 w_1, w_2 w1,w2 b b b)。

    self.P = np.identity(3)  # 2 个特征 + 1 个偏置
    # 输出
    [[1. 0. 0.]
     [0. 1. 0.]
     [0. 0. 0.]]
    
  • self.q:表示线性项 q q q,其值为 0,因为硬间隔 SVM 中我们只需要最小化 1 2 ∥ w ∥ 2 \frac{1}{2} \|w\|^2 21w2,不需要其他线性项。

    self.q = np.zeros(3)
    # 输出
    [0. 0. 0.]
    
  • self.Gself.h:这些是约束条件,用于确保每个样本都正确分类并满足硬间隔条件 y i ( w T x i + b ) ≥ 1 y_i(w^T x_i + b) \geq 1 yi(wTxi+b)1

    self.G = np.zeros((5, 3))  # 5 个样本,每个样本对应 (w1, w2, b)
    self.h = -np.ones(5)       # 对应每个样本的约束
    # 输出 G 和 h
    G = [[0. 0. 0.]
         [0. 0. 0.]
         [0. 0. 0.]
         [0. 0. 0.]
         [0. 0. 0.]]
    h = [-1. -1. -1. -1. -1.]
    
(3) 构建约束矩阵 G G G h h h

接下来,我们要根据数据构建约束条件:

self.P[0, 0] = 0  # 偏置 b 不需要惩罚
for i in range(m):
    self.G[i, 0] = -y[i]  # 对偏置项的影响
    self.G[i, 1:] = -X[i, :] * y[i]  # 对 w 的影响

每一行 G [ i ] G[i] G[i] 对应样本 X [ i ] X[i] X[i] 的约束 y i ( w T x i + b ) ≥ 1 y_i(w^T x_i + b) \geq 1 yi(wTxi+b)1

样本 X X X 标签 y y y 约束条件
(1, 2) 1 w 1 ⋅ 1 + w 2 ⋅ 2 + b ≥ 1 w_1 \cdot 1 + w_2 \cdot 2 + b \geq 1 w11+w22+b1
(2, 3) 1 w 1 ⋅ 2 + w 2 ⋅ 3 + b ≥ 1 w_1 \cdot 2 + w_2 \cdot 3 + b \geq 1 w12+w23+b1
(3, 3) 1 w 1 ⋅ 3 + w 2 ⋅ 3 + b ≥ 1 w_1 \cdot 3 + w_2 \cdot 3 + b \geq 1 w13+w23+b1
(2, 1) -1 − w 1 ⋅ 2 − w 2 ⋅ 1 − b ≥ 1 -w_1 \cdot 2 - w_2 \cdot 1 - b \geq 1 w12w21b1
(3, 2) -1 − w 1 ⋅ 3 − w 2 ⋅ 2 − b ≥ 1 -w_1 \cdot 3 - w_2 \cdot 2 - b \geq 1 w13w22b1

更新后的 G G G 矩阵和 h h

上一篇:C++入门基础知识129—【关于C 库函数 - time】


下一篇:使用Python读取CSV文件并计算每列的平均值