BP神经网络的训练集需要大样本吗?一般样本个数为多少?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BP神经网络的训练集需要大样本吗?一般样本个数为多少?相关的知识,希望对你有一定的参考价值。

BP神经网络的训练集需要大样本吗?一般样本个数为多少?
那如果我的训练集样本为69个,算是属于大样本数据集吗?对于建立BP神经网络够用吗?

BP神经网络的训练集需要大样本吗?一般样本个数为多少?
BP神经网络样本数有什么影响
学习神经网络这段时间,有一个疑问,BP神经网络中训练的次数指的网络的迭代次数,如果有a个样本,每个样本训练次数n,则网络一共迭代an次,在n>>a 情况下 , 网络在不停的调整权值,减小误差,跟样本数似乎关系不大。而且,a大了的话训练时间必然会变长。
换一种说法,将你的数据集看成一个固定值, 那么样本集与测试集 也可以按照某种规格确定下来如7:3 所以如何看待 样本集的多少与训练结果呢? 或者说怎么使你的网络更加稳定,更加符合你的所需 。

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

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

作者其实是实现了一个BP神经网络 ,不多说,看最后的例子

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


图片描述

我们可以运用逻辑回归算法来解决上面的分类问题,但是逻辑回归得到一个线性的直线做为分界线,可以看到上面的红线无论怎么摆放,总是有一个样本被错误地划分到不同类型中,所以对于上面的数据,仅仅一条直线不能很正确地划分他们的分类,如果我们运用神经网络算法,可以得到下图的分类效果,相当于多条直线求并集来划分空间,这样准确性更高。

图片描述

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



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

这时如果我们去掉 2个样本,则样本输入变成如下

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




则(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);


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
下面是这个测试程序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));

参考技术A 这要看做什么用了

只要训练样本的规律性很好的话那自然越多越好,如果不能满足一致规律的话多了反而有害,就比如拿着文革时候的数据最好解决文革时的问题,但不能用来解决2010年世博会问题一样。

还有就像楼上说的需要保留一些样本作为测试用,BP网络的话如果是分类问题可以保留10%左右吧,如果是预测问题的话5%应该就足够了,因为BP的预测能力的确有点弱,只适合预测离训练样本比较近的数据,这也是我自己的理解,呵呵。
参考技术B 这个没有明确要求,样本也不是越多越好。

通常情况下,你的样本可以一部分用来做验证。

加速你有100个样本,90%用来做训练,10%用来做验证等,当然,有时候还得留下10%做测试用。

我个人的经验是,样本数尽量在10以上吧。
参考技术C 69个…… 的确够少。 不知道你每个样本的特征数是多少? 如果就几个特征值的话用很小的神经网络可以试试, 但我觉得你可以尝试下其余的机器学习算法。 神经网络只有当数据量大的时候优势才会显现,

keras神经网络开发知识笔记

     mnist数据集获取60000个训练样本和10000个测试样本,样本为0-9十个数字,用全连接神经网络进行训练,并测试结果。

      例程采用60000个数据样本进行训练,对于一般的电脑来说,这样训练会比较费时间,学习测试较慢

     所以,可以加入以下几行代码:

# mnist has 60000 datas,down to 6000 to accelerate
x_train=x_train[:6000]

y_train=y_train[:6000]

将原始60000个样本只取前6000个样本进行训练

例程的核心代码为(部分数值有修改):

model = Sequential()
model.add(Dense(512, activation=‘relu‘, input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(64, activation=‘relu‘))
model.add(Dropout(0.2))

model.add(Dense(num_classes, activation=‘softmax‘))

  依次理解笔记:

   

model.add(Dense(512, activation=‘relu‘, input_shape=(784,)))

  

     为model添加Dense层,即全链接层,该层有784维输入,512为输出

   

model.add(Dropout(0.2))

  

    添加Dropout层,训练时概率性丢弃

model.add(Dense(64, activation=‘relu‘))

  

    再次添加Dense层,64维输出(输入为前一层,512维)

model.add(Dense(num_classes, activation=‘softmax‘))

  

  再次添加Dense层,10维输出(num_classes=10,即0-9十个数字)

  所以我们大致能够知道,神经网络是输入784维,第一层512维,第二层64维,输出10维。

   在例程末尾,可以添加两句

model.summary()

print (model.get_weights())

    

以上是关于BP神经网络的训练集需要大样本吗?一般样本个数为多少?的主要内容,如果未能解决你的问题,请参考以下文章

bp神经网络只有一类样本怎么分类

用MATLAB做bp神经网络的预测,训练的挺好。但是预测误差很大,是啥原因,怎么解决啊

有人知道bp神经网络Matlab R2012a 的newff用法么

用Matlab算BP神经网络的具体算法?

我应该删除与某些训练样本相同的测试样本吗?

keras神经网络开发知识笔记