27

numpyを使用して、関数の次の定義があります。

def powellBadlyScaled(X):
    f1 = 10**4 * X[0] * X[1] - 1
    f2 = numpy.exp(-numpy.float(X[0])) + numpy.exp(-numpy.float(X[1])) - 1.0001
    return f1 + f2

この関数は、最適化ルーチンで何度も評価されます。それはしばしば例外を引き起こします:

RuntimeWarning: overflow encountered in exp

フロートに割り当てられたスペースにオペランドを格納できないことを理解しています。しかし、どうすれば問題を克服できますか?

4

6 に答える 6

23

bigfloatパッケージを使用できます。任意精度の浮動小数点演算をサポートします。

http://packages.python.org/bigfloat/

import bigfloat
bigfloat.exp(5000,bigfloat.precision(100))
# -> BigFloat.exact('2.9676283840236670689662968052896e+2171', precision=100)

関数最適化フレームワークを使用していますか?それらは通常、値の境界を実装します(ペナルティ条件を使用)。それを試してみてください。関連する値は本当に極端ですか?最適化では、log(f)を最小化することは珍しくありません。(おおよその対数尤度など)。log(exp(f))== fではなく、そのexp値で最適化してもよろしいですか。?

この質問に対する私の答えを見てください:極値のロジットおよび逆ロジット関数

ところで、powellBadlyScaled(x、y)を最小化するだけの場合、最小値はx->+infおよびy->+infであるため、数値は必要ありません。

于 2012-03-04T22:35:36.023 に答える
4

numpy.seterrこの状況でnumpyがどのように動作するかを制御するために使用できます:http: //docs.scipy.org/doc/numpy/reference/generated/numpy.seterr.html

警告モジュールを使用して、警告の表示方法と表示方法を制御することもできます: http: //docs.python.org/library/warnings.html

于 2014-07-15T23:43:33.457 に答える
3

scipyを試してみてください-

scipy.special.expit(x)

于 2018-05-15T12:38:10.777 に答える
1

警告が表示される領域を確認し(X [0]、X [1]の特定の値を下回る可能性があります)、結果を非常に大きな数値に置き換えることで、アルゴリズムを改善できる可能性があります。関数がどのように動作するかを確認する必要があります。たとえば、exp(-x)+ exp(-y)+ x*yを確認する必要があります。

于 2014-06-18T13:56:03.697 に答える
1

特定のニーズによっては、入力引数をにトリミングすると便利な場合がありますexp()。オーバーフローした場合に実際にinfアウトしたい場合、または途方もなく膨大な数を取得したい場合は、他の回答がより適切です。

def powellBadlyScaled(X):
    f1 = 10**4 * X[0] * X[1] - 1
    f2 = numpy.exp(-numpy.float(X[0])) + numpy.exp(-numpy.float(X[1])) - 1.0001
    return f1 + f2


def powellBadlyScaled2(X):
    f1 = 10**4 * X[0] * X[1] - 1
    arg1 = -numpy.float(X[0])
    arg2 = -numpy.float(X[1])
    too_big = log(sys.float_info.max / 1000.0)  # The 1000.0 puts a margin in to avoid overflow later
    too_small = log(sys.float_info.min * 1000.0)
    arg1 = max([min([arg1, too_big]), too_small])
    arg2 = max([min([arg2, too_big]), too_small])
    # print('    too_small = {}, too_big = {}'.format(too_small, too_big))  # Uncomment if you're curious
    f2 = numpy.exp(arg1) + numpy.exp(arg2) - 1.0001
    return f1 + f2

print('\nTest against overflow: ------------')
x = [-1e5, 0]
print('powellBadlyScaled({}) = {}'.format(x, powellBadlyScaled(x)))
print('powellBadlyScaled2({}) = {}'.format(x, powellBadlyScaled2(x)))

print('\nTest against underflow: ------------')
x = [0, 1e20]
print('powellBadlyScaled({}) = {}'.format(x, powellBadlyScaled(x)))
print('powellBadlyScaled2({}) = {}'.format(x, powellBadlyScaled2(x)))

結果:

Test against overflow: ------------
*** overflow encountered in exp 
powellBadlyScaled([-100000.0, 0]) = inf
powellBadlyScaled2([-100000.0, 0]) = 1.79769313486e+305

Test against underflow: ------------
*** underflow encountered in exp    
powellBadlyScaled([0, 1e+20]) = -1.0001
powellBadlyScaled2([0, 1e+20]) = -1.0001

powellBadlyScaled2元のバージョンではオーバーフロー/アンダーフローは発生しませんでしたが、テストの1つではなくpowellBadlyScaled、変更されたバージョンでオーバーフロー/アンダーフローが発生したことに注意してください。実数であり、そうではないので、これは問題ない、または好まれるアプリケーションがたくさんあると思います。1.79769313486e+305inf1.79769313486e+305inf1.79769313486e+305inf

于 2018-01-12T05:24:40.333 に答える
0

私も同じ問題を抱えていました。精度をある程度無視できる場合は、np.round(my_float_array, decimals=<a smaller number>)このランタイム警告を克服するために使用してください。

于 2019-11-01T12:40:40.247 に答える