我试图获得一些物理上非常适合某些实验数据。我知道,y值不仅会随x单调增加,而且dy / dx也会单调增加。我已经尝试了许多拟合函数,包括多项式拟合和单变量样条,但这些都没有让我产生我正在寻找的拟合。
所以,我正在寻找一个曲线拟合函数(scipy?),这将允许我定义最终曲线的已知约束。下面是我的数据示例,其中一条拟合线不显示单调递增的导数。
import numpy as np
import matplotlib.pyplot as plt
data = np.array([[ 6.30991828, -10.22329935],
[ 6.30991828, -10.2127338 ],
[ 6.47697236, -10.01359361],
[ 6.47697236, -9.89353722],
[ 6.47697236, -9.81708052],
[ 6.55108034, -9.42113403],
[ 6.55108034, -9.21932801],
[ 6.58617165, -8.40428977],
[ 6.62007321, -7.6500927 ]])
interp = np.linspace(min(data[:,0]), max(data[:,0]), 20)
f = np.polyfit(data[:,0], data[:,-1], 3)
data_interp = np.polyval(f, interp)
plt.plot(data[:,0], data[:,1], 'x', interp, data_interp, '-')
编辑:我相信你可以在MATLAB中用slmengine做到这一点。
答案 0 :(得分:1)
您的数据很有趣:您有三个不连续点:位于6.30991828,6.47697236和6.55108034。那是真的吗?那是你想要捕捉的吗?
没有连续功能可以正确捕获这些不连续性。你唯一的希望是在不连续的两边分段拟合。你将有三个适合:
当然,该函数在不连续处是多值的。
如果那些对你没有意义,我会说任何三次多项式都会给你一个连续的,增加的一阶导数。
答案 1 :(得分:1)
编辑:另一次尝试。我之前发过半生不熟的回答。而且我读书也失败了。我希望这更好。
from scipy.optimize import minimize
import numpy as np
import matplotlib.pyplot as plt
data = np.array([[ 6.30991828, -10.22329935],
[ 6.30991828, -10.2127338 ],
[ 6.47697236, -10.01359361],
[ 6.47697236, -9.89353722],
[ 6.47697236, -9.81708052],
[ 6.55108034, -9.42113403],
[ 6.55108034, -9.21932801],
[ 6.58617165, -8.40428977],
[ 6.62007321, -7.6500927 ]])
x = data[:, 0]
def polynomial(p, x):
return p[0]+p[1]*x+p[2]*x**2+p[3]*x**3
def constraint_2nd_der(p):
return 2*p[2]+6*p[3]*x
def constraint_1st_der(p):
return p[1]+2*p[2]*x+3*p[3]*x**2
def objective(p):
return ((polynomial(p, x)-data[:, 1])**2).sum()
cons = (dict(type='ineq', fun=constraint_1st_der), dict(type='ineq', fun=constraint_2nd_der))
res = minimize(objective, x0=np.array([0., 0., 0., 0.]), method='SLSQP', constraints=cons)
if res.success:
pars = res.x
x = np.linspace(data[:, 0].min(), data[:, 0].max(), 100)
pol = polynomial(pars, x)
plt.plot(data[:, 0], data[:, 1], 'x', x, pol, '-')
plt.show()
else:
print 'Failed'