XOR异或三层神经网络JAVA实现

1.一层的感知机(Perceptron)是无法学习非线性的二分函数的

2.多层的神经网络含有一个或多个隐藏层,其权重的调整需要借助输出层的反向传播回输出层的方式来调整,这就是BP神经网络。

3.使用S形函数来做激活函数(导数容易计算,保证输出在0~1之间)

                                     

4.误差梯度的计算:激活函数的导数与神经元的输出误差的乘积,即:

                              

经数学推导后可得,

                            

(1)初始化:

权值w及阈值b的值应在[-2.4/Fi,2.4/Fi]之间,Fi为神经元i的输入总数,如本例中为2;

(2)激活

计算隐含层神经元的实际输出:

                        

计算输出层神经元的实际输出:

                        

(3)权重训练

输出层神经元的权重:

                      

隐藏层神经元的权重:

                      

(4)反复迭代,直到误差平方和满足一定要求(因为有的误差是正、有的负,用平方来衡量误差大小。似乎绝对值更好??)

5.本例中的神经网络图

6.简单代码实现:

import java.util.Random;

public class XorANN {
	//计算输出值
	/*
	 x1、x2:输入值
	 w1、w2:对应输入值权重
	 b:控制阈值,应仔细选择
	 返回值:输出值
	 */
	public  double caclOutput(double x1,double x2,double w1,double w2,double b)
	{
		return x1*w1+x2*w2-b;
	}
	
	//使用S型函数做为激活函数sigmoid
	/*
	 * out:输出的值
	  *  返回值:结果
	 */
	public  double activatorSigmoid(double out)
	{
        return 1.0/(1.0+Math.pow(Math.E,-out));
	}
	
	//计算误差
	/*
	 *  out:输出的结果值,real:真实值
	 */
	public  double caclError(double out,double 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;
	}
	//返回一个指定区间的随机小数
	/*
	 *  根据Hankin 2008的方法设置随机权重
	 *  权重范围为:[-2.4/Fi,2.4/Fi]
	 *  nextDouble方法返回[0,1]之间的随机小数
	 *  nextDouble-0.5方法返回[-0.5,0.5]之间的随机小数 
	 *  2*t*(r.nextDouble()-0.5)则返回[-t,t]之间的随机小数
	 */
	public double getRandom(int n,Random r)
	{
		double t=2.4/(double)n;
		return 2*t*(r.nextDouble()-0.5);
	}
	//结果函数
	public int Xor(double x1,double x2,double w13,double w14,double w23,double w24,double w35,double w45,double b3,double b4,double b5)
	{
		double o3=caclOutput(x1, x2, w13, w23, b3);
		double o4=caclOutput(x1, x2, w14, w24, b4);
		double out3=activatorSigmoid(o3);
		double out4=activatorSigmoid(o4);
		double o5=caclOutput(out3, out4, w35, w45, b5);
		double out=activatorSigmoid(o5);
		if(out>0.99) return 1;
		else return 0;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final double esp=0.00001;
		XorANN xor=new XorANN();
        int[][] input= {{0,0},{0,1},{1,0},{1,1}};
        int[]   real= {1,0,0,1};
        Random r=new Random();
        double w13=xor.getRandom(2,r);
        double w14=xor.getRandom(2,r);
        double w23=xor.getRandom(2,r);
        double w24=xor.getRandom(2,r);
        double w35=xor.getRandom(2,r);
        double w45=xor.getRandom(2,r);
        double b3=0.8; //b3、b4、b5为阈值
        double b4=-0.1;
        double b5=0.3;
        double a=0.1;  //学习率
        double s=0.1;  //损失值
        int p=0; //迭代次数
        while(s>esp)
        {
        	s=0.0;
        	p++;
        	for(int i=0;i<input.length;i++)
        	{
        		double o3=xor.caclOutput(input[i][0], input[i][1], w13, w23, b3);
        		double o4=xor.caclOutput(input[i][0], input[i][1], w14, w24, b4);
        		double out3=xor.activatorSigmoid(o3);
        		double out4=xor.activatorSigmoid(o4);
        		double o5=xor.caclOutput(out3, out4, w35, w45, b5);
        		double out5=xor.activatorSigmoid(o5);
        		double err=xor.caclError(out5, real[i]);
        		
        		double d5=out5*(1-out5)*err; //输出层误差梯度
        		//更新输出层的权重
        		w35+=a*out3*d5;
        		w45+=a*out4*d5;
        		double d3=out3*(1-out3)*d5*w35; //隐藏层误差梯度
        		double d4=out4*(1-out4)*d5*w45; //隐藏层误差梯度
        		//更新隐藏层权重
        		w13+=a*input[i][0]*d3;
        		w14+=a*input[i][0]*d4;
        		w23+=a*input[i][1]*d3;
        		w24+=a*input[i][1]*d4;
        		//更新阈值
        		b3+=a*(-1)*d3;
        		b4+=a*(-1)*d4;
        		b5+=a*(-1)*d5;
        	  
        		//计算误差平方和
        		s+=err*err;
        	}
        }
        //测试
        System.out.println("总共迭代次数"+p);
        System.out.println("w13="+w13+",w14="+w14+"w23="+w23+",w24="+w24+"w35="+w35+",w45="+w45+"b3="+b3+",b4="+b4+",b5="+b5);
		System.out.println("1 xor 1 ="+xor.Xor(1, 1, w13, w14, w23, w24, w35, w45, b3, b4, b5));
		System.out.println("1 xor 0 ="+xor.Xor(1, 0, w13, w14, w23, w24, w35, w45, b3, b4, b5));
		System.out.println("0 xor 1 ="+xor.Xor(0, 1, w13, w14, w23, w24, w35, w45, b3, b4, b5));
		System.out.println("0 xor 0 ="+xor.Xor(0, 0, w13, w14, w23, w24, w35, w45, b3, b4, b5));
	}

}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值