激活函数需要多精确以及它的输入有多大?

How Precise Does an Activation Function Need to Be and How Large Will Its Inputs Be?

我正在 Java 中编写一个基本的神经网络,并且正在编写激活函数(目前我刚刚编写了 sigmoid 函数)。我正在尝试使用 doubles(相对于 BigDecimal),希望训练实际上会花费合理的时间。但是,我注意到该函数不适用于较大的输入。目前我的功能是:

public static double sigmoid(double t){

    return (1 / (1 + Math.pow(Math.E, -t)));

}

这个函数 returns 非常精确的值一直到 t = -100 时,但是当 t >= 37 函数 returns 1.0 时。 在典型的神经网络中,当输入被归一化时,这样可以吗?神经元的输入总和会超过 ~37 吗?如果馈入激活函数的输入总和的大小从 NN 到 NN 不同,影响它的因素有哪些? 另外,有什么方法可以使这个函数更精确吗?是否有更精确 and/or 更快的替代方案?

令人惊讶的答案是 double 实际上比您需要的更精确。 This blog article by Pete Warden 声称即使是 8 位也足够精确。这不仅仅是一个学术想法:NVidia 的新 Pascal 芯片强调其单精度性能高于一切,因为这对深度学习训练很重要。

您应该规范化您的输入神经元值。如果仍然出现极值,将它们设置为-1或+1就可以了。事实上,this answer 显示明确地这样做。 (关于这个问题的其他答案也很有趣——建议只预先计算 100 个左右的值,根本不使用 Math.exp()Math.pow()!)

是的,在规范化网络中 double 可以使用。但这取决于你的输入,如果你的输入层更大,你的输入总和当然会更大。

我用C++遇到过同样的问题,t变大后,compiler/rte甚至不考虑E^-t和returns plain 1,因为它只计算1 /1 部分。我尝试将已经归一化的输入除以 1000-1000000,有时它会起作用,但有时它不起作用,因为我在第一个时期使用随机输入并且我的输入层是矩阵 784x784。不过,如果您的输入层很小,并且您的输入是标准化的,这将对您有所帮助