我有一个用 Java 编写的神经网络,它使用如下定义的 sigmoid 传递函数:
private static double sigmoid(double x)
{
return 1 / (1 + Math.exp(-x));
}
这在使用网络的训练和计算过程中被多次调用。有没有办法加快这个速度?不是它慢,只是它被使用了很多,所以这里的一个小优化将是一个很大的整体收益。
我有一个用 Java 编写的神经网络,它使用如下定义的 sigmoid 传递函数:
private static double sigmoid(double x)
{
return 1 / (1 + Math.exp(-x));
}
这在使用网络的训练和计算过程中被多次调用。有没有办法加快这个速度?不是它慢,只是它被使用了很多,所以这里的一个小优化将是一个很大的整体收益。
对于神经网络,您不需要 sigmoid 函数的确切值。因此,您可以预先计算 100 个值并重用最接近您输入的值,或者甚至更好(如评论所述)从相邻值进行插值。
本文描述了如何做到这一点(链接从s-lott 的答案中窃取)。
如您所见,只有 -10 < x < 10 的值才有意义。而且,正如另一条评论所述,该函数是对称的。您只需要存储一半的值。
编辑:对不起,我在这里显示了错误的图表。我已经纠正了。
如果您有很多节点 x 的值在 -10..+10 框之外,您可以完全省略计算这些值,例如,像这样..
if( x < -10 )
y = 0;
else if( x > 10 )
y = 1;
else
y = 1 / (1 + Math.exp(-x));
return y;
当然,这会导致每次计算的条件检查的开销,所以只有当你有很多饱和节点时才值得。
另一件值得一提的是,如果您使用反向传播,并且您必须处理函数的斜率,最好分段计算而不是“按原样”计算。
我现在不记得斜率了,但这就是我所说的,以双极 sigmoid 为例。而不是这样计算
y = (1 - exp(-x)) / (1 + exp(-x));
两次命中 exp(),您可以将昂贵的计算缓存在临时变量中,就像这样
temp = exp(-x);
y = (1 - temp) / (1 + temp);
有很多地方可以在 BP 网络中使用这种东西。
这是一个非常平滑的函数,因此查找和插值方案可能绰绰有余。
当我在 的范围内绘制函数时-10 <= x <= 10
,我在极端情况下获得了五位精度。这对您的应用程序是否足够好?
从数学的角度来看,我看不到任何优化它的可能性。