14

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

private static double sigmoid(double x)
{
    return 1 / (1 + Math.exp(-x));
}

这在使用网络的训练和计算过程中被多次调用。有没有办法加快这个速度?不是它慢,只是它被使用了很多,所以这里的一个小优化将是一个很大的整体收益。

4

4 回答 4

23

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

本文描述了如何做到这一点(链接从s-lott 的答案中窃取)。

这是 sigmoid 函数:Sigmoid 函数图

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


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

于 2010-05-22T11:21:46.457 回答
6

如果您有很多节点 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 网络中使用这种东西。

于 2010-05-22T15:22:51.537 回答
1

这是一个非常平滑的函数,因此查找和插值方案可能绰绰有余。

当我在 的范围内绘制函数时-10 <= x <= 10,我在极端情况下获得了五位精度。这对您的应用程序是否足够好?

于 2010-05-22T11:38:48.243 回答
0

从数学的角度来看,我看不到任何优化它的可能性。

于 2010-05-22T11:06:39.707 回答