带 LASSO 的线性变化点模型

机器算法验证 机器学习 时间序列 Python 套索 样条
2022-03-20 07:36:15

我正在试验时间序列数据,特别是使用傅里叶基函数并拟合 LASSO。然后我决定尝试将第一个点与另一个点连接起来,然后将那个点连接到最后一个点,看看它给了我什么。所以X矩阵是这样构建的(肯定效率不高):

import quandl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

data = quandl.get("BITSTAMP/USD")

y = data['Low']
y = y[-730:]

n_changepoints = 25
array_splits = np.array_split(np.array(y),n_changepoints)
y = np.array(y)
initial_point = y[0]
final_point = y[-1]
changepoints = np.zeros(shape=(len(y),n_changepoints))
for i in range(n_changepoints):
    moving_point = array_splits[i][-1]
    if i == 0:
        len_splits = len(array_splits[i])
    else:
        len_splits = len(np.concatenate(array_splits[:i+1]).ravel())
    slope = (moving_point - initial_point)/(len_splits)
    if i != n_changepoints - 1:        
        reverse_slope = (final_point - moving_point)/(len(y) - len_splits)
        reverse_slope = reverse_slope#*.5
    changepoints[0:len_splits, i] = slope * (1+np.array(list(range(len_splits))))
    changepoints[len_splits:, i] = changepoints[len_splits-1, i] + reverse_slope * (1+np.array(list(range((len(y) - len_splits)))))
    
plt.plot(y - y[0])
plt.plot(changepoints)
plt.show()

在此处输入图像描述

然后,如果我将它与套索和一些随机 alpha 相匹配,我会得到如下结果:

from sklearn.linear_model import Lasso
lasso_model = Lasso(alpha = 10000).fit(changepoints, y)
fitted = lasso_model.predict(changepoints)
plt.plot(y)
plt.plot(fitted)
plt.show()

在此处输入图像描述

它现在看起来像是一个趋势变化点模型,让人想起 fbprophet 的输出。

然后,当我将傅立叶项与这些项结合起来并拟合套索并进行一些调整时,我最终会得到一些相当合理的结果,这些结果与 fbprophet 之类的结果一致。所以我的主要问题是,连接相关点(即使用导数)的想法是什么?从一些研究来看,它看起来只是一些样条线的东西,但我显然是这个领域的新手,并且会喜欢一些方向!

使用更全面的实施进行编辑,并根据答案跟进问题:

可以在这里找到它以及一个简单的示例。真正追求的是其核心是特征工程,它被传递给一个简单的线性回归拟合,这里它是一个带有套索正则化的 GLM,其目标是类似于来自 fbProphet 的东西。那么这种“加权”矩阵的方法是一致的还是肯定会比使用另一组线性分段函数更糟糕?

具有这些傅立叶基函数的示例输出: 在此处输入图像描述

1个回答

好问题。

明天我还有更多要说的,但现在这里的重点是你的预测矩阵changepoints只是一个分段线性基函数的加权矩阵,其中权重设置为适合数据中的 25 个等距点。

在此处输入图像描述

尽管其他方法更受欢迎,但使用 lasso 来惩罚回归样条曲线是很常见的。如果您还没有阅读过它,统计学习要素的第 5 章将介绍这一点。

是基函数的标准矩阵(中图),是应用于每个基的权重(右图),是加权基矩阵(左图)。如果您要使用 OLS 而不是 lasso,则使用,因为回归权重可以捕获差异:,其中XwXwXXwy^=Xw×β=X×βwβw=w×β

然而,使用套索,你最终会得到一个稍微不同的解决方案,因为惩罚与惩罚我需要做更多的探索才能确定,但​​是使用应该只会导致对给定 L1 惩罚项 ( ) 的数据更紧密地拟合,因此存在一些惩罚,时给出完全相同的解决方案ββwXwalphaα>10,000X

注意:我跳过了一些关于基函数居中和减去线性趋势的细节。

代码:

def plot_weights(weights, colour=True):
    n = weights.shape[0]
    if colour:
        for i in range(n):
            plt.plot([i, i], [0, weights[i]])
    else:
        plt.vlines(x=np.arange(n), ymin=0, ymax=weights)
    plt.hlines(0, 0, n, linestyle='dashed')
    plt.ylabel('Weight')

slope = changepoints[:, 0]
weighted_bases = changepoints[:, 1:] - slope.reshape(-1, 1)

ix_argmax = np.abs(weighted_bases).argmax(0)
basis_weights = np.array([weighted_bases[ix, i] for i, ix in enumerate(ix_argmax)])
raw_bases = weighted_bases / basis_weights

fig, axes = plt.subplots(1, 4, figsize=(14, 2))
plt.sca(axes[0])
plt.plot(changepoints)
plt.title('Changepoint Matrix =')

plt.sca(axes[1])
plt.plot(slope)
plt.title('Slope +')

plt.sca(axes[2])
plt.plot(bases)
plt.title('(Basis functions')

plt.sca(axes[3])
plot_weights(basis_weights)
plt.title('× Weights)')
plt.tight_layout()