【问题标题】:How to increase the impact of an explanatory variable on Y as we step forward in time?随着时间的推移,如何增加解释变量对 Y 的影响?
【发布时间】:2019-02-24 12:53:44
【问题描述】:

问题:

我正在三个时间序列上构建模型,其中 Y 是因变量,X1 和 X2 是解释变量。假设有充分的理由相信 X1 对 Y 的影响与 X2 相比随着时间的推移而增加。您如何在多元回归模型中解释这一点? (随着问题的进行,我会展示一些代码 sn-ps,你会在最后找到完整的代码部分。)

细节 - 视觉方法:

以下是三个合成系列,其中 X1 对 Y 的影响在期末似乎非常强烈:

基本模型可以是:

model = smf.ols(formula='Y ~ X1 + X2')

如果你根据观察到的 Y 值绘制拟合值,你会得到:

并且坚持对模型的视觉评估,它似乎在该时期的大部分时间里表现良好,但在 8 月开始之后就很差了。 如何在多元回归模型中解释这一点?在this post 的帮助下,我尝试在这些模型中引入具有线性和平方时间步长的交互项:

mod_timestep  = Y ~ X1 + X2:timestep
mod_timestep2 = Y ~ X1 + X2:timestep2

顺便说一下,这些是时间步长:

结果:

似乎这两种方法最终的表现都好一点,但一开始就差很多。

还有其他建议吗?我知道有很多可能存在依赖模型和其他模型(如 ARIMA 或 GARCH)的滞后项。但出于多种原因,我希望保持在多元线性回归的范围内,并且尽可能不使用滞后项。

这是一个简单的复制和粘贴的全部内容:

#%%
# imports
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.dates as mdates
import numpy as np
import statsmodels.api as sm
import statsmodels.formula.api as smf
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)

###############################################################################
# Synthetic Data and plot
###############################################################################

# Function to build synthetic data
def sample():

    np.random.seed(26)
    date = pd.to_datetime("1st of Dec, 1999")

    nPeriod = 250

    dates = date+pd.to_timedelta(np.arange(nPeriod), 'D')
    #ppt = np.random.rand(1900)
    Y = np.random.normal(loc=0.0, scale=1.0, size=nPeriod).cumsum()
    X1 = np.random.normal(loc=0.0, scale=1.0, size=nPeriod).cumsum()
    X2 = np.random.normal(loc=0.0, scale=1.0, size=nPeriod).cumsum()

    df = pd.DataFrame({'Y':Y,
                       'X1':X1,
                       'X2':X2},index=dates)
    # Adjust level of series
    df = df+100

    # A subset
    df = df.tail(50)
    return(df)

# Function to make a couple of plots
def plot1(df, names, colors):

    # PLot
    fig, ax = plt.subplots(1)
    ax.set_facecolor('white')

    # Plot series
    counter = 0

    for name in names:
        print(name)
        ax.plot(df.index,df[name], lw=0.5, color = colors[counter])
        counter = counter + 1

    fig = ax.get_figure()

    # Assign months to X axis
    locator = mdates.MonthLocator()  # every month

    # Specify the X format
    fmt = mdates.DateFormatter('%b')
    X = plt.gca().xaxis
    X.set_major_locator(locator)
    X.set_major_formatter(fmt)
    ax.legend(loc = 'upper left', fontsize ='x-small')
    fig.show()

# Build sample data
df = sample()

# PLot of input variables
plot1(df = df, names = ['Y', 'X1', 'X2'], colors = ['red', 'blue', 'green'])

###############################################################################
# Models
###############################################################################

# Add timesteps to original df
timestep = pd.Series(np.arange(1, len(df)+1), index = df.index)
timestep2 = timestep**2
newcols2 = list(df)
df = pd.concat([df, timestep, timestep2], axis = 1)

newcols2.extend(['timestep', 'timestep2'])
df.columns = newcols2

def add_models_to_df(df, models, modelNames):

    df_temp = df.copy()

    counter = 0
    for model in models:
        df_temp[modelNames[counter]] = smf.ols(formula=model, data=df).fit().fittedvalues
        counter = counter + 1

    return(df_temp)

df_models = add_models_to_df(df, models = ['Y ~ X1 + X2', 'Y ~ X1 + X2:timestep', 'Y ~ X1 + X2:timestep2'],
                             modelNames = ['mod_regular', 'mod_timestep', 'mod_timestep2'])


# Models
df_models = add_models_to_df(df, models = ['Y ~ X1 + X2', 'Y ~ X1 + X2:timestep', 'Y ~ X1 + X2:timestep2'],
                             modelNames = ['mod_regular', 'mod_timestep', 'mod_timestep2'])

# Plots of models
plot1(df = df_models,
      names = ['Y', 'mod_regular', 'mod_timestep', 'mod_timestep2'],
      colors = ['red', 'black', 'green', 'grey'])

编辑 1 - 来自建议的屏幕截图:**

【问题讨论】:

  • 我做了一个 X1、X2 和 Y 的 3D 散点图。在 3 空间旋转视图后,数据看起来是一个“点云”,在视觉上没有明显的关系,可以建模为"Y = f(X1, X2)" - 这对于使用 np,random 对 sample() 进行编码的方式是有意义的。对原始数据执行此练习以查看是否有明显的 3D 关系可能会有所帮助。
  • 所以如果我理解正确,你想对最近的观察(X1)有更多的权重(重要性)?
  • @asimo.是的,这正是我的意思。
  • 这个可以通过特征工程来处理;通过计算列出从开始或结束日期经过的时间(天)的变量。然后,您可以应用一个简单的指数函数,如 W=K*exp(-timeElapsed/T),其中 K 是缩放常数,T 是衰减函数的时间常数。 W 用作案例重量。现在您可以将这个新的特征工程变量合并为您的新 X1
  • @vestland 如果上述提出的指数函数方法可以解决您的问题,请告诉我们

标签: python regression statsmodels


【解决方案1】:

使用您提供的链接上的其他选项似乎是更好的选择。

将您的函数与Y ~ X1 + X2*timestepY ~ X1 + X2*timestep2 一起使用至少会“抓住”开始时Y 的增加、期间的减少和结束时的突然增加。

我还不能发布图片,所以你必须自己尝试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 2013-08-30
    • 2012-11-25
    • 2011-03-07
    • 2013-08-10
    • 1970-01-01
    相关资源
    最近更新 更多