Scipy.optimize.curvefit() - массив не должен содержать infs или NaNs

Я пытаюсь сопоставить некоторые данные с кривой в Python, используя scipy.optimize.curve_fit. Я столкнулся с ошибкой ValueError: array must not contain infs or NaNs.

Я не считаю, что мои данные x или y содержат inf или NaNs:

>>> x_array = np.asarray_chkfinite(x_array)
>>> y_array = np.asarray_chkfinite(y_array)
>>>

Чтобы дать некоторое представление о том, как выглядят мои x_array и y_array на обоих концах (x_array - counts и y_array - квантиль):

>>> type(x_array)
<type 'numpy.ndarray'>
>>> type(y_array)
<type 'numpy.ndarray'>
>>> x_array[:5]
array([0, 0, 0, 0, 0])
>>> x_array[-5:]
array([2919, 2965, 3154, 3218, 3461])
>>> y_array[:5]
array([ 0.9999582,  0.9999163,  0.9998745,  0.9998326,  0.9997908])
>>> y_array[-5:]
array([  1.67399000e-04,   1.25549300e-04,   8.36995200e-05,
     4.18497600e-05,  -2.22044600e-16])

И моя функция:

>>> def func(x,alpha,beta,b):
...    return ((x/1)**(-alpha) * ((x+1*b)/(1+1*b))**(alpha-beta))
...

Что я выполняю с помощью:

>>> popt, pcov = curve_fit(func, x_array, y_array)

приводит к трассировке стека ошибок:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 426, in curve_fit
res = leastsq(func, p0, args=args, full_output=1, **kw)
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 338, in leastsq
cov_x = inv(dot(transpose(R),R))
File "/usr/lib/python2.7/dist-packages/scipy/linalg/basic.py", line 285, in inv
a1 = asarray_chkfinite(a)
File "/usr/lib/python2.7/dist-packages/numpy/lib/function_base.py", line 590, in asarray_chkfinite
"array must not contain infs or NaNs")
ValueError: array must not contain infs or NaNs

Я предполагаю, что ошибка может быть не относительно моих массивов, а скорее массива, созданного scipy на промежуточном этапе? У меня было немного прорываться через соответствующий источник scipy файлы, но вещи становятся волосатыми, довольно быстро отлаживая проблему таким образом. Есть ли что-то очевидное, что я здесь делаю неправильно? Я видел случайно упомянутый в других вопросах, что иногда некоторые предположения об исходном параметре (из которых у меня в настоящее время не имеют явного) могут привести к таким ошибкам, но даже если это так, было бы хорошо знать a) почему это и b) как его избежать.

Ответ 1

Почему он терпит неудачу

Не ваши входные массивы влекут за собой nans или infs, но оценка вашей целевой функции в некоторых точках X и для некоторых значений параметров приводит к nans или infs: другими словами, массив со значениями func(x,alpha,beta,b) для некоторых x, alpha, beta и b дает nans или infs над процедурой оптимизации.

Scipy.optimize функция подгонки кривой использует алгоритм Левенберга-Марквардта. Он также называется затухающей наименьшей квадратичной оптимизацией. Это итеративная процедура, и на каждой итерации вычисляется новая оценка оптимальных параметров функции. Кроме того, в какой-то момент оптимизации алгоритм исследует некоторую область пространства параметров, где ваша функция не определена.

Как исправить

1/Исходная оценка

Исходная оценка параметров является решающей для сходимости. Если первоначальная догадка далека от оптимального решения, вы с большей вероятностью исследуете некоторые области, где целевая функция undefined. Таким образом, если вы можете лучше понять, какие ваши оптимальные параметры и подать свой алгоритм с этим первоначальным предположением, можно избежать ошибки при продолжении.

2/Модель

Кроме того, вы можете изменить свою модель, чтобы она не возвращала nans. Для тех значений параметров params, где исходная функция func не определена, вы хотите, чтобы целевая функция принимала огромные значения, или, другими словами, что func(params) далека от значений Y, которые нужно установить.

