资讯动态

手推SVM对偶问题:从拉格朗日到SMO算法全解析

发布时间:2026/10/13 1:19:16 来源:尧图企业网站定制
1. 这不是“抄公式”而是亲手把SVM的骨架一节节拼出来你有没有试过翻开《统计学习方法》第7章看到拉格朗日对偶、KKT条件、核函数定义那一堆符号手指停在书页上脑子却卡在“为什么非得转成对偶问题”“Slater条件到底在验什么”“SMO里那个α₂更新公式是怎么蹦出来的”——不是记不住是没真正摸到它的关节。这篇笔记不讲“SVM是什么”它只干一件事用一支笔、一张纸、一个Python解释器从原始优化问题出发亲手推一遍对偶化全过程把每个等号成立的依据、每个不等式收紧的动机、每个算法步骤背后的几何直觉全摊开在你眼前。核心关键词就五个手推SVM、对偶问题、Slater条件、核技巧、SMO算法。它适合三类人刚学完SVM理论但推导总像隔着毛玻璃的研究生想把面试中“请手推SVM”这个高频题答出深度的求职者或者像我一样写过几十次SVM调包代码却某天突然想确认“scikit-learn里fit()那0.3秒背后到底发生了多少次坐标上升”。这不是速成课它要求你暂停5分钟拿出草稿纸在“minimize (1/2)||w||²”这行字后面亲手写下第一个拉格朗日函数。推导中所有关键转折点——比如为什么原始问题强对偶性不保证而对偶问题在Slater条件下能保证为什么高斯核能把圆圈数据映射成线性可分为什么SMO必须每次只优化两个α而不能三个——都会配上我在某次深夜调试时画歪的示意图、实测收敛曲线以及被删掉又重写的第三版SMO代码注释。它不承诺让你明天就发顶会但它能让你下次看到“max_α min_w,b L(w,b,α)”时心里清楚知道这串符号不是魔法咒语而是凸优化给我们的、一份可执行的施工图纸。2. 对偶问题为什么非得绕这么大弯子2.1 原始问题的硬伤约束太“野”解法太“笨”我们先回到SVM最本源的出发点找一个超平面让两类样本离它尽可能远。数学上这被写成一个带不等式约束的优化问题$$ \begin{aligned} \min_{w,b} \frac{1}{2} |w|^2 \ \text{s.t. } y^{(i)}(w^T x^{(i)} b) \geq 1, \quad i 1,\dots,m \end{aligned} $$这里 $w$ 是法向量$b$ 是偏置$x^{(i)}$ 是第 $i$ 个样本$y^{(i)} \in {-1, 1}$ 是标签。目标函数 $\frac{1}{2}|w|^2$ 是凸的很好但约束条件 $y^{(i)}(w^T x^{(i)} b) \geq 1$ 是 $m$ 个线性不等式它们共同围出一个可行域。问题来了这个可行域的形状完全取决于数据分布。如果数据本身线性不可分这个可行域可能直接是空集——优化器连起点都找不到。更麻烦的是即使可行域非空它也可能是一个非常“尖锐”的多面体导致梯度下降这类通用算法在边界附近震荡剧烈收敛极慢。我曾经用一个只有50个点的合成数据集测试过直接对原始问题用scipy.optimize.minimize选择SLSQP算法迭代了2000步目标函数值还在10⁻³量级反复横跳而对偶问题在同样设置下30步就稳了。原因很简单原始问题的变量是 $w$ 和 $b$维度是 $n1$$n$ 是特征数而约束是 $m$ 个当 $m \gg n$ 时约束数量远超变量问题变得“过度约束”数值求解器就像在迷宫里蒙眼走路每一步都要反复验证是否撞墙。提示这里有个常被忽略的细节——原始问题的约束是“硬间隔”的它强制要求所有点都满足 $y^{(i)}(w^T x^{(i)} b) \geq 1$。这在现实中几乎不可能所以后续才引入松弛变量 $\xi_i$ 变成软间隔。但手推对偶必须从最干净的硬间隔开始否则后面的KKT条件会混入额外的互补松弛项徒增混乱。2.2 拉格朗日函数把约束“塞进”目标里造一个新函数为了解决约束带来的麻烦我们引入拉格朗日乘子 $\alpha_i \geq 0$为每一个约束 $y^{(i)}(w^T x^{(i)} b) \geq 1$ 配一个。拉格朗日函数 $L(w, b, \alpha)$ 就是原始目标加上所有约束乘以对应乘子的“惩罚项”$$ L(w, b, \alpha) \frac{1}{2} |w|^2 - \sum_{i1}^m \alpha_i \left[ y^{(i)}(w^T x^{(i)} b) - 1 \right] $$注意这里的符号因为原始约束是 $\geq 1$标准形式是 $g_i(w,b) \leq 0$所以我们把约束改写为 $1 - y^{(i)}(w^T x^{(i)} b) \leq 0$这样拉格朗日项就是 $-\alpha_i g_i$即 $-\alpha_i [1 - y^{(i)}(w^T x^{(i)} b)]$整理后就是上面的形式。这个函数 $L$ 的精妙之处在于对于任意固定的 $w, b$如果我们能让所有 $\alpha_i \geq 0$那么 $L(w,b,\alpha)$ 的值一定小于等于原始目标函数 $\frac{1}{2}|w|^2$。为什么因为如果 $(w,b)$ 满足所有原始约束即 $y^{(i)}(w^T x^{(i)} b) - 1 \geq 0$那么减去一个非负数$\alpha_i$ 乘以一个非负数会让 $L$ 变小或不变如果 $(w,b)$ 不满足某个约束比如第 $j$ 个那么 $y^{(j)}(w^T x^{(j)} b) - 1 0$此时只要把 $\alpha_j$ 设得足够大$L$ 就可以趋向负无穷。这意味着对于一个不满足约束的 $(w,b)$$L$ 完全失去了作为“目标代理”的意义。因此我们定义一个关于 $(w,b)$ 的函数$$ \theta_P(w,b) \max_{\alpha_i \geq 0} L(w,b,\alpha) $$这个 $\theta_P$ 被称为原始问题的广义拉格朗日函数的最大值。它的行为是当 $(w,b)$ 满足所有原始约束时$\max_\alpha L \frac{1}{2}|w|^2$因为最优的 $\alpha_i$ 全为0不加惩罚当 $(w,b)$ 不满足任一约束时$\max_\alpha L \infty$因为可以选一个 $\alpha_j$ 让 $L$ 爆掉。所以原始问题等价于$$ \min_{w,b} \theta_P(w,b) \min_{w,b} \max_{\alpha_i \geq 0} L(w,b,\alpha) $$这就是所谓的主问题Primal Problem。它看起来更复杂了但好处是我们现在有了一个无约束的外层最小化对 $w,b$而内层最大化对 $\alpha$是一个线性操作相对友好。2.3 对偶问题诞生交换“min”和“max”的顺序现在我们考虑一个看似“违规”的操作把上面式子中的 $\min$ 和 $\max$ 顺序交换得到$$ \max_{\alpha_i \geq 0} \min_{w,b} L(w,b,\alpha) \max_{\alpha_i \geq 0} \theta_D(\alpha) $$这个新问题被称为对偶问题Dual Problem其中 $\theta_D(\alpha) \min_{w,b} L(w,b,\alpha)$。根据数学上的极大极小不等式Max-Min Inequality无论函数 $L$ 是什么恒有$$ \max_{\alpha} \min_{w,b} L(w,b,\alpha) \leq \min_{w,b} \max_{\alpha} L(w,b,\alpha) $$也就是说对偶问题的最优值 $d^$永远小于等于原始问题的最优值 $p^$。这个差值 $p^* - d^$ 被称为对偶间隙Duality Gap。如果 $p^ d^*$我们就说强对偶性Strong Duality成立。这时解对偶问题就等价于解原始问题而且对偶问题往往有更好的性质。那么什么条件下强对偶性成立这就是Slater条件要回答的问题。2.4 Slater条件一个“温和”的可行性检验Slater条件是凸优化中一个非常实用的充分条件。它说如果原始问题是凸的目标函数凸不等式约束函数 $g_i$ 凸等式约束线性并且存在一个点 $(\tilde{w}, \tilde{b})$使得所有不等式约束严格成立即 $g_i(\tilde{w}, \tilde{b}) 0$那么强对偶性一定成立。回到我们的SVM原始问题目标 $\frac{1}{2}|w|^2$ 是凸的约束 $g_i(w,b) 1 - y^{(i)}(w^T x^{(i)} b) \leq 0$ 是线性的因此也是凸的。所以Slater条件适用。它要求存在某个 $(\tilde{w}, \tilde{b})$使得对所有 $i$都有 $1 - y^{(i)}(\tilde{w}^T x^{(i)} \tilde{b}) 0$即 $y^{(i)}(\tilde{w}^T x^{(i)} \tilde{b}) 1$。这在几何上意味着存在一个超平面它不仅能分开两类数据而且能把所有点都“推”到各自类别的安全距离之外margin 1。这听起来很苛刻但其实它比“数据线性可分”还要弱一点。因为“线性可分”只要求存在一个超平面让所有点满足 $y^{(i)}(w^T x^{(i)} b) 0$而Slater要求的是 $1$。不过在实际数据中只要数据是线性可分的我们总可以通过缩放 $w$ 和 $b$ 来放大margin从而满足Slater条件。例如如果有一个超平面让所有点满足 $y^{(i)}(w^T x^{(i)} b) 0.5$那么把 $w$ 和 $b$ 同时乘以2就能得到 $y^{(i)}(2w^T x^{(i)} 2b) 1$。所以对于线性可分的数据Slater条件天然满足强对偶性成立。这是整个对偶推导合法性的基石。没有它我们后面所有关于KKT条件的讨论都可能失效。注意Slater条件是充分条件不是必要条件。有些问题即使不满足Slater强对偶性也可能成立。但在SVM这种标准凸问题里我们默认它成立这样就可以放心地用KKT条件来求解。3. 核技巧与SMO从纸面推导到键盘敲代码3.1 从对偶问题到支持向量推导的终点应用的起点既然强对偶性成立我们就可以放心地求解对偶问题。首先计算 $\theta_D(\alpha) \min_{w,b} L(w,b,\alpha)$。这是一个无约束优化对 $w$ 和 $b$ 分别求偏导并令其为0对 $w$ 求导$\nabla_w L w - \sum_{i1}^m \alpha_i y^{(i)} x^{(i)} 0$得到 $w \sum_{i1}^m \alpha_i y^{(i)} x^{(i)}$。对 $b$ 求导$\nabla_b L -\sum_{i1}^m \alpha_i y^{(i)} 0$得到 $\sum_{i1}^m \alpha_i y^{(i)} 0$。这两个等式就是KKT条件中的平稳性条件Stationarity。把 $w$ 的表达式代回 $L$并利用 $\sum \alpha_i y^{(i)} 0$经过一番代数运算展开平方项、合并同类项$L$ 就简化为一个只关于 $\alpha$ 的函数$$ \theta_D(\alpha) \sum_{i1}^m \alpha_i - \frac{1}{2} \sum_{i1}^m \sum_{j1}^m \alpha_i \alpha_j y^{(i)} y^{(j)} (x^{(i)})^T x^{(j)} $$于是对偶问题就变成了$$ \begin{aligned} \max_{\alpha} \sum_{i1}^m \alpha_i - \frac{1}{2} \sum_{i1}^m \sum_{j1}^m \alpha_i \alpha_j y^{(i)} y^{(j)} (x^{(i)})^T x^{(j)} \ \text{s.t. } \sum_{i1}^m \alpha_i y^{(i)} 0, \quad 0 \leq \alpha_i \leq C \quad (\text{软间隔引入}) \end{aligned} $$这里加入了软间隔的上限 $C$硬间隔时 $C\infty$但实际实现中总是设一个有限值。这个目标函数的关键在于最后一项$\sum_{i,j} \alpha_i \alpha_j y^{(i)} y^{(j)} (x^{(i)})^T x^{(j)}$。它只依赖于样本之间的内积$(x^{(i)})^T x^{(j)}$。这就是核技巧的入口。如果我们不是在原始特征空间 $\mathbb{R}^n$ 中工作而是先通过一个映射 $\phi: \mathbb{R}^n \to \mathcal{F}$ 把数据映射到一个更高维甚至无限维的特征空间 $\mathcal{F}$那么超平面的法向量 $w$ 就变成了 $w \sum_i \alpha_i y^{(i)} \phi(x^{(i)})$而对偶问题中的内积就变成了 $\phi(x^{(i)})^T \phi(x^{(j)})$。如果存在一个函数 $K(x^{(i)}, x^{(j)}) \phi(x^{(i)})^T \phi(x^{(j)})$我们就可以完全避免显式计算 $\phi$直接用 $K$ 来代替内积。这就是核函数Kernel Function。常见的有线性核$K(x,z) x^T z$多项式核$K(x,z) (x^T z c)^d$高斯径向基核RBF$K(x,z) \exp(-\gamma |x-z|^2)$RBF核之所以强大是因为它对应的 $\phi$ 映射到了一个无限维空间理论上能将任何数据集映射成线性可分。我在一个经典的“同心圆”数据集上测试过原始二维空间里两个圆圈套在一起线性分类器束手无策但换上RBF核$\gamma1.0$仅仅20个支持向量决策边界就完美地贴合了内圆轮廓。这背后是核函数在隐式地计算高维空间中点与点的相似度。3.2 SMO算法把一个大问题拆成无数个2元小问题对偶问题是一个带约束的二次规划QP问题。对于 $m$ 个样本它有 $m$ 个变量 $\alpha_i$。通用QP求解器如cvxopt的时间复杂度是 $O(m^3)$当 $m10^4$ 时计算量就到了 $10^{12}$ 级别完全不可行。SMOSequential Minimal Optimization算法由Platt在1998年提出其核心思想是每次只优化两个拉格朗日乘子 $\alpha_i$ 和 $\alpha_j$而固定其余所有 $\alpha_k$。为什么是两个因为对偶问题有一个等式约束 $\sum \alpha_i y^{(i)} 0$。如果只优化一个 $\alpha_i$那么为了满足这个等式其他所有 $\alpha_k$ 都得跟着动这就又回到了原问题。而优化两个我们可以利用这个等式把其中一个用另一个表示出来从而把二元优化变成一元优化且解析可解。假设我们选定 $\alpha_1$ 和 $\alpha_2$ 进行优化。由 $\sum \alpha_i y^{(i)} 0$有 $\alpha_1 y^{(1)} \alpha_2 y^{(2)} -\sum_{i3}^m \alpha_i y^{(i)} \text{const} \zeta$。所以 $\alpha_1 \frac{\zeta - \alpha_2 y^{(2)}}{y^{(1)}}$。将其代入对偶目标函数目标函数就变成了一个关于 $\alpha_2$ 的纯二次函数$W(\alpha_2) a \alpha_2^2 b \alpha_2 c$。求导令其为0就能得到 $\alpha_2$ 的无约束最优解 $\alpha_2^{\text{unc}}$。但 $\alpha_2$ 还有上下界$0 \leq \alpha_2 \leq C$并且由于 $\alpha_1$ 也必须在 $[0,C]$ 内这会给 $\alpha_2$ 带来额外的约束。最终$\alpha_2$ 的更新公式是$$ \alpha_2^{\text{new}} \text{clip}\left( \alpha_2^{\text{unc}}, ; L, ; H \right) $$其中 $L$ 和 $H$ 是根据 $y^{(1)}$ 和 $y^{(2)}$ 是否相等而确定的边界。这个“clip”操作就是SMO里最常被问到的“为什么是max和min套着写”的来源。我在第一次手写SMO时就在这里卡了整整一天。我把 $L$ 和 $H$ 的推导过程写在下面这张图里文字描述当 $y^{(1)} y^{(2)}$ 时$\alpha_1 \alpha_2 \zeta$所以 $\alpha_2$ 的范围是 $[\max(0, \zeta-C), \min(C, \zeta)]$当 $y^{(1)} \neq y^{(2)}$ 时$\alpha_1 - \alpha_2 \zeta$所以 $\alpha_2$ 的范围是 $[\max(0, -\zeta), \min(C, C-\zeta)]$。这个边界逻辑是SMO能稳定收敛的保障。3.3 从推导到代码一个极简但完整的SMO实现下面是一段不到100行的、可直接运行的SMO Python实现。它没有用任何机器学习库只依赖numpy目的是让你看清每一行代码对应的是哪一步推导。import numpy as np def smo_simple(X, y, C, max_passes, tol): 简化版SMO算法实现 X: (m, n) 特征矩阵 y: (m,) 标签向量值为-1或1 C: 软间隔参数 max_passes: 最大外层循环次数 tol: KKT条件容忍度 m, n X.shape alphas np.zeros(m) # 初始化所有alpha为0 b 0.0 passes 0 # 计算核矩阵这里用线性核K[i,j] X[i] X[j] K X X.T while passes max_passes: num_changed_alphas 0 for i in range(m): # 计算第i个样本的预测值 E_i f(x_i) - y_i # f(x_i) sum_j(alpha_j * y_j * K[j,i]) b fXi np.sum(alphas * y * K[:, i]) b Ei fXi - y[i] # 检查KKT条件如果alpha_i在(0,C)内则E_i应为0如果alpha_i0则E_i*y_i0如果alpha_iC则E_i*y_i0 if (y[i] * Ei -tol and alphas[i] C) or (y[i] * Ei tol and alphas[i] 0): # 随机选择第二个alpha j确保j ! i j np.random.choice([k for k in range(m) if k ! i]) # 计算E_j fXj np.sum(alphas * y * K[:, j]) b Ej fXj - y[j] # 保存旧值用于后续计算 alpha_i_old, alpha_j_old alphas[i], alphas[j] # 计算L和H if y[i] ! y[j]: L max(0, alphas[j] - alphas[i]) H min(C, C alphas[j] - alphas[i]) else: L max(0, alphas[i] alphas[j] - C) H min(C, alphas[i] alphas[j]) if L H: continue # 计算eta K[i,i] K[j,j] - 2*K[i,j] eta K[i,i] K[j,j] - 2 * K[i,j] if eta 0: continue # 计算alpha_j的无约束最优解 alpha_j_new_unc alphas[j] y[j] * (Ei - Ej) / eta # clip到[L, H] alphas[j] np.clip(alpha_j_new_unc, L, H) # 如果变化太小跳过 if abs(alphas[j] - alpha_j_old) 1e-5: continue # 计算alpha_i的新值 alphas[i] alphas[i] y[i] * y[j] * (alpha_j_old - alphas[j]) # 更新b b1 b - Ei - y[i] * (alphas[i] - alpha_i_old) * K[i,i] - y[j] * (alphas[j] - alpha_j_old) * K[i,j] b2 b - Ej - y[i] * (alphas[i] - alpha_i_old) * K[i,j] - y[j] * (alphas[j] - alpha_j_old) * K[j,j] if 0 alphas[i] C: b b1 elif 0 alphas[j] C: b b2 else: b (b1 b2) / 2.0 num_changed_alphas 1 if num_changed_alphas 0: passes 1 else: passes 0 return alphas, b # 使用示例 np.random.seed(42) # 生成一个简单的线性可分数据集 X np.array([[1, 2], [2, 3], [3, 3], [2, 1], [3, 2], [4, 2]]) y np.array([1, 1, 1, -1, -1, -1]) C 1.0 alphas, b smo_simple(X, y, C, max_passes20, tol1e-3) print(Alphas:, alphas) print(Bias b:, b)这段代码的核心就是把前面推导的每一步都翻译成了Python。比如eta的计算对应的是二阶导数曲率clip对应的是边界处理b1和b2的计算则源于KKT条件中对支持向量的补偿。我在调试时发现eta 0的判断至关重要——它防止了在 $x^{(i)}$ 和 $x^{(j)}$ 几乎相同时分母为零导致数值爆炸。另外“如果变化太小就跳过”这个判断是SMO收敛速度的保障它避免了在最优解附近做无意义的微调。4. 实操心得与避坑指南那些书上不会写的细节4.1 关于数据预处理归一化不是可选项是必选项很多人在第一次跑SMO时会遇到“算法不收敛”或“alpha全为0”的问题。我踩过的最大一个坑就是在处理一个包含身高单位cm范围150-200和年收入单位元范围30000-2000000的混合特征数据集时没有做归一化。结果SMO在优化过程中年收入特征主导了内积 $K[i,j]$ 的计算导致身高信息被完全淹没。alphas的更新方向严重偏向年收入维度算法花了上千次迭代才勉强找到一个margin极小的解。解决方法极其简单在输入SMO之前对每个特征列进行Z-score标准化减均值除标准差。这不仅让不同量纲的特征获得同等权重更重要的是它让核函数 $K(x,z) \exp(-\gamma |x-z|^2)$ 中的欧氏距离计算变得合理。因为 $|x-z|^2$ 是各维度差值的平方和如果一个维度的数值天生就比其他维度大几个数量级那么距离就完全由它决定。标准化后所有维度对距离的贡献是均衡的。这个教训让我养成了一个铁律任何涉及距离、内积、范数的算法第一步永远是标准化。4.2 关于核函数选择RBF不是万金油线性核有时更优网络上充斥着“RBF核效果最好”的说法这在很多情况下是对的但绝非绝对。我在一个文本分类项目中用TF-IDF向量维度高达50000训练SVM。当我尝试RBF核时gamma0.001训练时间超过2小时内存占用飙升到16GB而准确率只比线性核高了0.3%。原因在于高维稀疏向量下RBF核的计算 $K[i,j] \exp(-\gamma |x_i-x_j|^2)$ 需要先计算一个巨大的稠密距离矩阵这本身就是一场灾难。而线性核 $K[i,j] x_i^T x_j$可以利用向量的稀疏性用高效的稀疏矩阵乘法如scipy.sparse.csr_matrix来加速几秒钟就能完成。所以我的经验是当特征维度 $n$ 很高1000且向量稀疏时优先尝试线性核当 $n$ 较低100且数据呈现复杂的非线性结构时再系统地调参RBF核的 $\gamma$ 和 $C$。调参时我习惯用一个对数网格$\gamma \in {10^{-3}, 10^{-2}, 10^{-1}, 1, 10}$$C \in {10^{-1}, 1, 10, 100}$用5折交叉验证选最优组合。记住$\gamma$ 控制单个样本的影响半径$\gamma$ 越大影响越局部$C$ 控制对误分类的惩罚$C$ 越大margin越窄越容易过拟合。4.3 关于SMO的收敛判断别只看“passes”要看KKT残差SMO的官方停止条件是“外层循环连续max_passes次都没有更新任何alpha”但这在实践中过于保守。我见过一个案例数据集有1000个点max_passes10算法跑了15轮才停但最后检查发现有3个alpha的KKT条件残差即 $|y_i f(x_i) - 1|$ 对于 $0\alpha_iC$ 的点还高达0.05远超设定的tol0.001。这是因为SMO的随机配对策略有可能在某一轮里恰好避开了那些KKT条件最不满足的点。所以我在自己的实现里增加了一个更严格的检查在每次外层循环结束后遍历所有 $i$计算其KKT残差并记录最大值max_violation。只有当max_violation tol时才认为真正收敛。这个改动让我的SMO在相同数据上平均迭代轮数减少了40%且最终解的质量更稳定。代码片段如下# 在每次外层循环结束时添加 max_violation 0.0 for i in range(m): fXi np.sum(alphas * y * K[:, i]) b if 0 alphas[i] C: violation abs(y[i] * fXi - 1) elif alphas[i] 0: violation max(0, 1 - y[i] * fXi) else: # alphas[i] C violation max(0, y[i] * fXi - 1) max_violation max(max_violation, violation) if max_violation tol: break4.4 关于支持向量的识别别只看“alpha 0”要看“alpha tol”在理论推导中我们说“只有支持向量的alpha非零”。但在浮点数计算的世界里“非零”是个伪命题。由于数值误差一些本该是0的alpha可能会是 $10^{-15}$ 这样的量级。如果代码里写support_vectors X[alphas 0]你会把成百上千个“噪声”点都当成支持向量导致模型臃肿、预测变慢。正确的做法是设定一个与tol同量级的阈值比如1e-5然后写support_vectors X[alphas 1e-5]。我在一个图像特征数据集上测试过用0会选出1200个SV而用1e-5只选出237个预测速度提升了5倍准确率反而略有提升因为滤除了数值噪声。这个细节是连接纸面理论和键盘实践之间一道必须跨过的沟。5. 常见问题速查表从报错到原理一网打尽问题现象可能原因排查思路我的解决方案SMO训练时间过长迭代次数远超预期1. 数据未归一化导致梯度方向病态2.C或gamma设置过大使优化曲面过于陡峭3. 初始alphas全为0算法需要很长时间才能“激活”第一个支持向量1. 检查每个特征的标准差若差异100倍立即标准化2. 尝试将C从100降到1gamma从1降到0.1观察收敛速度我在所有项目中都强制加入预处理步骤X (X - X.mean(axis0)) / (X.std(axis0) 1e-8)。这个1e-8是防除零是血泪教训。训练完成后alphas全为0或全为C1. 数据线性不可分且C设置过小算法选择“放弃”所有点2. 标签y的值不是严格的-1和1而是0和1导致KKT条件计算错误1. 打印y的唯一值np.unique(y)2. 检查原始问题是否可行随便找一个超平面如w[1,0], b0看有多少点满足y[i]*(wX[i]b) 1必须确保y是[-1, 1]。我写了一个校验函数y np.where(y0, -1, 1)并在数据加载后第一行就调用它。使用RBF核时K[i,j]矩阵出现大量nan或infgamma设置过大导致exp(-gamma * huge_number)下溢为0或exp(-gamma * negative_number)上溢为inf计算 np.max(np.abs(X - X[0

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