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) 并不少见。(近似对数似然等)。您确定要优化该 exp 值而不是 log(exp(f)) == f. ?

看看我对这个问题的回答:logit and inverse logit functions forextreme values

顺便说一句,如果您所做的只是最小化 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

Maybe you can improve your algorithm by checking for which areas you get warnings (it will probably bellow certain values for X[ 0 ],X[ 1 ]), and replacing the result with a really big number. You need to see how your function behaves, I thing you should check e.g. 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原始powellBadlyScaled版本没有上溢/下溢,但修改后的版本给出了1.79769313486e+305而不是inf在其中一个测试中给出。我想有很多应用程序1.79769313486e+305实际上是这样的inf,这很好,甚至是首选,因为1.79769313486e+305它是一个实数,inf而不是一个实数。

于 2018-01-12T05:24:40.333 回答
0

我有同样的问题。如果在某种程度上可以忽略精度,请使用np.round(my_float_array, decimals=<a smaller number>)来克服此运行时警告。

于 2019-11-01T12:40:40.247 回答