我的神经网络有更好的激活函数吗?
Is there a better activation function for my neural network?
我正在编写一个程序来识别手写字母。我将 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 函数时,它只是 returns 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 函数适用?抱歉啰嗦 post 并提前感谢您的任何见解。
标准化您的输入。也就是说,对于每个图像,计算像素值的均值 mu
和方差 sigma
,并将旧像素值 v
替换为归一化值 (v - mu) / sigma
。这消除了您的像素值的巨大负值。
也可以考虑使用均值为0方差为1的正态分布的初始随机权重,这样你的点积的期望值为0。那么最好换成tanh激活函数,它是居中的为 0,因此可以加快学习速度(如果您的点积接近 0)。
我正在编写一个程序来识别手写字母。我将 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 函数时,它只是 returns 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 函数适用?抱歉啰嗦 post 并提前感谢您的任何见解。
标准化您的输入。也就是说,对于每个图像,计算像素值的均值 mu
和方差 sigma
,并将旧像素值 v
替换为归一化值 (v - mu) / sigma
。这消除了您的像素值的巨大负值。
也可以考虑使用均值为0方差为1的正态分布的初始随机权重,这样你的点积的期望值为0。那么最好换成tanh激活函数,它是居中的为 0,因此可以加快学习速度(如果您的点积接近 0)。