加速 Java 中的数学计算
Posted
技术标签:
【中文标题】加速 Java 中的数学计算【英文标题】:Speeding up Math calculations in Java 【发布时间】:2011-02-22 16:31:04 【问题描述】:我有一个用 Java 编写的神经网络,它使用如下定义的 sigmoid 传递函数:
private static double sigmoid(double x)
return 1 / (1 + Math.exp(-x));
这在使用网络进行训练和计算期间被调用很多次。有没有办法加快这个速度?不是慢,只是用的比较多,所以这里稍微优化一下,整体收益会很大。
【问题讨论】:
x 的值是否曾经重复,或者每次调用方法时它们总是不同的可能性更大? 另外,结果需要多准确? @Dave - 取决于所需的精度,但它们都是浮点数,非常独特 您是否对程序进行了剖析以知道改进它会显着提高整体性能? @Refactor 加快计算速度实际上是 NN 蛋头们的共同话题,所以我发现 ***ish 的这种反应非常幽默:) 【参考方案1】:对于神经网络,您不需要 sigmoid 函数的确切值。因此,您可以预先计算 100 个值并重用最接近您输入的值,或者甚至更好(如评论所述)从相邻值进行插值。
article 中描述了如何做到这一点(链接从answer of s-lott 被盗)。
这是sigmoid函数:
如您所见,只有 -10
编辑:很抱歉,我在这里显示了错误的图表。我已经更正了。
【讨论】:
如果您想要更精确一点,可能会超过 100 个。恕我直言,一个包含 5000 个(但可能甚至是 1000 个)值的查找表就足够了。 为了更精确,最好在最接近的两个值之间进行线性插值。 问题是对称的,所以你只需要一半的值。计算对方是微不足道的。 这是一个完全不同的函数图。 erf(x) 很难计算,exp(x) 不是。 @Ha:不错的收获。这看起来像双极 sigmoid 函数。 OP 中的 sigmoid 函数具有水平渐近线 0 和 1。【参考方案2】:如果您有很多节点 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 网络中使用这种东西。
【讨论】:
【参考方案3】:这是一个非常平滑的函数,因此查找和插值方案可能绰绰有余。
当我在-10 <= x <= 10
的范围内绘制函数时,我在极端情况下获得了五位精度。这对您的应用程序是否足够好?
【讨论】:
【参考方案4】:从数学的角度来看,我认为没有任何优化的可能性。
【讨论】:
以上是关于加速 Java 中的数学计算的主要内容,如果未能解决你的问题,请参考以下文章