除了scipy,在python上还有其他方法可以进行曲线拟合吗?

nszi6y05  于 2023-06-06  发布在  Python
关注(0)|答案(3)|浏览(162)

我做了一个代码,把数据拟合到正弦图上。但效果不好

import numpy as np
import pandas as pd
from scipy.optimize import curve_fit

def f(x, a, b, c, d):
    return (a)*np.sin((b)*x+(c))+(d)

df = pd.read_csv("./data.csv", usecols = ['t3','Vz'])

#df=pd.read_csv("E:/2023/spring/프밍기/codes/data.csv")
data_need = df.iloc[range(249), [0, 1]]
x = np.array(data_need['t3'])
y = np.array(data_need['Vz'])

popt, pcov = curve_fit(f, x, y)

a, b, c, d = popt
formatted_a = "{:.3f}".format(a)
formatted_b = "{:.3f}".format(b)
formatted_c = "{:.3f}".format(c)
formatted_d = "{:.3f}".format(d)
function_expression = f"y = {formatted_a} * sin({formatted_b}x + {formatted_c}) + {formatted_d}"
print(function_expression)

import matplotlib.pyplot as plt
plt.scatter(x, y, marker='.')
plt.plot(x, y, linewidth=2)
plt.plot(x, f(x, *popt), color='red', linewidth=2)
plt.legend(['Original', 'Best Fit'], loc=2)
plt.show()

输出如下:

我想知道为什么结果不好,还有其他方法可以在python中进行曲线拟合。

66bbxpm5

66bbxpm51#

有多个软件包来执行各种拟合和/或建模任务。
任何曲线拟合/最小二乘最小化的一个特征是,您需要提供参数的初始猜测。如果初始猜测非常偏离,则最小化可能根本不收敛,或者收敛到次优解。
在本例中,您没有指定初始猜测,scipy.optimize.curve_fit使用了一些值,结果不好;所以首先要做的就是指定它。你可以从数据范围粗略估计振幅,从峰到峰距离粗略估计频率等。
并去除数据流开始零补丁。

vql8enpb

vql8enpb2#

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

# It's just a dummy data...
n = 200
xdata = np.linspace(0, 25, n)

ydata = np.array([3.38, 2.811, 2.539, 1.925, 1.717, 1.529, 1.185, 1.035, 
                  1.191, 1.272, 1.238, 1.477, 1.821, 2.102, 2.142, 2.528, 
                  2.813, 3.594, 3.542, 3.717, 3.918, 4.165, 3.965, 3.547, 
                  3.651, 3.262, 2.694, 2.324, 2.014, 1.589, 1.263, 1.288, 
                  1.132, 0.832, 0.881, 1.075, 1.298, 1.491, 1.919, 2.55, 
                  2.556, 3.061, 3.33, 3.415, 3.751, 3.906, 4.239, 3.735, 
                  3.793, 3.655, 3.457, 3.045, 2.427, 2.192, 1.584, 1.468, 
                  1.344, 1.264, 1.09, 0.78, 1.145, 1.226, 1.502, 1.989, 
                  2.223, 2.6, 2.896, 3.5, 3.651, 3.864, 4.023, 4.074, 3.993, 
                  4.001, 3.292, 2.983, 2.673, 2.728, 2.157, 1.745, 1.538, 
                  0.988, 0.923, 1.094, 1.103, 1.15, 1.172, 1.687, 1.884, 
                  2.256, 2.927, 3.21, 3.424, 3.734, 3.8, 3.849, 3.865, 4.097, 
                  3.639, 3.644, 3.472, 2.945, 2.46, 2.24, 1.808, 1.427, 1.043, 
                  0.861, 0.862, 0.968, 1.278, 1.406, 1.552, 1.853, 2.117, 
                  2.489, 3.186, 3.153, 3.82, 3.617, 4.127, 3.919, 4.153, 
                  3.893, 3.294, 3.145, 2.759, 2.619, 1.887, 1.673, 1.675, 
                  1.149, 1.213, 0.853, 0.898, 1.38, 1.484, 1.764, 1.895, 
                  2.388, 2.602, 3.156, 3.297, 3.622, 3.846, 3.772, 3.891, 
                  3.912, 3.88, 3.4, 3.457, 2.773, 2.307, 1.991, 1.666, 1.312, 
                  0.999, 1.118, 1.015, 1.242, 0.921, 1.128, 1.387, 1.942, 
                  2.096, 2.739, 2.875, 3.286, 3.776, 4.09, 3.948, 3.86, 4.099, 
                  3.756, 3.735, 3.182, 3.066, 2.27, 2.163, 1.623, 1.604, 
                  1.375, 1.3, 0.968, 1.098, 0.888, 1.363, 1.445, 1.82, 2.214, 
                  2.747, 2.902, 3.502, 3.766, 3.691, 3.74, 3.946, 3.999, 
                  3.629, 3.629])

def f(x, a, b, c, d):
    return a*np.sin(b*x + c) + d

# fitting all data
popt, pcov = curve_fit(f, xdata, ydata)
a, b, c, d = popt

# using only a portion of the data
i = slice(0, 25)
popt2, pcov2 = curve_fit(f, xdata[i], ydata[i])
a2, b2, c2, d2 = popt2

print(popt)
print(popt2)

plt.plot(xdata, ydata, marker='.', ls='')
plt.plot(xdata, f(xdata, *popt), color='red', linewidth=2)
plt.plot(xdata, f(xdata, *popt2), color='orange', linewidth=2)
plt.legend(['Original', 
            f'Fitting all data ({n} points)', 
            f'Fitting from i = {i.start} to {i.stop-1}'], 
           loc=2)
plt.show()

x33g5p2x

x33g5p2x3#

正弦曲线拟合很容易失败,所以不要尝试。执行FFT并观察峰值。从Numpy执行rfft。它将更加健壮,并且不需要边界或初始猜测就能很好地工作。

相关问题