私は、C++で滑らかな関数の数値勾配を計算しようとしています。パラメータ値はゼロから非常に大きな値(おそらく1e10から1e20まで)で変化する可能性があります。数値勾配を計算するための「標準的な」方法はありますか?
私はテストベンチとして関数f(x、y)= 10 * x^3 + y^3を使用しましたが、 xまたはyが大きすぎると、正しい勾配を得ることができないことがわかりました。ここで
はgraidientを計算するために私のコードです:
#include <iostream>
#include <cmath>
#include <cassert>
using namespace std;
double f(double x, double y)
{
// black box expensive function
return 10 * pow(x, 3) + pow(y, 3);
}
int main()
{
// double x = -5897182590.8347721;
// double y = 269857217.0017581;
double x = 1.13041e+19;
double y = -5.49756e+14;
const double epsi = 1e-4;
double f1 = f(x, y);
double f2 = f(x, y+epsi);
double f3 = f(x, y-epsi);
cout << f1 << endl;
cout << f2 << endl;
cout << f3 << endl;
cout << f1 - f2 << endl; // 0
cout << f2 - f3 << endl; // 0
return 0;
}
私は勾配を計算するために上記のコードを使用している場合は、勾配がゼロになります!
テストベンチ関数10 * x^3 + y^3は単なるデモですが、私が解決する必要がある実際の問題は実際にはブラックボックス関数です。
したがって、数値勾配を計算するための「標準的な」方法はありますか?
"_large x and y_" w.r.t.の計算をしましたか? 'x^3'と' y^3'に?ヒント: 'double'には限界があります。 –
勾配を計算するための標準的な方法は計算です。数値で実装する方法はあなたの責任です。 (10^19)^ 3 = 10^57、そうですか? – duffymo
@duffymoこれは 'double'(1e308、ISTR)の範囲内の* well * – Alnitak