【问题标题】:Plotting a piece-wise fit to non-linear data绘制非线性数据的分段拟合
【发布时间】:2016-03-09 11:31:11
【问题描述】:

我有一个类似于this previous StackOverflow question 的问题。我有一个数据集,我想拟合几个分段函数,然后绘制结果。

下面用红色标出了数据。

为了提供一些上下文,y 值表示电机需要多少毫秒才能转动 x 度。我已将原始值上传到this Pastebin

我现在想分段拟合三个函数:

  • 多项式拟合数据的开始,其中电机加速到最大速度。
  • 达到最大速度时的线性拟合。
  • 多项式拟合,然后电机关闭并减速。

到目前为止,我已经尝试使用下面显示的代码对两个线性函数进行分段拟合。考虑到数据的样子,我希望看到从原点到大约ms=550 的数据有一个斜率,然后从那里看到第二条线平行于 x 轴。

但是,这不是我得到的:

在我尝试使用三个函数进行分段拟合之前,我首先想了解为什么我得到这个图而不是我所期望的。

所以我的问题是:

  1. 谁能解释如何更正我的代码以使其适合两个线性函数?
  2. 如何扩展我的代码以使用三个函数绘制分段拟合?

用于创建上述绘图的代码如下:

from pandas import *
import matplotlib.pyplot as plt
import numpy as np
from scipy import optimize

#Getting data using Pandas
df = read_csv("test_data.csv")
ms = df["ms"].values
degrees = df["Degrees"].values

#A piece wise function taken from the other stackoverflow
def piecewise_linear(x, x0, y0, k1, k2):
    return np.piecewise(x, [x < x0], [lambda x:k1*x + y0-k1*x0, lambda x:k2*x + y0-k2*x0])

#Setting linspace and making the fit
x_new = np.linspace(ms[0], ms[-1])

p , e = optimize.curve_fit(piecewise_linear, ms, degrees)


#Plotting data and fit

fig = plt.figure()
ax = fig.add_subplot(111)

ax.plot(x_new, piecewise_linear(x_new, *p), '.', df)
ax.set_ylim([0, 450])
ax.set_xlim([0, 800])

【问题讨论】:

    标签: python numpy matplotlib scipy curve-fitting


    【解决方案1】:

    2。问题:你需要重新定义piecewise_linear,现在它有三个部分,随意改变(我只是放了一个2阶,1阶和3阶多项式的例子)。

    #Piecewise function defining 2nd deg, 1st degree and 3rd degree exponentials
    def piecewise_linear(x, x0, x1, y0, y1, k1, k2, k3, k4, k5, k6):
        return np.piecewise(x, [x < x0, x>= x0, x> x1], [lambda x:k1*x + k2*x**2, lambda x:k3*x + y0, lambda x: k4*x + k5*x**2 + k6*x**3 + y1])
    

    1.问题:显然为了使用curve_fit(),您需要转换为numpy数组。

    #Setting linspace and making the fit, make sure to make you data numpy arrays
    x_new = np.linspace(ms[0], ms[-1], dtype=float)
    m = np.array(ms, dtype=float)
    deg = np.array(degrees, dtype=float)
    guess = np.array( [100, 500, -30, 350, -0.1, 0.0051, 1, -0.01, -0.01, -0.01], dtype=float)
    p , e = optimize.curve_fit(piecewise_linear, m, deg)
    #Plotting data and fit
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(x_new, piecewise_linear(x_new, *p), '-', df)
    ax.set_ylim([0, 450])
    ax.set_xlim([0, 800])
    

    作为旁注,我还为您的初始参数添加了一些有根据的猜测,这比让 python 随机选择更适合您。

    那就做吧

    ax.plot(x_new, piecewise_linear(x_new, *p), '-', ms[::20], degrees[::20], 'o')
    

    【讨论】:

    • 谢谢,这正是我想要的。我注意到我需要在 curve_fit() 中添加猜测以获得拟合的平坦端。否则它就像一个魅力:)
    • 没问题 :),这也是我发现的,如果随意放置,3rd degree 就不太适合了。
    猜你喜欢
    • 1970-01-01
    • 2019-03-15
    • 2020-07-27
    • 2011-07-18
    • 2022-01-05
    • 2017-03-17
    • 2016-11-25
    • 2017-12-18
    • 2018-11-19
    相关资源
    最近更新 更多