我的神经网络有更好的激活功能吗?

时间:2018-05-01 00:47:25

标签: java neural-network bufferedimage activation-function sigmoid

我正在编写一个识别手写字母的程序。我有500px * 500px图像,我导入为BufferedImages,我将每个像素的getRBG()值作为神经网络的输入,因此有250,000个输入。 getRGB()的值范围从-16777216(表示写入)到-1(表示白色背景)。从输入到第一个隐藏节点的权重从0到1随机化。我一直使用sigmoid函数1/(1+e^(-x))作为我的激活函数来获取0到1之间的所有值。但我的问题是因为有这么多的输入,当我用权重取它们的点积时,我得到一个具有巨大幅度的数字(例如,1.3E8-1.3E8)。然后,当我将该数字放入sigmoid函数时,结果总是全1或全0,因此它实际上没有将有价值的信息传递给第二个隐藏节点。此外,由于图像主要是白色,因此大多数输入为-1。

我调整了代码,以便在点积之后打印值,然后在通过sigmoid函数后打印它。

After dot product with weights, before sigmoid function: 
-1.3376484582733577E8   
-1.3382651127917042E8   
-1.3438475698429278E8   
-1.3356711106666781E8   
-1.3470225249402404E8   
-1.3372922925798771E8   
-1.3211961536262843E8   
-1.3512040351863045E8   

After sigmoid function: 
0.0 
0.0 
0.0 
0.0 
0.0 
0.0 
0.0 
0.0 

要编辑getRGB()值,我使用函数newRGBValue = (getRGB() + 2) * (-1)因此所有值的范围都是-1到16777214.但是,当我将所有这些值传递给sigmoid函数时,它只返回1带有这些值的新点积是巨大的正数(如下面的输出所示)。

After dot product, before sigmoid function: 
1.3198725189415371E8    
1.3345978405544662E8    
1.3375036029244222E8    
1.3278472449389385E8    
1.328751157809899E8 
1.3309195657860701E8    
1.34090008925348E8  
1.3300517803640646E8

After: 
1.0 
1.0 
1.0 
1.0 
1.0 
1.0 
1.0 
1.0

我应该为这个程序使用更好的激活功能吗?或者有没有办法可以操作输入,以便sigmoid功能适合?对于这篇冗长的帖子感到抱歉,并提前感谢任何见解。

1 个答案:

答案 0 :(得分:1)

标准化您的输入。也就是说,对于每个图像,计算像素值的平均值mu和方差sigma,并将旧像素值v替换为标准化值(v - mu) / sigma。这消除了您对像素值产生的巨大负值。

还要考虑使用均值为0和方差为1的正态分布初始随机权重,这样点积的期望值为0.然后,最好切换到tanh激活函数,该函数以0为中心,因此可以加快学习速度(如果您的点数产品接近0)。