ニューラル ネットワークの最後の層で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();
NaN
y が多くの場合 (y(f) > 709 の場合、exp(y(f)) は inf を返す) になるため、これは 100 個を超える隠しノードではうまく機能しません。私はこのバージョンを思いつきました:
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の結果を何らかの形で「歪め」ました。正しい解を計算する他の方法を考えられますか? この ANN の正確な出力を計算するために使用できる C++ ライブラリまたはトリックはありますか?
編集: 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 になります。これらの実装の詳細を誰も教科書に書き留めていないのはなぜだろうか。