You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于CVXPY的SVM实现问题:RBF与线性核持续报错

SVM(CVXPY实现)维度错误与核函数问题修正方案

核心问题分析

  • 变量维度定义错误:原代码中alpha = cp.Variable(n),但SVM对偶问题中alpha是每个样本对应的拉格朗日乘子,维度应为样本数m而非特征数n,混淆了原始问题与对偶问题的变量定义。
  • 约束条件维度不匹配:原约束用cp.sum()压缩维度,导致无法对应每个样本的约束要求,正确逻辑应为每个样本单独满足y_i*(决策函数) >= 1 - xi_i。
  • 核函数未实际调用:仅定义了线性/RBF核函数,但fit过程未使用,无法实现核SVM的非线性分类能力。
  • 类方法缩进错误:plot_decision_boundary未作为SVM类的方法缩进,导致调用失败。
  • 预测逻辑错误:原predict函数的决策边界计算不符合SVM理论,尤其无法适配核函数场景。

修正步骤与完整代码

1. 基于对偶问题实现通用核SVM

统一采用对偶形式实现,同时支持线性与RBF核:

import numpy as np
import cvxpy as cp
import matplotlib.pyplot as plt

class SVM:
    def __init__(self, kernel='linear', C=1.0, gamma=0.1):
        self.kernel = kernel
        self.C = C
        self.gamma = gamma
        self.alpha = None
        self.b = None
        self.X_train = None
        self.y_train = None

    def _linear_kernel(self, X1, X2):
        # 计算线性核矩阵:(m1,n) @ (n,m2) -> (m1,m2)
        return np.dot(X1, X2.T)

    def _rbf_kernel(self, X1, X2):
        # 计算RBF核矩阵
        m1, _ = X1.shape
        m2, _ = X2.shape
        kernel_matrix = np.zeros((m1, m2))
        for i in range(m1):
            for j in range(m2):
                kernel_matrix[i,j] = np.exp(-self.gamma * np.sum((X1[i] - X2[j])**2))
        return kernel_matrix

    def _get_kernel_matrix(self, X1, X2):
        if self.kernel == 'linear':
            return self._linear_kernel(X1, X2)
        elif self.kernel == 'rbf':
            return self._rbf_kernel(X1, X2)
        else:
            raise ValueError("仅支持'linear'或'rbf'核函数")

    def fit(self, X, y):
        m, n = X.shape
        self.X_train = X
        self.y_train = y

        # 对偶问题变量:alpha为每个样本的拉格朗日乘子,维度(m,)
        alpha = cp.Variable(m)
        # 松弛变量xi,每个样本对应一个,维度(m,)
        xi = cp.Variable(m)

        # 计算核矩阵
        K = self._get_kernel_matrix(X, X)

        # 构建约束条件
        constraints = []
        constraints.append(alpha >= 0)
        constraints.append(alpha <= self.C)
        constraints.append(xi >= 0)
        # 每个样本的约束:y_i*(sum_j(alpha_j*y_j*K_ij) + b) >= 1 - xi_i
        y_col = y.reshape(-1, 1)
        constraints.append(cp.multiply(y_col, K @ cp.multiply(alpha, y_col) + self.b) >= 1 - xi)

        # 对偶问题目标函数(转为最小化形式)
        obj = cp.Minimize(0.5 * cp.quad_form(cp.multiply(alpha, y), K) - cp.sum(alpha) + self.C * cp.sum(xi))

        # 求解优化问题
        prob = cp.Problem(obj, constraints)
        prob.solve()

        # 保存结果
        self.alpha = alpha.value
        # 从支持向量计算偏置b(选取0<alpha<C的样本)
        support_vec_idx = np.where((self.alpha > 1e-5) & (self.alpha < self.C - 1e-5))[0]
        if len(support_vec_idx) > 0:
            self.b = np.mean(y[support_vec_idx] - np.dot(K[support_vec_idx], cp.multiply(alpha.value, y).value))
        else:
            self.b = 0.0

    def predict(self, X):
        # 计算决策函数:sum_j(alpha_j*y_j*K(x, X_j)) + b
        K = self._get_kernel_matrix(X, self.X_train)
        decision = np.dot(K, cp.multiply(self.alpha, self.y_train).value) + self.b
        return np.sign(decision)

    def plot_decision_boundary(self, X, y):
        plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired, edgecolors='k', marker='o')

        x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
        y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1

        xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
                             np.arange(y_min, y_max, 0.1))

        Z = self.predict(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)

        plt.contourf(xx, yy, Z, alpha=0.3, levels=[-1, 0, 1], cmap=plt.cm.Paired)
        plt.xlabel('Feature 1')
        plt.ylabel('Feature 2')
        plt.title(f'Decision Boundary for {self.kernel.capitalize()} SVM')
        plt.show()

# 训练数据
X_train = np.array([[1, 2], [2, 3], [3, 4], [4, 5]])
y_train = np.array([-1, -1, 1, 1])

# 线性核SVM测试
svm_linear = SVM(kernel='linear', C=1.0)
svm_linear.fit(X_train, y_train)
svm_linear.plot_decision_boundary(X_train, y_train)

# RBF核SVM测试
svm_rbf = SVM(kernel='rbf', C=1.0, gamma=0.5)
svm_rbf.fit(X_train, y_train)
svm_rbf.plot_decision_boundary(X_train, y_train)

关键修正说明

  • 变量维度修正:将alpha维度改为样本数m,符合对偶SVM的理论定义。
  • 核矩阵适配:实现线性与RBF核的矩阵计算逻辑,满足对偶问题的核函数需求。
  • 约束条件修复:去掉错误的维度压缩操作,确保每个样本单独满足约束,解决维度不兼容问题。
  • 偏置b计算:从支持向量中推导计算b,符合SVM的理论推导逻辑。
  • 预测逻辑修正:基于核矩阵计算决策函数,同时支持线性与非线性分类场景。
  • 类方法修复:将plot_decision_boundary调整为类的内部方法,确保调用正常。

内容的提问来源于stack exchange,提问作者fallou0202

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 07:29:51