提问人:Simon 提问时间:5/22/2010 最后编辑:ZaidSimon 更新时间:1/19/2018 访问量:13827
在 Java 中加速数学计算
Speeding up Math calculations in Java
问:
我有一个用 Java 编写的神经网络,它使用定义如下的 sigmoid 传递函数:
private static double sigmoid(double x)
{
return 1 / (1 + Math.exp(-x));
}
这在使用网络的训练和计算过程中被多次调用。有什么方法可以加快速度吗?这并不是说它很慢,只是它被大量使用,所以这里的小优化将是一个很大的整体收益。
答:
1赞
Femaref
5/22/2010
#1
从数学的角度来看,我认为没有任何优化它的可能性。
24赞
tangens
5/22/2010
#2
对于神经网络,您不需要 sigmoid 函数的确切值。因此,您可以预先计算 100 个值并重用最接近输入的值,或者更好的是(如注释所述)从相邻值进行插值。
本文介绍了如何做到这一点(链接是从 s-lott 的答案中窃取的)。
如您所见,只有 -10 < x < 10 的值才有趣。而且,正如另一条评论所说,该函数是对称的。您只需要存储一半的值。
编辑:很抱歉,我在这里显示了错误的图表。我已经纠正了它。
评论
1赞
nico
5/22/2010
如果您想要更高的精度,也许超过 100 个。恕我直言,一个包含 5000 个(甚至可能是 1000 个)值的查找表绝对足够。
2赞
Jouni K. Seppänen
5/22/2010
为了获得更高的精度,最好在最接近的两个值之间进行线性插值。
2赞
Peter Lawrey
5/22/2010
问题是对称的,所以你只需要一半的值。计算另一边是微不足道的。
1赞
Ha.
5/22/2010
这是一个完全不同功能的图。erf(x) 很难计算,exp(x) 则不然。
0赞
Zaid
5/22/2010
@Ha : 不错的收获。这看起来像双极 S 形函数。OP 中的 sigmoid 函数具有水平渐近线 0 和 1。
1赞
duffymo
5/22/2010
#3
这是一个非常流畅的函数,因此查找和插值方案可能绰绰有余。
当我在 的范围内绘制函数时,我在极端情况下得到 5 位精度。这对您的应用来说足够好吗?-10 <= x <= 10
6赞
JustJeff
5/22/2010
#4
如果你有很多节点的 x 值在 -10..+10 框之外,你可以省略计算这些值,例如,像这样。
if( x < -10 )
y = 0;
else if( x > 10 )
y = 1;
else
y = 1 / (1 + Math.exp(-x));
return y;
当然,这会产生每次计算的条件检查开销,因此只有在您有很多饱和节点时才值得。
另一件值得一提的事情是,如果你使用的是反向传播,并且你必须处理函数的斜率,最好是分段计算,而不是“按书面”计算。
我现在不记得斜率了,但这就是我所说的,以双极 S 形体为例。而不是以这种方式计算
y = (1 - exp(-x)) / (1 + exp(-x));
它命中了 exp() 两次,您可以将昂贵的计算缓存在临时变量中,如下所示
temp = exp(-x);
y = (1 - temp) / (1 + temp);
在BP网中有很多地方可以使用这种东西。
评论