python - scipy curve fitting negative value -
i fit curve curve_fit
, prevent becoming negative. unfortunately, code below not work. hints? lot!
# imports scipy.optimize import curve_fit import numpy np import matplotlib.pyplot plt xdata = [0.0009824379203203417, 0.0011014182912933933, 0.0012433979929054324, 0.0014147106052612918, 0.0016240300315499524, 0.0018834904507916608, 0.002210485320720769, 0.002630660216394964, 0.0031830988618379067, 0.003929751681281367, 0.0049735919716217296, 0.0064961201261998095, 0.008841941282883075, 0.012732395447351627, 0.019894367886486918, 0.0353677651315323, 0.07957747154594767, 0.3183098861837907] ydata = [99.61973156923796, 91.79478510744039, 92.79302188621314, 84.32927272723863, 77.75060981602016, 75.62801782349504, 70.48026800610839, 72.21240551953743, 68.14019252499526, 55.23015406920851, 57.212682880377464, 50.777016257727176, 44.871140881319626, 40.544138806850846, 32.489105158795525, 25.65367127756607, 19.894206907130403, 13.057996247388862] def func(x,m,c,d): ''' fitting function put d absolute number prevent negative values d? ''' return x**m * c + abs(d) p0 = [-1, 1, 1] coeff, _ = curve_fit(func, xdata, ydata, p0) # fit curve m, c, d = coeff[0], coeff[1], coeff[2] print("d: " + str(d)) # why negative!!
your model works fine following plot shows. used code , plotted original data , data obtain fitted parameters:
as can see, data can nicely reproduced indeed obtain negative value d
(which must not bad thing depending on context of model). if want avoid it, recommend use lmfit
can constrain parameters ranges. next plot shows outcome.
as can see, reproduces data , obtain positive value d
desired.
namely:
m: -0.35199747 c: 8.48813181 d: 0.05775745
here entire code reproduces figures:
# imports scipy.optimize import curve_fit import numpy np import matplotlib.pyplot plt #additional import lmfit import minimize, parameters, parameter, report_fit xdata = [0.0009824379203203417, 0.0011014182912933933, 0.0012433979929054324, 0.0014147106052612918, 0.0016240300315499524, 0.0018834904507916608, 0.002210485320720769, 0.002630660216394964, 0.0031830988618379067, 0.003929751681281367, 0.0049735919716217296, 0.0064961201261998095, 0.008841941282883075, 0.012732395447351627, 0.019894367886486918, 0.0353677651315323, 0.07957747154594767, 0.3183098861837907] ydata = [99.61973156923796, 91.79478510744039, 92.79302188621314, 84.32927272723863, 77.75060981602016, 75.62801782349504, 70.48026800610839, 72.21240551953743, 68.14019252499526, 55.23015406920851, 57.212682880377464, 50.777016257727176, 44.871140881319626, 40.544138806850846, 32.489105158795525, 25.65367127756607, 19.894206907130403, 13.057996247388862] def func(x,m,c,d): ''' fitting function put d absolute number prevent negative values d? ''' print m,c,d return np.power(x,m)*c + d p0 = [-1, 1, 1] coeff, _ = curve_fit(func, xdata, ydata, p0) # fit curve m, c, d = coeff[0], coeff[1], coeff[2] print("d: " + str(d)) # why negative!! plt.scatter(xdata, ydata, s=30, marker = "v",label='p') plt.scatter(xdata, func(xdata, *coeff), s=30, marker = "v",color="red",label='curvefit') plt.show() #####the new approach starts here def func2(params, x, data): m = params['m'].value c = params['c'].value d = params['d'].value model = np.power(x,m)*c + d return model - data #that's want minimize # create set of parameters params = parameters() params.add('m', value= -2) #value initial condition params.add('c', value= 8.) params.add('d', value= 10.0, min=0) #min=0 prevents d becomes negative # fit, here leastsq model result = minimize(func2, params, args=(xdata, ydata)) # calculate final result final = ydata + result.residual # write error report report_fit(params) try: import pylab pylab.plot(xdata, ydata, 'k+') pylab.plot(xdata, final, 'r') pylab.show() except: pass
Comments
Post a Comment