我在神经网络的最后一层使用Softmax激活函数。但是我对这个函数的安全实现有问题。
一个简单的实现是这样的:
Vector y = mlp(x); // output of the neural network without softmax activation function
for(int f = 0; f < y.rows(); f++)
y(f) = exp(y(f));
y /= y.sum();
这对于> 100个隐藏节点不能很好地工作,因为在许多情况下y将为NaN
(如果y(f) > 709,则exp(y(f))将返回inf)。我想出了这个版本:
Vector y = mlp(x); // output of the neural network without softmax activation function
for(int f = 0; f < y.rows(); f++)
y(f) = safeExp(y(f), y.rows());
y /= y.sum();
其中safeExp
定义为
double safeExp(double x, int div)
{
static const double maxX = std::log(std::numeric_limits<double>::max());
const double max = maxX / (double) div;
if(x > max)
x = max;
return std::exp(x);
}
此函数限制exp的输入。在大多数情况下,这是有效的,但不是在所有情况下,我没有真正设法找出它在哪些情况下不起作用。当我在前一层中有800个隐藏的神经元时,它根本不起作用。
然而,即使这起作用了,我还是以某种方式“扭曲”了ANN的结果。你还能想出其他方法来计算正确的解吗?有没有什么C++库或技巧可以用来计算这个ANN的确切输出?
edit:由Itamar Katz提供的解决方案是:
Vector y = mlp(x); // output of the neural network without softmax activation function
double ymax = maximal component of y
for(int f = 0; f < y.rows(); f++)
y(f) = exp(y(f) - ymax);
y /= y.sum();
它在数学上确实是一样的。然而,在实践中,由于浮点精度的原因,一些较小的值会变为0。我想知道为什么从来没有人在教科书中写下这些实现细节。
https://stackoverflow.com/questions/9906136
复制相似问题