Scipy optimize.curve_fit 有时不收敛

1 投票
1 回答
2805 浏览
提问于 2025-04-16 05:22

我正在尝试使用numpy.optimize.curve_fit来估算一个开关序列的频率和相位。以下是我使用的代码:

from numpy import *
from scipy import optimize

row = array([0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0,])

def fit_func(x, a, b, c, d):
    return c * sin (a * x + b) + d

p0 = [(pi/10.0), 5.0, row.std(), row.mean()]
result = optimize.curve_fit(fit_func, arange(len(row)), row, p0)
print result

这个方法是有效的。但是在某些数据行上,即使它们看起来完全正常,程序也会失败。

这是一个失败的例子:

row = array([1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, 0.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, 0.0,  0.0,  0.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  0.0,  0.0,  0.0,  0.0, 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  0.0,  0.0, 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0,  1.0, 1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,])

错误信息是:

RuntimeError: 找不到最佳参数:实际和预测的平方和相对减少值最多为0.000000,两个连续迭代之间的相对误差最多为0.000000

这个错误信息对我来说几乎没有帮助。

我做了一个快速测试,发现如果改变p0中的参数,这一行就会成功……而其他行则会失败。这是为什么呢?

1 个回答

2

我试了你提供的两组数据,结果都很好用。我用的是Scipy 0.8.0rc3。你用的是什么版本呢?还有一个建议是把c和d设置为固定值,因为它们每次应该是一样的。我把c设置为0.6311786,d设置为0.5。如果你想用另一种方法,也可以使用FFT(快速傅里叶变换)加上零填充和二次拟合来找到频率。其实,任何音高估计的方法都可以用,因为你是在寻找基频。

撰写回答