使用Pegasos小批量算法求解SVM优化遇numpy浮点精度问题
嘿,我明白你遇到的麻烦了——用Pegasos小批量算法实现SVM时,total变量要么是0,要么是1e-1到1e-5的极小值,乘以eta/k后直接变成0,导致权重w根本没法更新,一直停留在初始的0向量。这其实是实现Pegasos时常见的数值精度和逻辑问题,我给你几个具体的排查和修复方向:
先核对Pegasos学习率
eta的计算是否正确
别忘了Pegasos的学习率公式是eta = 1/(lambda * t),其中t是当前的迭代次数(必须从1开始计数,不能从0),lambda是正则化系数。如果t起始错了或者lambda设得太大,eta会变得极小,再除以小批量大小k后,eta/k的缩放因子会把total的微小值直接压到0。建议你在迭代过程中打印eta、k、eta/k这几个值,确认它们的数量级是否合理。切换到64位浮点数存储避免数值下溢
如果你现在用的是32位浮点数(float)来存储total、w这些变量,1e-5量级的数值已经接近float的精度下限(约1e-7),再乘以一个小的eta/k很容易触发下溢变成0。把所有相关变量都换成64位浮点数(double),这样能保留更多的小数位,极大降低下溢的概率。重构更新规则的计算顺序减少精度损失
原始的Pegasos更新规则是:w = (1 - eta*lambda)*w + (eta/k)*total你可以调整计算顺序,先计算
(eta/k)*total这部分(用double存储),再和(1 - eta*lambda)*w相加。另外,也要确保1 - eta*lambda的结果是正数——如果eta*lambda >= 1,那w会被直接清零,这显然不对,这时候你需要调整lambda或者t的起始值。检查
total的计算逻辑是否符合Pegasos定义
回忆一下,Pegasos小批量中的total是所有满足y_i*(w·x_i) < 1的样本的y_i*x_i之和。初始时w是0,所以y_i*(w·x_i)应该是0,所有样本都应该被纳入total的计算,这时候total不应该大多是0才对!这说明你的total计算逻辑可能有问题:比如是不是把标签y_i的取值当成了{0,1}(而不是Pegasos要求的{-1,1})?或者误判了样本的条件(比如写成了>=1而不是<1)?这部分一定要仔细核对。调整正则化参数
lambda的大小
如果lambda太大,会导致1 - eta*lambda非常接近0,甚至变成负数(当t很小时),这会严重压制w的更新。你可以尝试减小lambda的值,比如从1e-4开始逐步调整,确保eta*lambda的结果在0到1之间,这样(1 - eta*lambda)才会是一个合理的衰减因子。
内容的提问来源于stack exchange,提问作者scottstots

