微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

scipy 奇怪的意外行为 curve_fit 正弦波的大数据集

如何解决scipy 奇怪的意外行为 curve_fit 正弦波的大数据集

出于某种原因,当我尝试将大量数据转换为正弦波时,它会失败并将其拟合到水平线上。有人能解释一下吗?

最少的工作代码

import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
# Seed the random number generator for reproducibility
import pandas

np.random.seed(0)

# Here it work as expected
# x_data = np.linspace(-5,5,num=50)
# y_data = 2.9 * np.sin(1.05 * x_data + 2) + 250 + np.random.normal(size=50)

# With this data it breaks
x_data = np.linspace(0,2500,num=2500)
y_data = -100 * np.sin(0.01 * x_data + 1) + 250 + np.random.normal(size=2500)

# And plot it

plt.figure(figsize=(6,4))
plt.scatter(x_data,y_data)


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

# Used to fit the correct function
# params,params_covariance = optimize.curve_fit(test_func,x_data,y_data)

# making some guesses
params,y_data,p0=[-80,3,260])

print(params)
plt.figure(figsize=(6,label='Data')
plt.plot(x_data,test_func(x_data,*params),label='Fitted function')

plt.legend(loc='best')

plt.show()

This is the function with a lot of data and fitted incorrectly

This is the function with little data and fitted correctly

有谁知道如何解决这个问题。我应该使用不同的拟合方法而不是最小二乘法吗?还是应该减少数据点的数量

解决方法

根据您的数据,您可以使用更强大的 lmfit 而不是 scipy

特别是,您可以使用 SineModel(有关详细信息,请参阅 here)。

SineModel 中的

lmfit 不适用于“移位”正弦波,但您可以轻松处理移位

y_data_offset = y_data.mean()
y_transformed = y_data - y_data_offset
plt.scatter(x_data,y_transformed)
plt.axhline(0,color='r')

enter image description here

现在你可以适应正弦波

from lmfit.models import SineModel

mod = SineModel()

pars = mod.guess(y_transformed,x=x_data)
out = mod.fit(y_transformed,pars,x=x_data)

您可以使用 print(out.fit_report()) 检查结果并使用

绘制结果
plt.plot(x_data,y_data,lw=7,color='C1')
plt.plot(x_data,out.best_fit+y_data_offset,color='k')
#           we add the offset ^^^^^^^^^^^^^

enter image description here

或使用内置绘图方法 out.plot_fit(),请参阅 here 了解详情。

请注意,在 SineModel 中,所有参数“都被限制为非负”,因此您定义的负振幅 (-100) 在参数拟合结果中将为正 (+100)。所以相位也不会是 1 而是 π+1(PS:他们称 shift 相位)

print(out.best_values)

{'amplitude': 99.99631403054289,'frequency': 0.010001193681616227,'shift': 4.1400215410836605}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。