如何更好地拟合数据或平移数据?我的拟合远低于数据
我们需要通过拍摄一个摆锤来检测它的运动,用特定的软件跟踪摆锤,并把时间、x坐标和y坐标的值存储到一个txt文件里。因为我的手很抖,所以图表看起来也很抖(附上了图片)。
这是我的代码:
import sys
sys.path.insert(0, "..")
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
%matplotlib inline
import pandas as pd
data = np.loadtxt('newdata.txt', delimiter = ',', skiprows = 1)
t = data[:,0]
x = data[:,1]
def cos_func(times, amplitude, frequency):
return amplitude * np.cos(frequency * times)
def period2freq(period):
return 1.0 / period * 2.0 * np.pi
def freq2period(freq):
return 1.0 / freq * 2.0 * np.pi
popt, pcov = curve_fit(cos_func, # our function
t, # measured x values
x, # measured y values
p0=(200, period2freq(150))) # the initial guess for the two parameters
fig, ax = plt.subplots(1, 1)
ax.plot(t, x, label='Measured')
ax.plot(t, cos_func(t, popt[0], popt[1]), label='Best Fit')
ax.legend()
我尝试了一些东西,现在这是我的代码和图片,效果还是不好:
# Laden der Daten
data = np.loadtxt('newdata.txt', delimiter = ',', skiprows = 1)
t = data[:,0]
x = data[:,1]
# Definition der Fit-Funktion mit Offset und Phase
def cos_func(times, amplitude, frequency, phase, offset):
return amplitude * np.cos(frequency * times + phase) + offset
# Startparameter für den Fit
initial_amplitude = (np.max(x) - np.min(x)) / 2 # Amplitude als Hälfte der Amplitude der Daten
initial_frequency = 2 * np.pi / 150 # Annahme für die Frequenz
initial_phase = 0 # Startphase
initial_offset = -220 # Ihr Offset-Wert
shift = 10 # Verschiebung um 5 Einheiten nach rechts
# Durchführung des Fits
p0 = (initial_amplitude, initial_frequency, initial_phase, initial_offset)
popt, pcov = curve_fit(cos_func, t, x, p0=p0)
# Anpassen der Phase für die Verschiebung nach rechts
popt[2] += shift * initial_frequency
# Plotten der Daten und des Fits
plt.figure(figsize=(10, 6))
plt.plot(t, x, label='Measured')
plt.plot(t, cos_func(t, *popt), label='Best Fit')
plt.legend()
plt.xlabel('Time')
plt.ylabel('Position')
plt.title('Fit of Pendulum Motion')
plt.show()
老实说,我只是随便玩了玩,让它看起来好一点,但效果还是不好,我也不太明白。
2 个回答
0
你正在使用的函数有两个特点,而这些特点在你的数据中并不存在:
- 这个函数的最大值一定出现在开始的时候(t=0),因为你使用的是余弦函数而没有相位偏移。你应该加上一个相位偏移(在函数的参数中加一个常数)。
- 另外,这个函数的值一定是围绕0波动的,因为你没有允许在y轴上移动。你也应该加上这个偏移。(既然你在问题中提到这一点:是的,你可以通过从所有数据值中减去平均值来把数据的平均值调整为零。但在拟合函数中加一个常数可能更灵活,也能让结果更直接地与原始数据相关。)
总结一下,你应该使用一个函数 y(t) = a * cos(b * t + c) + d,其中 (a,b,c,d) 需要你来确定。
另外,你不仅在拍摄时摇晃得很厉害,而且看起来你还在用相机跟着摆动的物体移动。因此,图像中物体的位置并不对应于物体在空间中的绝对位置……不过,没关系,你还是能得到一条尽可能贴合数据点的余弦曲线……
0
你有没有试过把你的函数改成这样:
def cos_func(times, amplitude, frequency, offset):
return amplitude * np.cos(frequency * times) + offset