BP神经网络样本数多少有什么影响 ?

BP神经网络样本数有什么影响

学习神经网络这段时间,有一个疑问,BP神经网络中训练的次数指的网络的迭代次数,若是有a个样本,每一个样本训练次数n,则网络一共迭代an次,在n>>a 状况下 , 网络在不停的调整权值,减少偏差,跟样本数彷佛关系不大。并且,a大了的话训练时间必然会变长。
换一种说法,将你的数据集当作一个固定值, 那么样本集与测试集 也能够按照某种规格肯定下来如7:3 因此如何看待 样本集的多少与训练结果呢? 或者说怎么使你的网络更加稳定,更加符合你的所需 。java

我尝试从以前的一个例子中看下区别 web

如何用70行Java代码实现深度神经网络算法算法

做者实际上是实现了一个BP神经网络 ,很少说,看最后的例子数组

一个运用神经网络的例子
最后咱们找个简单例子来看看神经网络神奇的效果。为了方便观察数据分布,咱们选用一个二维坐标的数据,下面共有4个数据,方块表明数据的类型为1,三角表明数据的类型为0,能够看到属于方块类型的数据有(1,2)和(2,1),属于三角类型的数据有(1,1),(2,2),如今问题是须要在平面上将4个数据分红1和0两类,并以此来预测新的数据的类型。网络

这里写图片描述
图片描述dom

咱们能够运用逻辑回归算法来解决上面的分类问题,可是逻辑回归获得一个线性的直线作为分界线,能够看到上面的红线不管怎么摆放,老是有一个样本被错误地划分到不一样类型中,因此对于上面的数据,仅仅一条直线不能很正确地划分他们的分类,若是咱们运用神经网络算法,能够获得下图的分类效果,至关于多条直线求并集来划分空间,这样准确性更高。
这里写图片描述
图片描述svg

简单粗暴,用做者的代码运行后 训练5000次 。根据训练结果来预测一条新数据的分类(3,1)学习

这里写图片描述

预测值 (3,1)的结果跟(1,2)(2,1)属于一类 属于正方形测试

这时若是咱们去掉 2个样本,则样本输入变成以下this

//设置样本数据,对应上面的4个二维坐标数据
  double[][] data = new double[][]{{1,2},{2,2}};
 //设置目标数据,对应4个坐标数据的分类
  double[][] target = new double[][]{{1,0},{0,1}};

这里写图片描述

这里写图片描述

则(3,1)结果变成了三角形,

若是你选前两个点 你会发现直接一条中间线就能够区分 这时候的你的结果跟以前4个点时有区别 so 你得增长样本 直到这些样本按照你所想要的方式分类 ,因此样本的多少 重要性体如今,样本得能反映全部的特征值(也就是输入值) ,样本多少或者特征(本例子指点的位置特征)决定的你的网络的训练结果,!!!这是 咱们反推出来的结果 。这里距离深度学习好像近了一步。

另外,这个70行代码的神经网络没有保存你训练的网络 ,因此你每次运行都是从新训练的网络。其实,在你训练事后 权值已经肯定了下来,咱们肯定网络也就是根据权值,so只要把训练后的权值保存下来,将须要分类的数据按照这种权值带入网络,便可获得输出值,也就是一旦网络肯定, 权值也就肯定,一个输入对应一个固定的输出,不会再次改变!我的看法。

最后附上做者的源码,做者的文章见开头连接
下面的实现程序BpDeep.java能够直接拿去使用,

import java.util.Random;
public class BpDeep{
    public double[][] layer;//神经网络各层节点
    public double[][] layerErr;//神经网络各节点偏差
    public double[][][] layer_weight;//各层节点权重
    public double[][][] layer_weight_delta;//各层节点权重动量
    public double mobp;//动量系数
    public double rate;//学习系数

