我试图使用delta训练规则为AND布尔函数训练感知器。但即使在收敛之后,它也错误地对输入进行了分类(实际上是1个输入)。你能告诉我我错在哪里:http://ideone.com/CDgTQE
这是使用的训练功能:
public void trianWithDelta(Example[] examples){
for(int i=0;i<1000;++i){
dw1 = 0;
dw2 = 0;
for(Example ex:examples){
double o = computeOutput(ex);
double t = ex.o;
dw1 = dw1 + n*(t-o)*ex.x1;
dw2 = dw2 + n*(t-o)*ex.x2;
}
w1 += dw1;
w2 += dw2;
}
}
训练样例(布尔AND):
Example[] examples = new Example[]{
new Example(-1, -1, -1),
new Example(-1 , 1, -1),
new Example( 1, -1, -1),
new Example( 1, 1, 1)
};
结果: w1:0.49999999999999994 w2:0.5000000000000002
培训后使用培训示例进行测试:
-1
1(不正确)
-1
1
答案 0 :(得分:1)
你的代码实际上是正确,问题在于你理解使用无偏见的感知器可以学到什么,什么不可以。
如果你没有偏见,那么学习AND几乎是不可能的,因为:
y=-x
实现的,在您的代码中它意味着w1=w2
,甚至是它们的值之间的最小差异将打破分类器(例如1e-20
)尝试在纸上画出正确的分隔符,你会注意到,没有偏差你的线必须交叉(0,0),因此,它必须是y = -x,因此对于(-1, 1)和(1,-1)激活为0。
只需添加偏置节点就可以解决这两个问题(这就是你应该做的)。
您还可以更改AND的“位”定义 - 例如,将“False”编码为-2
Example[] examples = new Example[]{
new Example(-2, -2, -2),
new Example(-2 , 1, -2),
new Example( 1, -2, -2),
new Example( 1, 1, 1)
};
运行代码的行为符合预期
Trained weights : 0.6363636363636364 0.6363636363636364
-1
-1
-1
1