Python:分段多项式曲线拟合指数
Python: piecewise polynomial curve fit in the exponential
我想重现按以下方式分段拟合分布的研究结果。
- ln(y_data) = A(x):拟合中心部分的三阶多项式
- ln(y_data) = B(x) :拟合两个尾部的一阶多项式
到目前为止,我使用了 curve_fit 并定义了一个分段函数,并通过以下要求在边界 x0 和 x1 处施加了连续性和平滑性:
- f_1(x0) = f_2(x0) & f_2(x1) = f_3(x1)
- f'_1(x0) = f'_2(x0) & f'_2(x1) = f'_3(x1)
我的代码是:
import numpy as np
from matplotlib import pyplot as plt
from scipy import optimize
plt.figure(figsize=(9,6))
def piecewise_func(x, x0, x1, a0, a1, b0, b1, b2, b3, c0, c1):
x0 = 0.015
x1 = 0.06
b3 = ((c1-(a0+a1*x0-c0-c1*x1)/(x0-x1) + (x0+x1)/(2*(x0-x1)) * (a1-c1) -x1/(x0-x1)*(a1-c1))/(3.*x1**2))/(1.-(-1.5*(x0+x1)**2 + (x0**3-x1**3)/(x0-x1) + 3.*x1*(x0+x1))/(3.*x1**2))
b2 = (a1 - c1 - 3.*b3*(x0**2 - x1**2))/(2.*(x0-x1))
b1 = (a0+a1*x0-c0-c1*x1-b2*(x0**2-x1**2)-b3*(x0**3-x1**3))/(x0-x1)
b0 = a0 + a1*x0 - b1*x0 - b2*x0**2 - b3*x0**3
condlist = [x < x0, (x >= x0) & (x < x1), x >= x1]
funclist = [lambda x: a0 + a1*x,
lambda x: b0 + b1*x + b2*x**2 + b3*x**3,
lambda x: c0 + c1*x]
return np.piecewise(x, condlist, funclist)
p , e = optimize.curve_fit(piecewise_func, xvals, np.log(yvals))
x_plot = np.linspace(0., 0.15, len(xvals))
plt.plot(xvals, np.log(yvals), "+")
plt.plot(xvals, (piecewise_func(x_plot, *p)), 'C3-', lw=3)
plt.show()
当前 x0、x1 的值是静态的。理想情况下,这些也是自由变量。
满足边界条件:
# continuity
print 'continuity f_1(x0)=f_2(x0): ',a0 + a1*x0, '//', b0 + b1*x0 + b2*x0**2. + b3*x0**3.
print 'continuity f_2(x1)=f_3(x1): ',b0 + b1*x1 + b2*x1**2. + b3*x1**3., '//',c0 + c1*x1 ,'\n'
# smoothness for first derivative
print 'smoothness df_1(x0)=df_2(x0): ',a1, '//', b1 + 2.*b2*x0 + 3.*b3*x0**2.
print 'smoothness df_2(x1)=df_3(x1): ',b1 + 2.*b2*x1 + 3.*b3*x1**2., '//',c1
屈服
continuity f_1(x0)=f_2(x0): 4.68285214128 // 4.68285214128
continuity f_2(x1)=f_3(x1): 6.53425912688 // 6.53425912688
smoothness df_1(x0)=df_2(x0): 233.211740443 // 233.211740443
smoothness df_2(x1)=df_3(x1): -5.51084715909 // -5.51084715909
我怎样才能获得正确的配合?感谢您的帮助!
(下采样)数据由以下公式给出:
array([[ 2.72580000e-03, 2.00000000e+00],
[ 5.35160000e-03, 6.00000000e+00],
[ 8.35440000e-03, 3.10000000e+01],
[ 1.15380000e-02, 8.10000000e+01],
[ 1.48130000e-02, 1.89000000e+02],
[ 1.81220000e-02, 2.88000000e+02],
[ 2.14320000e-02, 4.31000000e+02],
[ 2.47350000e-02, 5.27000000e+02],
[ 2.80210000e-02, 5.90000000e+02],
[ 3.12730000e-02, 6.59000000e+02],
[ 3.44930000e-02, 7.56000000e+02],
[ 3.76910000e-02, 7.90000000e+02],
[ 4.08610000e-02, 8.36000000e+02],
[ 4.39970000e-02, 8.61000000e+02],
[ 4.71140000e-02, 8.45000000e+02],
[ 5.01930000e-02, 8.38000000e+02],
[ 5.32830000e-02, 8.39000000e+02],
[ 5.63310000e-02, 8.14000000e+02],
[ 5.93720000e-02, 7.61000000e+02],
[ 6.24040000e-02, 7.29000000e+02],
[ 6.54260000e-02, 7.06000000e+02],
[ 6.84390000e-02, 7.05000000e+02],
[ 7.14430000e-02, 6.77000000e+02],
[ 7.44370000e-02, 6.45000000e+02],
[ 7.74210000e-02, 6.82000000e+02],
[ 8.04130000e-02, 6.75000000e+02],
[ 8.34120000e-02, 6.77000000e+02],
[ 8.63850000e-02, 6.63000000e+02],
[ 8.93820000e-02, 6.62000000e+02],
[ 9.23710000e-02, 6.34000000e+02],
[ 9.53670000e-02, 5.87000000e+02],
[ 9.83720000e-02, 5.46000000e+02],
[ 1.01390000e-01, 5.22000000e+02],
[ 1.04390000e-01, 5.10000000e+02],
[ 1.07400000e-01, 4.97000000e+02],
[ 1.10440000e-01, 4.77000000e+02],
[ 1.13480000e-01, 4.82000000e+02],
[ 1.16540000e-01, 4.55000000e+02]])
您可以将曲线拟合问题包装到一个优化 x0 和 x1 的外部优化问题中。
尝试:
def piecewise_func(p,x):
a0,a1,c0,c1,x0,x1 = p
b3 = ((c1-(a0+a1*x0-c0-c1*x1)/(x0-x1) + (x0+x1)/(2*(x0-x1)) * (a1-c1) -x1/(x0-x1)*(a1-c1))/(3.*x1**2))/ (1.-(-1.5*(x0+x1)**2 + (x0**3-x1**3)/(x0-x1) + 3.*x1*(x0+x1))/(3.*x1**2))
b2 = (a1 - c1 - 3.*b3*(x0**2 - x1**2))/(2.*(x0-x1))
b1 = (a0+a1*x0-c0-c1*x1-b2*(x0**2-x1**2)-b3*(x0**3-x1**3))/(x0-x1)
b0 = a0 + a1*x0 - b1*x0 - b2*x0**2 - b3*x0**3
condlist = [x < x0, (x >= x0) & (x < x1), x >= x1]
funclist = [lambda x: a0 + a1*x,
lambda x: b0 + b1*x + b2*x**2 + b3*x**3,
lambda x: c0 + c1*x]
return np.piecewise(x, condlist, funclist)
def optFunc(p,extra):
x,y = extra
return piecewise_func(p,x)-y
fit,ier = optimize.leastsq(optFunc,[0.,1.,0.,1.,0.01,0.1],[x,np.log(y)])
print fit
plt.plot(x,np.log(y),'k+')
plt.plot(x,piecewise_func(fit,x))
这应该产生以下拟合:click here
我想重现按以下方式分段拟合分布的研究结果。
- ln(y_data) = A(x):拟合中心部分的三阶多项式
- ln(y_data) = B(x) :拟合两个尾部的一阶多项式
到目前为止,我使用了 curve_fit 并定义了一个分段函数,并通过以下要求在边界 x0 和 x1 处施加了连续性和平滑性:
- f_1(x0) = f_2(x0) & f_2(x1) = f_3(x1)
- f'_1(x0) = f'_2(x0) & f'_2(x1) = f'_3(x1)
我的代码是:
import numpy as np
from matplotlib import pyplot as plt
from scipy import optimize
plt.figure(figsize=(9,6))
def piecewise_func(x, x0, x1, a0, a1, b0, b1, b2, b3, c0, c1):
x0 = 0.015
x1 = 0.06
b3 = ((c1-(a0+a1*x0-c0-c1*x1)/(x0-x1) + (x0+x1)/(2*(x0-x1)) * (a1-c1) -x1/(x0-x1)*(a1-c1))/(3.*x1**2))/(1.-(-1.5*(x0+x1)**2 + (x0**3-x1**3)/(x0-x1) + 3.*x1*(x0+x1))/(3.*x1**2))
b2 = (a1 - c1 - 3.*b3*(x0**2 - x1**2))/(2.*(x0-x1))
b1 = (a0+a1*x0-c0-c1*x1-b2*(x0**2-x1**2)-b3*(x0**3-x1**3))/(x0-x1)
b0 = a0 + a1*x0 - b1*x0 - b2*x0**2 - b3*x0**3
condlist = [x < x0, (x >= x0) & (x < x1), x >= x1]
funclist = [lambda x: a0 + a1*x,
lambda x: b0 + b1*x + b2*x**2 + b3*x**3,
lambda x: c0 + c1*x]
return np.piecewise(x, condlist, funclist)
p , e = optimize.curve_fit(piecewise_func, xvals, np.log(yvals))
x_plot = np.linspace(0., 0.15, len(xvals))
plt.plot(xvals, np.log(yvals), "+")
plt.plot(xvals, (piecewise_func(x_plot, *p)), 'C3-', lw=3)
plt.show()
当前 x0、x1 的值是静态的。理想情况下,这些也是自由变量。
满足边界条件:
# continuity
print 'continuity f_1(x0)=f_2(x0): ',a0 + a1*x0, '//', b0 + b1*x0 + b2*x0**2. + b3*x0**3.
print 'continuity f_2(x1)=f_3(x1): ',b0 + b1*x1 + b2*x1**2. + b3*x1**3., '//',c0 + c1*x1 ,'\n'
# smoothness for first derivative
print 'smoothness df_1(x0)=df_2(x0): ',a1, '//', b1 + 2.*b2*x0 + 3.*b3*x0**2.
print 'smoothness df_2(x1)=df_3(x1): ',b1 + 2.*b2*x1 + 3.*b3*x1**2., '//',c1
屈服
continuity f_1(x0)=f_2(x0): 4.68285214128 // 4.68285214128
continuity f_2(x1)=f_3(x1): 6.53425912688 // 6.53425912688
smoothness df_1(x0)=df_2(x0): 233.211740443 // 233.211740443
smoothness df_2(x1)=df_3(x1): -5.51084715909 // -5.51084715909
(下采样)数据由以下公式给出:
array([[ 2.72580000e-03, 2.00000000e+00],
[ 5.35160000e-03, 6.00000000e+00],
[ 8.35440000e-03, 3.10000000e+01],
[ 1.15380000e-02, 8.10000000e+01],
[ 1.48130000e-02, 1.89000000e+02],
[ 1.81220000e-02, 2.88000000e+02],
[ 2.14320000e-02, 4.31000000e+02],
[ 2.47350000e-02, 5.27000000e+02],
[ 2.80210000e-02, 5.90000000e+02],
[ 3.12730000e-02, 6.59000000e+02],
[ 3.44930000e-02, 7.56000000e+02],
[ 3.76910000e-02, 7.90000000e+02],
[ 4.08610000e-02, 8.36000000e+02],
[ 4.39970000e-02, 8.61000000e+02],
[ 4.71140000e-02, 8.45000000e+02],
[ 5.01930000e-02, 8.38000000e+02],
[ 5.32830000e-02, 8.39000000e+02],
[ 5.63310000e-02, 8.14000000e+02],
[ 5.93720000e-02, 7.61000000e+02],
[ 6.24040000e-02, 7.29000000e+02],
[ 6.54260000e-02, 7.06000000e+02],
[ 6.84390000e-02, 7.05000000e+02],
[ 7.14430000e-02, 6.77000000e+02],
[ 7.44370000e-02, 6.45000000e+02],
[ 7.74210000e-02, 6.82000000e+02],
[ 8.04130000e-02, 6.75000000e+02],
[ 8.34120000e-02, 6.77000000e+02],
[ 8.63850000e-02, 6.63000000e+02],
[ 8.93820000e-02, 6.62000000e+02],
[ 9.23710000e-02, 6.34000000e+02],
[ 9.53670000e-02, 5.87000000e+02],
[ 9.83720000e-02, 5.46000000e+02],
[ 1.01390000e-01, 5.22000000e+02],
[ 1.04390000e-01, 5.10000000e+02],
[ 1.07400000e-01, 4.97000000e+02],
[ 1.10440000e-01, 4.77000000e+02],
[ 1.13480000e-01, 4.82000000e+02],
[ 1.16540000e-01, 4.55000000e+02]])
您可以将曲线拟合问题包装到一个优化 x0 和 x1 的外部优化问题中。
尝试:
def piecewise_func(p,x):
a0,a1,c0,c1,x0,x1 = p
b3 = ((c1-(a0+a1*x0-c0-c1*x1)/(x0-x1) + (x0+x1)/(2*(x0-x1)) * (a1-c1) -x1/(x0-x1)*(a1-c1))/(3.*x1**2))/ (1.-(-1.5*(x0+x1)**2 + (x0**3-x1**3)/(x0-x1) + 3.*x1*(x0+x1))/(3.*x1**2))
b2 = (a1 - c1 - 3.*b3*(x0**2 - x1**2))/(2.*(x0-x1))
b1 = (a0+a1*x0-c0-c1*x1-b2*(x0**2-x1**2)-b3*(x0**3-x1**3))/(x0-x1)
b0 = a0 + a1*x0 - b1*x0 - b2*x0**2 - b3*x0**3
condlist = [x < x0, (x >= x0) & (x < x1), x >= x1]
funclist = [lambda x: a0 + a1*x,
lambda x: b0 + b1*x + b2*x**2 + b3*x**3,
lambda x: c0 + c1*x]
return np.piecewise(x, condlist, funclist)
def optFunc(p,extra):
x,y = extra
return piecewise_func(p,x)-y
fit,ier = optimize.leastsq(optFunc,[0.,1.,0.,1.,0.01,0.1],[x,np.log(y)])
print fit
plt.plot(x,np.log(y),'k+')
plt.plot(x,piecewise_func(fit,x))
这应该产生以下拟合:click here