Curve fitting runs smoothly when we provide a good starting point. We can get one
- linear regression on
sp.norm.ppf(x_data)
andnp.log(y_data)
- or by installing a free (not cropped) model first
Alternatively, if you want the computer to find a solution without "help"
, excel.
import numpy as np
import scipy.stats as sp
from scipy.optimize import curve_fit, basinhopping, brute
def func1(x, n1, n2):
return np.clip(np.exp(n2 + n1*(sp.norm.ppf(x))),25e4,10e6)
def func_free(x, n1, n2):
return np.exp(n2 + n1*(sp.norm.ppf(x)))
def sqerr(n12, x, y):
return ((func1(x, *n12) - y)**2).sum()
x_data = np.array((1e-04,9e-01,9.5835e-01,9.8e-01,9.9e-01,9.9e-01))
y_data = np.array((250e3,1e6,2.5e6,5e6,7.5e6,10e6))
lin = sp.linregress(sp.norm.ppf(x_data), np.log(y_data))
(n1f, n2f), infof = curve_fit(func_free, x_data, y_data, (1, 1))
(n1, n2), info = curve_fit(func1, x_data, y_data, (lin.slope, lin.intercept))
(n12, n22), info2 = curve_fit(func1, x_data, y_data, (n1f, n2f))
hop = basinhopping(sqerr, (1, 1), minimizer_kwargs=dict(args=(x_data, y_data)), stepsize=10)
brt = brute(sqerr, ((-100, 100), (-100, 100)), (x_data, y_data), 201, full_output=True)
assert np.allclose((n1, n2), (n12, n22))
assert np.allclose((n1, n2), hop.x)
assert np.allclose((n1, n2), brt[0])
n1excel, n2excel = 1.7925, 11.6771
print('solution', n1, n2)
print('error', ((func1(x_data, n1, n2) - y_data)**2).sum())
print('excel', ((func1(x_data, n1excel, n2excel) - y_data)**2).sum())
:
solution 2.08286042997 11.1397332743
error 3.12796761241e+12
excel 5.80088578059e+12
. , , , , - sp.norm.ppf
. , . , , - sp.norm.ppf(x_data)
- -, .
sp.norm.ppf(x_data)
.