我的Python版玩具SVM中的错误是什么?

时间:2015-10-29 23:58:05

标签: python machine-learning

我目前正在通过Andrej Karpathy的Hacker's guide to Neural Networks。在第2章:机器学习,二进制分类中,他举了一个(非常基本的)SVM的例子。这是Karpathy的代码:

var a = 1, b = -2, c = -1; // initial parameters
for(var iter = 0; iter < 400; iter++) {
  // pick a random data point
  var i = Math.floor(Math.random() * data.length);
  var x = data[i][0];
  var y = data[i][1];
  var label = labels[i];

// compute pull
  var score = a*x + b*y + c;
  var pull = 0.0;
  if(label === 1 && score < 1) pull = 1;
  if(label === -1 && score > -1) pull = -1;

// compute gradient and update parameters
  var step_size = 0.01;
  a += step_size * (x * pull - a); // -a is from the regularization
  b += step_size * (y * pull - b); // -b is from the regularization
  c += step_size * (1 * pull);
}

以下是我在Python中的版本:

import numpy
import random

X = numpy.array([[1.2, 0.7],
                 [-0.3, 0.5],
                 [-3, -1],
                 [0.1, 1.0],
                 [3.0, 1.1],
                 [2.1, -3]])

labels = [1, -1, 1, -1, -1, 1]

a = 1
b = -2
c = -1

l = len(X)-1

steps = 400

for n in range(0, steps):
    i = random.randint(0, l)
    x = X[i][0]
    y = X[i][1]
    label = labels[i]

    if n == 0:
            for j in range(0, l+1):
                x = X[j][0]
                y = X[j][1]
                label = labels[j]
                score = a*x + b*y + c
                print x,",",y,"-->", label, "vs.", score

    score = a*x + b*y + c
    pull = 0.0
    if label == 1 and score < 1:
        pull = 1
    if label == -1 and score > -1:
        pull = -1

    step_size = 0.01
    a += step_size * (x * pull - a)
    b += step_size * (y * pull - b)
    c += step_size * (1 * pull)

    if n == steps-1:
        print ""
        for j in range(0, l+1):
            x = X[j][0]
            y = X[j][1]
            label = labels[j]
            score = a*x + b*y + c
            print x,",",y,"-->", label, "vs.", score

问题是,即使超过建议的400次迭代,对于某些向量,参数也不会产生正确的标签。

以下是400次迭代后的输出:

1.2 , 0.7 --> 1 vs. -0.939483353298
-0.3 , 0.5 --> -1 vs. -0.589208602761
-3.0 , -1.0 --> 1 vs. 0.651953448705
0.1 , 1.0 --> -1 vs. -0.921882586141
3.0 , 1.1 --> -1 vs. -1.44552077331
2.1 , -3.0 --> 1 vs. 0.896623596303

“ - &gt;”之后的第一个值是正确的标签,第二个值是分数,即学习标签。

所有矢量/学习标签都是正确的(在分配带正确符号的值的意义上),第一个除外。

我不确定原因是什么:我的代码出错了吗?我检查了几次,但没有找到任何东西。或者我忘记了Python特有的东西。或者,最后,是否有一些ML相关的原因,为什么在这种情况下没有学习正确的标签。但是要怀疑它,否则Karpathy得到了正确的结果是没有意义的。

任何评论或帮助我们都非常感激。

1 个答案:

答案 0 :(得分:2)

我相信我发现了问题:

(A)您的数据集没有线性切割。

(B)Karpathy&#34; Monte Carlo&#34;在这样的数据集上出现梯度下降。

(C)你和Karpathy使用了不同的数据。

DATA SETS
label   Karpathy's      yours
  1     [1.2, 0.7]      [1.2, 0.7]
 -1     [-0.3, -0.5]    [-0.3, 0.5]
  1     [3.0, 0.1]      [-3, -1]
 -1     [-0.1, -1.0]    [0.1, 1.0]
 -1     [-1.0, 1.1]     [3.0, 1.1]
  1     [2.1, -3]       [2.1, -3]

你给出的数据集大致有一条切割线(超平面) y = 1 / 3x + 1/2,但该线的三个角落不断争论分裂。事实证明,最好的分频器明显不同,将[1.2,0.7]严重地放在线路的错误一侧,但对此非常不满。

原始数据在y = -3x + 1处有一条整齐的切割线,该算法大致近似于(舍入的)0.6x - 0.1y - 0.5

同样,这个算法正在寻找最低成本的契合而不是纯粹的#34;最广泛分离通道的SVM。即使 是一条整齐的切割线,这个算法也不会收敛它;相反,它破坏了通往可接受解决方案附近的方式。

它选择一个随机点。如果该点被严格分类 - 得分是正确的符号,其幅度大于&gt; 1 - 没有任何反应。但是,如果该点位于线的错误一侧,或者甚至太接近舒适度,那么它会拉出参数以获得更有利的处理。

除非频道宽2个单位,否则争议地区内的积分将继续轮流推迟。没有收敛标准......事实上,在某一点之后没有收敛保证。

仔细查看Karpathy的代码:主算法对数据点进行更改,得分<&lt; 1或&gt; -1(取决于培训课程)。然而,如果结果的符号是正确的,则评估算法要求胜利。这是合理的,但它与训练功能并不完全一致。在我的试验中,第一点总是具有幅度<1的分数。 0.07,但实际值华夫饼在0的两边。其他点很清楚0,但只有两个传递1.有四点争论线应该在哪里。

这对你有用吗?