我目前正在通过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得到了正确的结果是没有意义的。
任何评论或帮助我们都非常感激。
答案 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.有四点争论线应该在哪里。
这对你有用吗?