Кроме того, в тех точках, где ваша целевая функция не определена, вы можете вернуть большой поплавок, например AVG(Y)*10e5 с AVG в среднем (чтобы вы были намного больше среднего значения Y, которое должно быть установлено).

Ссылка

Вы могли бы посмотреть этот пост: Подгонка данных к уравнению в python vs gnuplot

Ответ 2

Ваша функция имеет отрицательную мощность (x ^ -альфа), это то же самое, что (1/x) ^ (альфа). Если x всегда 0, ваша функция вернет inf, и ваша операция с кривой будет ломаться, я удивлен, что предупреждение/ошибка не выбрасывается ранее, информируя вас о делении на 0.

Кстати, почему вы умножаете и делите на 1?

Ответ 3

Я смог воспроизвести эту ошибку в python2.7 следующим образом:

from sklearn.decomposition import FastICA
X = load_data.load("stuff")    #this sets X to a 2d numpy array containing 
                               #large positive and negative numbers.
ica = FastICA(whiten=False)

print(np.isnan(X).any())   #this prints False
print(np.isinf(X).any())   #this prints False

ica.fit(X)                 #this produces the error:

Что всегда вызывает ошибку:

/usr/lib64/python2.7/site-packages/sklearn/decomposition/fastica_.py:58: RuntimeWarning: invalid value encountered in sqrt
  return np.dot(np.dot(u * (1. / np.sqrt(s)), u.T), W)
Traceback (most recent call last):
  File "main.py", line 43, in <module>
    ica()
  File "main.py", line 18, in ica
    ica.fit(X)
  File "/usr/lib64/python2.7/site-packages/sklearn/decomposition/fastica_.py", line 523, in fit
    self._fit(X, compute_sources=False)
  File "/usr/lib64/python2.7/site-packages/sklearn/decomposition/fastica_.py", line 479, in _fit
    compute_sources=compute_sources, return_n_iter=True)
  File "/usr/lib64/python2.7/site-packages/sklearn/decomposition/fastica_.py", line 335, in fastica
    W, n_iter = _ica_par(X1, **kwargs)
  File "/usr/lib64/python2.7/site-packages/sklearn/decomposition/fastica_.py", line 108, in _ica_par
    - g_wtx[:, np.newaxis] * W)
  File "/usr/lib64/python2.7/site-packages/sklearn/decomposition/fastica_.py", line 55, in _sym_decorrelation
    s, u = linalg.eigh(np.dot(W, W.T))
  File "/usr/lib64/python2.7/site-packages/scipy/linalg/decomp.py", line 297, in eigh
    a1 = asarray_chkfinite(a)
  File "/usr/lib64/python2.7/site-packages/numpy/lib/function_base.py", line 613, in asarray_chkfinite
    "array must not contain infs or NaNs")
ValueError: array must not contain infs or NaNs

Решение:

from sklearn.decomposition import FastICA
X = load_data.load("stuff")    #this sets X to a 2d numpy array containing 
                               #large positive and negative numbers.
ica = FastICA(whiten=False)

#this is a column wise normalization function which flattens the
#two dimensional array from very large and very small numbers to 
#reasonably sized numbers between roughly -1 and 1
X = (X - np.mean(X, axis=0)) / np.std(X, axis=0)

print(np.isnan(X).any())   #this prints False
print(np.isinf(X).any())   #this prints False

ica.fit(X)                 #this works correctly.

Почему этот шаг нормализации исправляет ошибку?

Я нашел момент эврики здесь: PLSRegression sklearn: " ValueError: массив не должен содержать infs или NaNs,

То, что я думаю, происходит, это то, что numpy питается гигантскими числами и очень маленькими числами, а внутри него крошечный мозг создает NaN и Inf. Так что это ошибка в sklearn. Работа вокруг заключается в том, чтобы сгладить ваши входные данные в алгоритм, чтобы не было очень больших или очень маленьких чисел.

Плохой склеарн! НЕТ печенья!