Python 中的二次链或多分段连接
Quadratic to Chaining or Connected Multiple Piecewise in Python
我在 Whosebug 中研究了一段时间,但找不到任何多分段曲线拟合的示例。我想将二次函数转换为分段函数的多重链接(我不知道它的确切名称,但我需要将每个尾部连接到下一个分段的头部,简单地 "connected")。到目前为止,这是我的代码,使用 scipy.optimize
将二次函数转换为 2 个分段线性函数。
import scipy.optimize as opt
import numpy as np
import copy
def func_2piecewise(x, m_0, x_1, y_1, m_1):
y = np.piecewise(x, [x <= x_1, x > x_1],
[lambda x:m_0*(x-x_1) + y_1, lambda x:m_1*(x-x_1) + y_1])
return y
xmin=0
xmax=100
a=0.1
a0=1
a00=10
piece_number=2
sigma=np.ones(numberOfStep)
if piece_number==2:
lower_bounds=[-np.inf,xmin,-np.inf,-np.inf]
upper_bounds=[np.inf,xmax,np.inf,np.inf]
w, _ = opt.curve_fit(func_2piecewise, x_sample, y_sample,bounds=(lower_bounds,upper_bounds),sigma=sigma)
x_0=copy.deepcopy(xmin)
y_0=func_2piecewise(x_0, *w).tolist()
[m_0, x_1, y_1, m_1]=w
result=[x_0,y_0,m_0,x_1,y_1,m_1]
问题是,我无法对三个分段实施相同的方法(我不知道如何制作 x_2 > x_1):
def func_gradients(x_list,y_list):
len_x_list=len(x_list)
if len_x_list==1:
m_list=y_list/x_list
return m_list
m_list=[]
for idx in range(len_x_list-1):
m_list.append((y_list[idx+1]-y_list[idx])/(x_list[idx+1]-x_list[idx]))
return m_list
def func_3piecewise(x, m_0, x_1, y_1, x_2, y_2, m_2):
y = np.piecewise(x, [x <= x_1, (x > x_1) & (x <= x_2), x > x_2],
[lambda x:m_0*(x-x_1) + y_1, lambda x:y_1+(y_2-y_1)*(x-x_1)/(x_2-x_1), lambda x:m_2*(x-x_2) + y_2])
return y
if piece_number==3:
lower_bounds=[-np.inf,xmin,-np.inf,xmin,-np.inf,-np.inf]
upper_bounds=[np.inf,xmax,np.inf,xmax,np.inf,np.inf]
w, _ = opt.curve_fit(func_3piecewise, x_sample, y_sample,bounds=(lower_bounds,upper_bounds),sigma=sigma)
x_0=copy.deepcopy(xmin)
y_0=func_3piecewise(x_0, *w).tolist()
[m_0, x_1, y_1, x_2, y_2, m_2]=w
m_1=func_gradients(x_2-x_1,y_2-y_1)
result=[x_0,y_0,m_0,x_1,y_1,m_1, x_2, y_2, m_2]
完整代码见pastebin
所以,问题是:
如何在 python 中为一般的 n 段建立链接(分段函数的每个尾部连接到下一段的头部,或者简单地 "connected")分段函数? 可以接受其他算法或求解器。
编辑:到目前为止,我添加了 2 个分段的结果。
更新:我发现我的代码(三段)因为一个小错别字而无法运行(很抱歉,请告诉我是否应该删除这个问题)。现在它开始工作了,我更新了粘贴箱。但是,如果你有一个通用的(灵活的,不需要为每个数字变体编写函数)可以生成 n 件的功能,我会很乐意接受答案。
您可以参数化距离 x2-x1
而不是参数化 x2
。因为你可以给优化器边界,所以你可以将距离设置为大于 0。
例如,要生成具有 4 个区间的一般分段线性函数,请定义以下内容:
分隔区间和x0、x1、x2的点。 4 个区间的斜率分别为 m0、m1、m2 和 m3。 x0处的函数值为y0.
定义 d1 = x1 - x0, d2 = x2 - x1。来自这里:
x1 = x0 + d1
x2 = x0 + d1 + d2
然后,您有 8 个优化参数:x0、y0、d1、d2、m0、m1、m2 和 m3。根据您的优化问题的性质,除 x0 和 y0 之外的所有内容都是非负的。
第一个区间的方程式:
y = m0 * (x - x0) + y0
第二个区间的方程式:
y = m1 * (x - x0) + y0
现在你可以通过在其区间的最右边点应用前面的方程,以递归的方式得到其余的方程。对于x1点,函数的值为:
y1 = m1 * d1 + y0
所以第三个方程是
y =
m2 * (x - x1) + y1 =
m2 * (x - x0 - d1) + m1 * d1 + y0
对于 x2 点,这给出
y2 = m2 * d2 + y1
所以第四个方程是
y =
m3 * (x - x2) + y2 =
m3 * (x - x0 - d1 - d2) + m2 * d2 + m1 * d1 + y0
我在 Whosebug 中研究了一段时间,但找不到任何多分段曲线拟合的示例。我想将二次函数转换为分段函数的多重链接(我不知道它的确切名称,但我需要将每个尾部连接到下一个分段的头部,简单地 "connected")。到目前为止,这是我的代码,使用 scipy.optimize
将二次函数转换为 2 个分段线性函数。
import scipy.optimize as opt
import numpy as np
import copy
def func_2piecewise(x, m_0, x_1, y_1, m_1):
y = np.piecewise(x, [x <= x_1, x > x_1],
[lambda x:m_0*(x-x_1) + y_1, lambda x:m_1*(x-x_1) + y_1])
return y
xmin=0
xmax=100
a=0.1
a0=1
a00=10
piece_number=2
sigma=np.ones(numberOfStep)
if piece_number==2:
lower_bounds=[-np.inf,xmin,-np.inf,-np.inf]
upper_bounds=[np.inf,xmax,np.inf,np.inf]
w, _ = opt.curve_fit(func_2piecewise, x_sample, y_sample,bounds=(lower_bounds,upper_bounds),sigma=sigma)
x_0=copy.deepcopy(xmin)
y_0=func_2piecewise(x_0, *w).tolist()
[m_0, x_1, y_1, m_1]=w
result=[x_0,y_0,m_0,x_1,y_1,m_1]
问题是,我无法对三个分段实施相同的方法(我不知道如何制作 x_2 > x_1):
def func_gradients(x_list,y_list):
len_x_list=len(x_list)
if len_x_list==1:
m_list=y_list/x_list
return m_list
m_list=[]
for idx in range(len_x_list-1):
m_list.append((y_list[idx+1]-y_list[idx])/(x_list[idx+1]-x_list[idx]))
return m_list
def func_3piecewise(x, m_0, x_1, y_1, x_2, y_2, m_2):
y = np.piecewise(x, [x <= x_1, (x > x_1) & (x <= x_2), x > x_2],
[lambda x:m_0*(x-x_1) + y_1, lambda x:y_1+(y_2-y_1)*(x-x_1)/(x_2-x_1), lambda x:m_2*(x-x_2) + y_2])
return y
if piece_number==3:
lower_bounds=[-np.inf,xmin,-np.inf,xmin,-np.inf,-np.inf]
upper_bounds=[np.inf,xmax,np.inf,xmax,np.inf,np.inf]
w, _ = opt.curve_fit(func_3piecewise, x_sample, y_sample,bounds=(lower_bounds,upper_bounds),sigma=sigma)
x_0=copy.deepcopy(xmin)
y_0=func_3piecewise(x_0, *w).tolist()
[m_0, x_1, y_1, x_2, y_2, m_2]=w
m_1=func_gradients(x_2-x_1,y_2-y_1)
result=[x_0,y_0,m_0,x_1,y_1,m_1, x_2, y_2, m_2]
完整代码见pastebin
所以,问题是: 如何在 python 中为一般的 n 段建立链接(分段函数的每个尾部连接到下一段的头部,或者简单地 "connected")分段函数? 可以接受其他算法或求解器。
编辑:到目前为止,我添加了 2 个分段的结果。
更新:我发现我的代码(三段)因为一个小错别字而无法运行(很抱歉,请告诉我是否应该删除这个问题)。现在它开始工作了,我更新了粘贴箱。但是,如果你有一个通用的(灵活的,不需要为每个数字变体编写函数)可以生成 n 件的功能,我会很乐意接受答案。
您可以参数化距离 x2-x1
而不是参数化 x2
。因为你可以给优化器边界,所以你可以将距离设置为大于 0。
例如,要生成具有 4 个区间的一般分段线性函数,请定义以下内容:
分隔区间和x0、x1、x2的点。 4 个区间的斜率分别为 m0、m1、m2 和 m3。 x0处的函数值为y0.
定义 d1 = x1 - x0, d2 = x2 - x1。来自这里:
x1 = x0 + d1
x2 = x0 + d1 + d2
然后,您有 8 个优化参数:x0、y0、d1、d2、m0、m1、m2 和 m3。根据您的优化问题的性质,除 x0 和 y0 之外的所有内容都是非负的。
第一个区间的方程式:
y = m0 * (x - x0) + y0
第二个区间的方程式:
y = m1 * (x - x0) + y0
现在你可以通过在其区间的最右边点应用前面的方程,以递归的方式得到其余的方程。对于x1点,函数的值为:
y1 = m1 * d1 + y0
所以第三个方程是
y =
m2 * (x - x1) + y1 =
m2 * (x - x0 - d1) + m1 * d1 + y0
对于 x2 点,这给出
y2 = m2 * d2 + y1
所以第四个方程是
y =
m3 * (x - x2) + y2 =
m3 * (x - x0 - d1 - d2) + m2 * d2 + m1 * d1 + y0