(1)设置权重值为[-0.5,0.5]
(2)选择阶跃函数为激活函数,即大于0则为1,其他为0
(3)训练权重:
误差=真实值-训练值
新权重=原权重+学习率 (误差>0)
新权重=原权重+学习率 (误差<0)
误差为0权重不变
(4)迭代直到收敛,收敛的条件是4种情况误差都为0
简单代码如下:
import java.util.*;
public class AndOrPrecptron {
//计算输出值
/*
x1、x2:输入值
w1、w2:对应输入值权重
b:控制阈值,应仔细选择
返回值:输出值
*/
public double caclOutput(int x1,int x2,double w1,double w2,double b)
{
return x1*w1+x2*w2-b;
}
//使用阶跃函数做为激活函数sign
/*
* out:输出的值
* 返回值:结果
*/
public int activatorSign(double out)
{
if(out>0) return 1;
else return 0;
}
//计算误差
/*
* out:输出的结果值,real:真实值
*/
public int caclError(int out,int real)
{
return real-out;
}
//更新权重
/*
* x:之前的输入值,w:对应权重,err:误差,a:学习率
*/
public double updateWeight(int x,double w,int err,double a)
{
if(x==0)
return w;
else
if(err>0)
return w+a;
else if(err<0)
return w-a;
else
return w;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
AndOrPrecptron p=new AndOrPrecptron();
int[][] input= {{0,0},{0,1},{1,0},{1,1}};
int[] real= {0,0,0,1};
Random r=new Random();
//初始权重在[-0.5,0.5]
double w1=r.nextDouble()-0.5;
double w2=r.nextDouble()-0.5;
//w1=0.3;
//w2=-0.1;
double a=0.1;//学习率
double b=0.2;//阈值,这个选择比较重要
int s=1; //是否收敛的标志,如果为0就收敛,否则不收敛
while(s!=0)
{
s=0;
for(int i=0;i<input.length;i++)
{
double o=p.caclOutput(input[i][0], input[i][1], w1, w2, b);
int out=p.activatorSign(o);
int err=p.caclError(out,real[i]);
if(err!=0) s++;
w1=p.updateWeight(input[i][0], w1, err, a);
w2=p.updateWeight(input[i][1], w2, err, a);
System.out.println("w1="+w1+",w2="+w2);
}
System.out.println("s="+s);
}
//测试
System.out.println("w1="+w1+",w2="+w2);
System.out.println("1 && 1 ="+p.activatorSign(p.caclOutput(1,1,w1,w2,b)));
System.out.println("1 && 0 ="+p.activatorSign(p.caclOutput(1,0,w1,w2,b)));
System.out.println("0 && 1 ="+p.activatorSign(p.caclOutput(0,1,w1,w2,b)));
System.out.println("0 && 0 ="+p.activatorSign(p.caclOutput(0,0,w1,w2,b)));
}
}