Scipy curve_fit молча терпит неудачу только для очень определенных значений x - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть кусок кода большего размера, который соответствует функциям данных в своей основе.Данные и функции, которые будут установлены, являются динамическими.Недавно я добавил дополнительную точку данных ко всей системе, и теперь curve_fit всегда возвращает первоначальное предположение (или что-то слишком близкое к нему), независимо от того, как я его выбрал.Это происходит для очень разных значений y и значений x (десять наборов первых, два набора последних).

Я знаю, что выбор начальных значений важен, но у меня никогда не было проблем с использованиемпо умолчанию раньше (мои функции, как правило, просты) и могут вернуться в состояние, в котором это просто работает, раскомментировав новый код, который добавляет дополнительную точку данных.Теперь можно подумать, что, очевидно, проблема заключается в новом коде, но между новым добавлением и фактической подачей данных в curve_fit есть довольно много шагов.Я уже проверил, что тип ввода для curve_fit такой же: np.ndarray, только на один элемент длиннее в проблемном случае.

Однако при создании MWE я заметил, что это толькоточный x-массив, который приводит к проблеме.Он полностью исчезает, когда я копирую напечатанный x-вектор основной программы в моем MWE вместо внутреннего представления.Следовательно, я могу показать только проблему с внешним файлом: local_z.npy [150kB]

MWE:

import numpy as np
from scipy.optimize import curve_fit

values = np.array([[1.37712972, 1.58475346, 1.78578759, 1.9843099,  1.73393093],
                   [-0.0155715,  -0.01534987, -0.00910744, -0.00189728, -1.73393093],
                   [1.23613934, 0.76894505, 0.18876817, 0.06376843, 1.1637315 ],
                   [0.8535248,  0.53093829, 0.13033993, 0.04403058, 0.80352895],
                   [0.51505805, 0.32039379, 0.0786534,  0.02657018, 0.48488813]])
heights = np.array([ 22.110203,  65.49054,  110.321526, 156.54034,  166.59094])
local_z = np.load('local_z.npy')
print('difference in heights', local_z - heights)

def func(z, a0, a1):
    return a0 + a1*z

for v in values:
    popt_non_working = curve_fit(func, local_z, v)[0]
    print('not working: ', popt_non_working)
    popt_working = curve_fit(func, heights, v)[0]
    print('working: ', popt_working)

Мой вывод с Python 2.7.6,numpy 1.14.1 и scipy 1.0.0:

$ python auxiliary/SUBLIME_fit_test.py  
('difference in heights', array([-2.10693358e-07, -4.49218746e-07, -4.26269537e-07,  4.23828126e-06, 2.38281251e-06]))
/home/csag5117/venv/local/lib/python2.7/site-packages/scipy/optimize/minpack.py:785: OptimizeWarning: Covariance of the parameters could not be estimated category=OptimizeWarning)
('not working: ', array([1., 1.]))
('working: ', array([1.35420488, 0.00325281]))
('not working: ', array([1., 1.]))
('working: ', array([ 0.38896878, -0.00714073]))
('not working: ', array([1., 1.]))
('working: ', array([ 1.06301278, -0.00363439]))
('not working: ', array([1., 1.]))
('working: ', array([ 0.73398503, -0.00250946]))
('not working: ', array([1., 1.]))
('working: ', array([ 0.442922  , -0.00151433]))

Как видите, версия, в которой я использую heights в качестве значений x, работает как положено (возвращает параметры подгонки), тогда как версиягде я использую сохраненный `local_z 'нет, хотя разница между двумя массивами очень мала.Я показываю только несколько значений y, чтобы показать, что это не ошибка на миллион, которую можно исправить с помощью правильных начальных значений.Это также только один пример, у меня также есть один с большим количеством точек данных (24 вместо 5) с таким же поведением.

Для полноты, добавлен блок кода (когда я отключаю это, все работает),Интересно, что пропущение последнего значения в local_z (которое добавляется блоком кода) с помощью local_z[:-1] в MWE не решает проблему.

zi_minus_dd -= 1
zf_long = np.append(out.zf, np.squeeze(data.zf[t])[z_mask_full[-1] + 1])
u_zi = np.interp(zi_minus_dd, zf_long,
    np.append(out.u, np.squeeze(data.u[t])[z_mask_full[-1] + 1]))
v_zi = np.interp(zi_minus_dd, zf_long,
    np.append(out.v, np.squeeze(data.v[t])[z_mask_full[-1] + 1]))
th_zi = np.interp(zi_minus_dd, zf_long,
    np.append(out.th, np.squeeze(data.th[t])[z_mask_full[-1] + 1]))

zh_long = np.append(out.zh, np.squeeze(data.zh[t])[z_mask_full[-1] + 1])
uw_zi = np.interp(zi_minus_dd, zf_long,
    np.append(out.uw_raw, np.squeeze(data.uw[t])[z_mask_full[-1] + 1]))
vw_zi = np.interp(zi_minus_dd, zf_long,
    np.append(out.vw_raw, np.squeeze(data.vw[t])[z_mask_full[-1] + 1]))
tke_zi = np.interp(zi_minus_dd, zf_long,
    np.append(out.tke, np.squeeze(data.TKE[t])[z_mask_full[-1] + 1]))

out.zf = np.append(out.zf, zi_minus_dd)
out.u = np.append(out.u, u_zi)
out.v = np.append(out.v, u_zi)
out.th = np.append(out.th, u_zi)

out.zh = np.append(out.zh, zi_minus_dd)
out.uw_raw = np.append(out.uw_raw, u_zi)
out.vw_raw = np.append(out.vw_raw, u_zi)
out.tke = np.append(out.tke, u_zi)

out.zfи out.zh - векторы, которые позже превращаются в local_z.Весь код довольно большой и также зависит от файлов netCDF (data в приведенном выше фрагменте).Я уже спрашивал об этом здесь , но это было для рабочего кода.

Я в значительной степени озадачен и понятия не имею, как я могу это исправить или даже продолжить отладку.Возможно ли, что есть какая-то проблема с копией против Deepcopy или что-то подобное?Хотя мне интересно, как это будет передаваться в MWE через сохраненный массив ...

1 Ответ

0 голосов
/ 18 сентября 2018

Отслеживать это было довольно весело.: -)

Это не значения, а их типы .Это проблема точности: heights, который работает, это float64, local_z, который не работает, это только float32.

У нас есть

In [70]: heights
Out[70]: array([ 22.110203,  65.49054 , 110.321526, 156.54034 , 166.59094 ])

In [71]: heights.dtype
Out[71]: dtype('float64')

In [72]: curve_fit(func, heights, v)[0]
Out[72]: array([1.35420488, 0.00325281])

и

In [73]: local_z
Out[73]: 
array([ 22.110205,  65.49054 , 110.321526, 156.54034 , 166.59094 ],
      dtype=float32)

In [74]: curve_fit(func, local_z, v)[0]
C:\Python\lib\site-packages\scipy\optimize\minpack.py:794: OptimizeWarning: Covariance of the parameters could not be estimated
  category=OptimizeWarning)
Out[74]: array([1., 1.])

Но если мы хотим, мы можем заставить local_z работать:

In [75]: curve_fit(func, local_z.astype(np.float64), v)[0]
Out[75]: array([1.35420488, 0.00325281])

или высоты не получаются:

In [76]: curve_fit(func, heights.astype(np.float32), v)[0]
C:\Python\lib\site-packages\scipy\optimize\minpack.py:794: OptimizeWarning: Covariance of the parameters could not be estimated
  category=OptimizeWarning)
Out[76]: array([1., 1.])
...