我正在尝试找到一个在 Python 中单调拟合数据的过程。
数据不一定是单调的。由于理论假设,我只想实现单调拟合。
我想这样做的一种方法是运行等渗回归,然后使用三次样条插值。有更简单的选择吗?
例如,在 R 中;我会将 cob 包用于约束样条曲线。Python中是否存在类似的东西?
如果有效的话,实现相同结果的其他方法也很好(例如,在数据的单调变换上拟合曲线,以保持关系的整体形状)。
谢谢!
我正在尝试找到一个在 Python 中单调拟合数据的过程。
数据不一定是单调的。由于理论假设,我只想实现单调拟合。
我想这样做的一种方法是运行等渗回归,然后使用三次样条插值。有更简单的选择吗?
例如,在 R 中;我会将 cob 包用于约束样条曲线。Python中是否存在类似的东西?
如果有效的话,实现相同结果的其他方法也很好(例如,在数据的单调变换上拟合曲线,以保持关系的整体形状)。
谢谢!
嗨,我不知道您的问题的具体情况,但您可能会发现以下参考资料非常有趣:Eilers,2006(尤其是第 3 段)。参考中提出的想法实现起来相当简单(附录中应该还有一些matlab代码)。无论如何,你会在下面找到我自己的尝试:-)
该论文使用了一种更平滑的技术,称为 P 样条。Eilers 和 Marx 于 1991 年引入了 P 样条曲线,并结合了 B 样条曲线(在等间距已知上定义)和样条系数的有限差分正则化(第二个参考文献还包含一些代码,您可以使用这些代码来习惯该方法,如果你要)。
在我的回答中,我将使用 P 样条的特殊情况,即 Whittaker 分级方法(参见Eilers,2003,其中还包含附录中的一些计算机代码)。
为了实现单调性,我们希望估计的 Whittaker 平滑器的一阶差分具有相同的符号(全部为负或正)。假设我们想要一个单调递增的 fit。继Eilers, 2006之后,我们可以将问题写为
下面你会发现一个比较单调和非单调拟合的小例子。
import math
import numpy
import matplotlib.pyplot as plt
# Simulate data
N = 100
xlo = 0.001
xhi = 2*numpy.pi
x = numpy.arange(xlo, xhi, step = (xhi-xlo)/N)
y0 = numpy.sin(x) + numpy.log(x)
y = y0 + numpy.random.randn(N) * 0.5
# Prepare bases (Imat) and penalty
dd = 3
E = numpy.eye(N)
D3 = numpy.diff(E, n = dd, axis=0)
D1 = numpy.diff(E, n = 1, axis=0)
la = 100
kp = 10000000
# Monotone smoothing
ws = numpy.zeros(N - 1)
for it in range(30):
Ws = numpy.diag(ws * kp)
mon_cof = numpy.linalg.solve(E + la * D3.T @ D3 + D1.T @ Ws @ D1, y)
ws_new = (D1 @ mon_cof < 0.0) * 1
dw = numpy.sum(ws != ws_new)
ws = ws_new
if(dw == 0): break
print(dw)
# Monotonic and non monotonic fits
z = mon_cof
z2 = numpy.linalg.solve(E + la * D3.T @ D3, y)
# Plots
plt.scatter(x, y, linestyle = 'None', color = 'gray', s = 0.5, label = 'raw data')
plt.plot(x, z, color = 'red', label = 'monotonic smooth')
plt.plot(x, z2, color = 'blue', linestyle = '--', label = 'unconstrained smooth')
plt.legend(loc="lower right")
plt.show()
我希望这会有所帮助(或者至少你觉得它很有趣)。
我不知道明确适合样条曲线的 python 包,但你应该能够在最新版本的 scikit-learn 中通过梯度提升来实现你的目标(https://scikit-learn.org/stable/auto_examples/release_highlights /plot_release_highlights_0_23_0.html)。
具体来说,您可以使用HistGradienBoostingRegressor和 setting拟合广义加法模型max_depth=1
,这可确保特征之间没有交互(如果这是您想要的)。然后,您可以使用monotonic_cst
为每个特征指定单调性约束。
此选项也存在于XGBoost中。