我正在编写一个识别手写字母的程序。我有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功能适合?对于这篇冗长的帖子感到抱歉,并提前感谢任何见解。
答案 0 :(得分:1)
标准化您的输入。也就是说,对于每个图像,计算像素值的平均值mu
和方差sigma
,并将旧像素值v
替换为标准化值(v - mu) / sigma
。这消除了您对像素值产生的巨大负值。
还要考虑使用均值为0和方差为1的正态分布初始随机权重,这样点积的期望值为0.然后,最好切换到tanh激活函数,该函数以0为中心,因此可以加快学习速度(如果您的点数产品接近0)。