0

Я пытаюсь подгонять кривую с помощью scipy.optimize.curve_fit, и пока она работает очень хорошо, за исключением случая, когда значение в моем сигма-массиве равна нулю. Я понимаю, что алгоритм не может справиться с этим, поскольку в этом случае я делю на нуль. Из SciPy документации:Python: привязка данных с помощью scipy.optimize.curve_fit с sigma = 0

сигмы: Нет или M-длина последовательности, опционально Если не None, неопределенность в ydata массиве. Они используются как веса в задаче наименьших квадратов, т. Е. Минимизации np.sum (((f (xdata, * popt) - ydata)/sigma) ** 2) Если None, предполагается, что неопределенности равны 1.

Вот что мой код выглядит следующим образом:

import numpy as np 
import matplotlib.pyplot as plt 
from scipy.optimize import curve_fit 

x = [0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875, 2.125, 2.375, 2.625, 2.875, 3.125, 3.375, 3.625, 3.875, 4.125, 4.375] 
y_para = [0, 0, 0.0414, 0.2164, 0.2616, 0.4254, 0.5698, 0.5921, 0.6286, 0.6452, 0.5879, 0.6032, 0.6667, 0.6325, 0.7629, 0.7164, 0.7091, 0.7887] 
err = [0, 0, 0.0391, 0.0331, 0.0943, 0.0631, 0.1219, 0.1063, 0.0912, 0.0516, 0.0365, 0.0327, 0.0227, 0.103, 0.1344, 0.0697, 0.0114, 0.0465] 

def logistic_growth(x, A1, A2, x_0, p): 
    return A2 + (A1-A2)/(1+(x/x_0)**p) 

x_plot = np.linspace(0, 4.5, 100) 

bounds_para = ([0.,0,-np.inf,-np.inf],[0.0000000001, 1,np.inf,np.inf]) 

paras, paras_cov = curve_fit(logistic_growth, x, y_para, bounds = bounds_para, sigma = err, absolute_sigma=True) 
para_curve = logistic_growth(x_plot, *paras) 

plt.figure() 
plt.errorbar(x,y_para, err, color = 'b', fmt = 'o', label = "Data") 
plt.plot(x_plot, para_curve, color = 'b', label = "Fit")  
plt.show() 

Выполнение этого без сигма-опции в curve_fit работает отлично, но в том числе и он поднимает:

ValueError: Residuals are not finite in the initial point. 

, в результате чего из нулей в ERR-массиве , Кто-нибудь знает способ обойти это?

ответ

1

Почему бы не просто сбросить переменную? Если он имеет нулевую дисперсию, он не может внести существенный вклад в ваш анализ.

+0

Это работает довольно хорошо. Возможно, это единственный способ решить эту проблему. Но на самом деле я хотел бы также рассмотреть эти точки данных, потому что недостающая панель ошибок является результатом того, что значение для этой точки данных не изменилось для нескольких реплик. Это может случиться и для ненулевых значений, но это маловероятно. Установка очень низкого значения ошибки в этом случае также не делает этого трюка, так как полностью перепутала кривую. Я по-прежнему буду с вашим предложением, поскольку он дает хороший результат, кажется статистически правильным и решает проблему. Так что спасибо тебе! –

1

Это то, что SciPy док говорит о curve_fitсигма параметра: "Они используются в качестве весов в задаче наименьших квадратов ... Тогда, на мой взгляд, они должны быть обратным к ошибки. Вот что я предлагаю.

import numpy as np 
import matplotlib.pyplot as plt 
from scipy.optimize import curve_fit 

x = [0.125, 0.375, 0.625, 0.875, 1.125, 1.375, 1.625, 1.875, 2.125, 2.375, 2.625, 2.875, 3.125, 3.375, 3.625, 3.875, 4.125, 4.375] 
y_para = [0, 0, 0.0414, 0.2164, 0.2616, 0.4254, 0.5698, 0.5921, 0.6286, 0.6452, 0.5879, 0.6032, 0.6667, 0.6325, 0.7629, 0.7164, 0.7091, 0.7887] 
err = [0, 0, 0.0391, 0.0331, 0.0943, 0.0631, 0.1219, 0.1063, 0.0912, 0.0516, 0.0365, 0.0327, 0.0227, 0.103, 0.1344, 0.0697, 0.0114, 0.0465] 

weights = [1/max(_,0.001) for _ in err] 
print (weights) 

def logistic_growth(x, A1, A2, x_0, p): 
    return A2 + (A1-A2)/(1+(x/x_0)**p) 

x_plot = np.linspace(0, 4.5, 100) 

bounds_para = ([0.,0,-np.inf,-np.inf],[0.0000000001, 1,np.inf,np.inf]) 

paras, paras_cov = curve_fit(logistic_growth, x, y_para, bounds = bounds_para, 
    absolute_sigma=True, 
    sigma = weights) 
para_curve = logistic_growth(x_plot, *paras) 

plt.figure() 
plt.errorbar(x,y_para, err, color = 'b', fmt = 'o', label = "Data") 
plt.plot(x_plot, para_curve, color = 'b', label = "Fit")  
plt.show() 

Это приводит к следующему графику, в котором эти начальные точки данных лежат очень близко к установленной линии.

resulting plot

+0

Я думаю, что ошибки используются обратно для минимизации проблемы наименьших квадратов. Из scipy doc: «веса в задаче наименьших квадратов, т. Е. Минимизация np.sum (((f (xdata, * popt) - ydata)/sigma) ** 2)", что означает, что большее значение ошибки/сигмы приведет к более низкий вес для соответствующей точки данных. Я на самом деле попробовал ваш предвиденный подход раньше и знаю, что он дает хороший результат для этого особого случая, но я думаю, что это не правильный подход для такого рода проблем. –

+0

Я полагаю, что мой вопрос заключается в том, должны ли нулевые значения для * err * для некоторых точек данных означать, что эти точки были точно определены или что они были неточно определены? Значительно ли более высокие значения * err * подразумевают большую или меньшую точность? –

Смежные вопросы