java - 我的神经网络有更好的激活函数吗?

标签 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,因此它本质上没有将任何有值(value)的信息传递给第二个隐藏节点。此外,由于图像主要是白色,因此大多数输入都是 -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 函数合适?很抱歉这篇冗长的文章,并提前感谢您的任何见解。

最佳答案

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

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

关于java - 我的神经网络有更好的激活函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50110050/

相关文章:

java - Java 中的终结队列

python - 使用 Keras 进行数据增强

machine-learning - 神经网络性能优化

java缓冲图像导致空白图像

java - 如何在 Java 中检查字符串是否为日期时间格式

java - 在Java中使用Stax时出现空xml节点的问题

java - 使用迭代器填充集合

python - 使用 PyNN 发送尖峰时出错 - SpiNNaker

java - BufferedImage 的 getSubimage() 到底做了什么?

Java - 为大图像添加填充