加快Java中的数学计算

Sim*_*mon 11 java mathematical-optimization neural-network

我有一个用Java编写的神经网络,它使用如下定义的sigmoid传递函数:

private static double sigmoid(double x)
{
    return 1 / (1 + Math.exp(-x));
}
Run Code Online (Sandbox Code Playgroud)

而这就是所谓的许多培训和使用网络的计算过程中的时间.有没有办法加速这个?这并不是说它很慢,只是它被大量使用,所以这里的一个小优化将是一个很大的整体收益.

tan*_*ens 21

对于神经网络,您不需要sigmoid函数的确切值.因此,您可以预先计算100个值并重用最接近输入的值,或者甚至更好(如注释所述)从邻居值进行插值.

本文介绍了如何执行此操作(链接从s-lott答案中窃取).

这是sigmoid函数:Sigmoid函数图

如您所见,只有-10 <x <10的值才有意义.并且,正如另一条评论所述,该功能是对称的.您只需要存储一半的值.


编辑:对不起,我在这里显示错误的图表.我已经纠正过了.

  • 为了获得更高的精度,最好在最近的两个值之间进行线性插值. (2认同)
  • 问题是对称的,所以你只需要一半的值.计算另一方是微不足道的. (2认同)

Jus*_*eff 5

如果你有很多节点,其中x的值在-10 .. + 10框之外,你可以省略计算这些值,例如,像这样.

if( x < -10 )
    y = 0;
else if( x > 10 )
    y = 1;
else
    y = 1 / (1 + Math.exp(-x));
return y;
Run Code Online (Sandbox Code Playgroud)

当然,这会导致每次计算的条件检查的开销,所以如果你有很多饱和节点,这是值得的.

值得一提的另一件事是,如果你正在使用反向传播,并且你必须处理函数的斜率,最好将它计算成碎片而不是"写入".

我不记得此刻的斜率,但这就是我所说的以双极S形为例.而不是以这种方式计算

y = (1 - exp(-x)) / (1 + exp(-x));
Run Code Online (Sandbox Code Playgroud)

两次命中exp(),你可以在临时变量中缓存昂贵的计算,就像这样

temp = exp(-x);
y = (1 - temp) / (1 + temp);
Run Code Online (Sandbox Code Playgroud)

在BP网络中有很多地方可以使用这种东西.