我一直在try 使用scipy.curve_fit来拟合一条曲线,但它似乎坚持某个局部最小值(非常接近初始参数猜测),并且没有try 任何其他组合.通常在100-200次迭代后停止. 正如你所看到的,这种情况往往很糟糕. 预期形状为:短恒定线、斜坡线、(可选恒定线)、下斜线、短恒定线

def piecewise_linear(X, x1, x2, x22, x3, y1, y2, y3):
    return  np.piecewise(X,  [(X < x1), (x1 <= X) & (X < x2), (x2 <= X) & (X <= x22), (x22 < X) & (X < x3), X >= x3],
                  [lambda X: y1, lambda X: y1 + (y2 - y1) / (x2 - x1) * (X - x1),
                  lambda X: y2, lambda X: y2 + (y3 - y2) / (x3 - x22) * (X - x22), lambda X: y3])  

for i in range(num of vectors): 
    bounds = ([0, global_min_left_x, global_max_x, global_max_x,  -np.inf, -np.inf,-np.inf],
              [global_max_x, global_max_x, global_min_right_x, vector_length, np.inf,np.inf, np.inf])
    additional_kwargs = {'method': 'dogbox', 'ftol': 1e-15, 'xtol': 1e-15, 'maxfev': 100000}
    params, _ = curve_fit(piecewise_linear, X, Z, bounds=bounds,
                         p0=(global_min_left_x, global_max_x,global_max_x, global_min_right_x,
                                          global_min_left_z, global_max_z, global_min_right_z),
                                      **additional_kwargs)

    fitted_curve = [piecewise_linear(x, *params) for x in X]

Fit example

也许解决方案是设置正确的kwargs(tbh,我真的不确定我是否理解正确).我也try 了不同的P0,但问题是一样的-几乎没有拟合,基本上只是连接P0点.

也许看看我试图拟合的数据会有用,所以有一个例子 https://pastebin.com/f0xF9fsd

推荐答案

你有一个伸缩问题,你发布的数据是1e-8的规模,这会混淆优化算法.

您必须首先重新调整数据的比例,然后由于此优化可能陷入局部极小值,您应该try 从随机初始点重新启动它.我在您发布的数据上try 了以下代码(使用您的表示法,第一列是X,第二列是Z,函数piecewise_linear与您定义的一样):

ntrials = 1000
nparams = 7  # number of parameters to optimize

scale = max(max(abs(X)), max(abs(Z)))
print(f'scale: {scale}')
X = X / scale
Z = Z / scale

min_err = np.inf
best_params = None
for i in range(ntrials):
    try:
        params, stats = curve_fit(piecewise_linear, X, Z,
                                  p0=np.random.randn(nparams))
    except:
        # Ignores RuntimeError: Optimal parameters not found:
        # Number of calls to function has reached maxfev
        continue
    fitted_curve = [piecewise_linear(x, *params) for x in X]
    err = np.mean(np.square(Z - fitted_curve))
    # print(f'i: {i}: {err}')
    if err < min_err:
        min_err = err
        best_params = params

Printing scale shows around 6e-8 and you can multiply the parameters with this to scale them back if you need to. The best parameters of a 1000 trials gives me a mean squared error around 4e-6 on the rescaled data, and good curve: good-fit-image

Python相关问答推荐

pandas DataFrame GroupBy.diff函数的意外输出

删除最后一个pip安装的包

为什么带有dropna=False的groupby会阻止后续的MultiIndex.dropna()工作?

从numpy数组和参数创建收件箱

如何记录脚本输出

删除字符串中第一次出现单词后的所有内容

实现自定义QWidgets作为QTimeEdit的弹出窗口

转换为浮点,pandas字符串列,混合千和十进制分隔符

实现神经网络代码时的TypeError

如何禁用FastAPI应用程序的Swagger UI autodoc中的application/json?

Pandas Data Wrangling/Dataframe Assignment

在Python中计算连续天数

Pandas:计算中间时间条目的总时间增量

pysnmp—lextudio使用next()和getCmd()生成器导致TypeError:tuple对象不是迭代器''

如何在FastAPI中替换Pydantic的constr,以便在BaseModel之外使用?'

如何获得3D点的平移和旋转,给定的点已经旋转?

如何在验证文本列表时使正则表达式无序?

有没有办法让Re.Sub报告它所做的每一次替换?

如何在信号的FFT中获得正确的频率幅值

对于标准的原始类型注释,从键入`和`从www.example.com `?