多分段线性函数拟合

今天遇到需求需要进行多分段线性函数拟合,发现了两种方法可以实现。

1.Stack Overflow上有人给出的一个答案

在Stack Overflow有大佬给出了回答,如何进行分段线性函数拟合,对于2分段函数吗,可以用numpy.piecewise()创建分段函数,再用curve_fit()去训练得到参数即可。对于多分段线性函数,大佬也给出了一个自己写的函数来实现,该函数可以拟合出多分段线性函数的拟合点。Stack Overflow回答链接。

1.1二分段函数代码及输出

from scipy import optimize
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ,11, 12, 13, 14, 15], dtype=float)
y = np.array([5, 7, 9, 11, 13, 15, 28.92, 42.81, 56.7, 70.59, 84.47, 98.36, 112.25, 126.14, 140.03])

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])

p , e = optimize.curve_fit(piecewise_linear, x, y)
xd = np.linspace(0, 15, 100)
plt.plot(x, y, "o")
plt.plot(xd, piecewise_linear(xd, *p))

多分段线性函数拟合_第1张图片

1.2 多分段线性函数代码及实现

多分段线性函数代码链接

%matplotlib inline
import numpy as np
import pylab as pl

def make_test_data(seg_count, point_count):
    x = np.random.uniform(2, 10, seg_count)
    x = np.cumsum(x)
    x *= 10 / x.max()
    y = np.cumsum(np.random.uniform(-1, 1, seg_count))
    X = np.random.uniform(0, 10, point_count)
    Y = np.interp(X, x, y) + np.random.normal(0, 0.05, point_count)
    return X, Y
   
from scipy import optimize

def segments_fit(X, Y, count):
    xmin = X.min()
    xmax = X.max()

    seg = np.full(count - 1, (xmax - xmin) / count)

    px_init = np.r_[np.r_[xmin, seg].cumsum(), xmax]
    py_init = np.array([Y[np.abs(X - x) < (xmax - xmin) * 0.01].mean() for x in px_init])

    def func(p):
        seg = p[:count - 1]
        py = p[count - 1:]
        px = np.r_[np.r_[xmin, seg].cumsum(), xmax]
        return px, py

    def err(p):
        px, py = func(p)
        Y2 = np.interp(X, px, py)
        return np.mean((Y - Y2)**2)

    r = optimize.minimize(err, x0=np.r_[seg, py_init], method='Nelder-Mead')
    return func(r.x)
 
X, Y = make_test_data(10, 2000)
px, py = segments_fit(X, Y, 8)

pl.plot(X, Y, ".")
pl.plot(px, py, "-or");

多分段线性函数拟合_第2张图片

2.pwlf实现多分段线性函数

pwlf是一个很完善的多分段线性函数实现的包了,官网链接,这个包是比较好的,在我的实践中,用1.2的代码无法成功拟合出来,但是用这个包可以成功拟合出多分段线性函数,因此这个包是要比上面的代码更好的。而且这个包可以实现的功能也很多了,这里放个官方可实现的功能目录。
当然这个包不止可以拟合多段线性函数,也可以不是线性函数,比如二次函数等等都可以。
多分段线性函数拟合_第3张图片

你可能感兴趣的:(python方面的一些文章,包括语言和工具,多分段线性函数,python)