Python:曲线拟合看起来很混乱

问题描述

我正在尝试将曲线拟合到一些数据,但所得的曲线看起来像乱七八糟的混乱。我不知道这些系数是否准确。使用此示例数据集,它可以打印出类似三角形的图像,而使用我的原始数据集,则看起来更糟。主要是教程。我尝试从替代教程中删除sympy代码,但这样做无济于事。

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

x = [0.0009425070688029959,0.0009398496240601303,0.0018779342723004293,0.004694835680751241,0.0009425070688029959,0.004734848484848552,0.0018993352326685255,0.0009460737937558928]
y = [0.0028301886792453904,0.003762935089369628,0.001881467544684814,0.0009433962264150743,0.0028301886792453904,0.0019029495718363059,0.0038058991436727804,0.0018939393939393534]
"""
Plot your data
"""
plt.plot(x,y,'ro',label="Original Data")

"""
brutal force to avoid errors
"""    
x = np.array(x,dtype=float) #transform your data in a numpy array of floats 
y = np.array(y,dtype=float) #so the curve_fit can work

"""
create a function to fit with your data. a,b,c and d are the coefficients
that curve_fit will calculate for you. 
In this part you need to guess and/or use mathematical kNowledge to find
a function that resembles your data
"""
def func(x,c,d):
  return b * x * x + c * x + d

"""
make the curve_fit
"""
popt,pcov = curve_fit(func,x,y)

"""
The result is:
popt[0] = a,popt[1] = b,popt[2] = c and popt[3] = d of the function,so f(x) = popt[0]*x**3 + popt[1]*x**2 + popt[2]*x + popt[3].
"""
print("b = " + str(popt[0]) + "  c = " + str(popt[1]) + "  d = " + str(popt[2]))

"""t
Use sympy to generate the latex sintax of the function
"""
xs = sym.Symbol('\lambda')    
tex = sym.latex(func(xs,*popt)).replace('$','')
plt.title(r'$f(\lambda)= %s$' %(tex),fontsize=16)

"""
Print the coefficients and plot the funcion.
"""

plt.plot(x,func(x,*popt),label="Fitted Curve") #same as line above \/
#plt.plot(x,popt[0]*x**3 + popt[1]*x**2 + popt[2]*x + popt[3],label="Fitted Curve") 

plt.legend(loc='upper left')
plt.show()

The plotted curve from the data above.

解决方法

这是因为Matplotlib只会在原始数据(在x和y数组中)的几个点之间按照定义的顺序绘制线条。只有3个唯一的x值(加上一些噪音),这就是为什么您看到看起来像三角形的原因。

解决方法是创建一个新数组,在感兴趣的范围内均匀分布x个有序的x值。您可以使用linspace function in numpy来做到这一点。

例如,对于第二个绘图命令,请尝试以下操作:

x_eval = np.linspace(min(x),max(x),100)

plt.plot(x_eval,func(x_eval,*popt),label="Fitted Curve")

x_eval列出了原始数据中最小x最大值和最大x值之间的100个均匀分布的值。

,

您似乎需要对xdata进行排序。

尝试插入此内容:

x,y = zip(*sorted(zip(x,y)))

那样

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

x = [0.0009425070688029959,0.0009398496240601303,0.0018779342723004293,0.004694835680751241,0.0009425070688029959,0.004734848484848552,0.0018993352326685255,0.0009460737937558928]
y = [0.0028301886792453904,0.003762935089369628,0.001881467544684814,0.0009433962264150743,0.0028301886792453904,0.0019029495718363059,0.0038058991436727804,0.0018939393939393534]
"""
Plot your data
"""
plt.plot(x,y,'ro',label="Original Data")

"""
brutal force to avoid errors
"""    

x,y)))

x = np.array(x,dtype=float) #transform your data in a numpy array of floats 
y = np.array(y,dtype=float) #so the curve_fit can work

"""
create a function to fit with your data. a,b,c and d are the coefficients
that curve_fit will calculate for you. 
In this part you need to guess and/or use mathematical knowledge to find
a function that resembles your data
"""
def func(x,c,d):
  return b * x * x + c * x + d

"""
make the curve_fit
"""
popt,pcov = curve_fit(func,x,y)

"""
The result is:
popt[0] = a,popt[1] = b,popt[2] = c and popt[3] = d of the function,so f(x) = popt[0]*x**3 + popt[1]*x**2 + popt[2]*x + popt[3].
"""
print("b = " + str(popt[0]) + "  c = " + str(popt[1]) + "  d = " + str(popt[2]))

"""t
Use sympy to generate the latex sintax of the function
"""
xs = sym.Symbol('\lambda')    
tex = sym.latex(func(xs,*popt)).replace('$','')
plt.title(r'$f(\lambda)= %s$' %(tex),fontsize=16)

"""
Print the coefficients and plot the funcion.
"""

plt.plot(x,func(x,label="Fitted Curve") #same as line above \/
#plt.plot(x,popt[0]*x**3 + popt[1]*x**2 + popt[2]*x + popt[3],label="Fitted Curve") 

plt.legend(loc='upper left')
plt.show()

The plotted curve from the data above.