    public BpDeep(int[] layernum, double rate, double mobp){
        this.mobp = mobp;
        this.rate = rate;
        layer = new double[layernum.length][];
        layerErr = new double[layernum.length][];
        layer_weight = new double[layernum.length][][];
        layer_weight_delta = new double[layernum.length][][];
        Random random = new Random();
        for(int l=0;l<layernum.length;l++){
            layer[l]=new double[layernum[l]];
            layerErr[l]=new double[layernum[l]];
            if(l+1<layernum.length){
                layer_weight[l]=new double[layernum[l]+1][layernum[l+1]];
                layer_weight_delta[l]=new double[layernum[l]+1][layernum[l+1]];
                for(int j=0;j<layernum[l]+1;j++)
                    for(int i=0;i<layernum[l+1];i++)
                        layer_weight[l][j][i]=random.nextDouble();//随机初始化权重
            }   
        }
    }
    //逐层向前计算输出
    public double[] computeOut(double[] in){
        for(int l=1;l<layer.length;l++){
            for(int j=0;j<layer[l].length;j++){
                double z=layer_weight[l-1][layer[l-1].length][j];
                for(int i=0;i<layer[l-1].length;i++){
                    layer[l-1][i]=l==1?in[i]:layer[l-1][i];
                    z+=layer_weight[l-1][i][j]*layer[l-1][i];
                }
                layer[l][j]=1/(1+Math.exp(-z));
            }
        }
        return layer[layer.length-1];
    }
    //逐层反向计算偏差并修改权重
    public void updateWeight(double[] tar){
        int l=layer.length-1;
        for(int j=0;j<layerErr[l].length;j++)
            layerErr[l][j]=layer[l][j]*(1-layer[l][j])*(tar[j]-layer[l][j]);

        while(l-->0){
            for(int j=0;j<layerErr[l].length;j++){
                double z = 0.0;
                for(int i=0;i<layerErr[l+1].length;i++){
                    z=z+l>0?layerErr[l+1][i]*layer_weight[l][j][i]:0;
                    layer_weight_delta[l][j][i]= mobp*layer_weight_delta[l][j][i]+rate*layerErr[l+1][i]*layer[l][j];//隐含层动量调整
                    layer_weight[l][j][i]+=layer_weight_delta[l][j][i];//隐含层权重调整
                    if(j==layerErr[l].length-1){
                        layer_weight_delta[l][j+1][i]= mobp*layer_weight_delta[l][j+1][i]+rate*layerErr[l+1][i];//截距动量调整
                        layer_weight[l][j+1][i]+=layer_weight_delta[l][j+1][i];//截距权重调整
                    }
                }
                layerErr[l][j]=z*layer[l][j]*(1-layer[l][j]);//记录偏差
            }
        }
    }

    public void train(double[] in, double[] tar){
        double[] out = computeOut(in);
        updateWeight(tar);
    }
}

下面是这个测试程序BpDeepTest.java的源码:

import java.util.Arrays;
public class BpDeepTest{
    public static void main(String[] args){
        //初始化神经网络的基本配置
        //第一个参数是一个整型数组,表示神经网络的层数和每层节点数,好比{3,10,10,10,10,2}表示输入层是3个节点,输出层是2个节点,中间有4层隐含层,每层10个节点
        //第二个参数是学习步长,第三个参数是动量系数
        BpDeep bp = new BpDeep(new int[]{2,10,2}, 0.15, 0.8);

        //设置样本数据,对应上面的4个二维坐标数据
        double[][] data = new double[][]{{1,2},{2,2},{1,1},{2,1}};
        //设置目标数据,对应4个坐标数据的分类
        double[][] target = new double[][]{{1,0},{0,1},{0,1},{1,0}};

        //迭代训练5000次
        for(int n=0;n<5000;n++)
            for(int i=0;i<data.length;i++)
                bp.train(data[i], target[i]);

        //根据训练结果来检验样本数据
        for(int j=0;j<data.length;j++){
            double[] result = bp.computeOut(data[j]);
            System.out.println(Arrays.toString(data[j])+":"+Arrays.toString(result));
        }

        //根据训练结果来预测一条新数据的分类
        double[] x = new double[]{3,1};
        double[] result = bp.computeOut(x);
        System.out.println(Arrays.toString(x)+":"+Arrays.toString(result));
    }
}

天天都有收获!