LSTM - 一段时间后预测相同的常数值

2024-05-22

我有一个变量,我想预测未来 30 年的情况。不幸的是我没有很多样品。

df = pd.DataFrame({'FISCAL_YEAR': [1979,1980,1981,1982,1983,  1984,  
1985,  1986,  1987,  1988,  1989,  1990,  1991,  1992,  1993,  1994,  
1995,  1996,
  1997,  1998,  1999,  2000,  2001,  2002,  2003,  2004,  2005,  2006,  
2007,  2008,  2009,  2010,  2011,  2012,  2013,  2014,  2015,  2016,  
2017,  2018,  2019],
 'VALS': [1341.9,  1966.95,  2085.75,  2087.1000000000004,  2760.75,  
3461.4,  3156.3,  3061.8,  2309.8500000000004,  2320.65,  2535.3,  
2964.6000000000004,  2949.75,  2339.55,
  2327.4,  2571.75,  2299.05,  1560.6000000000001,  1370.25,  1301.4,  
1215.0,  5691.6,  6281.55,  6529.950000000001,  17666.100000000002,  
14467.95,  15205.050000000001,  14717.7,  14426.1,  12946.5,
  13000.5,  12761.550000000001,  13076.1,  13444.650000000001,  
13444.650000000001,  13321.800000000001,  13536.45,  13331.25,  
12630.6,  12741.300000000001,  12658.95]})

这是我的代码:

def build_model(n_neurons,dropout,s):
    lstm = Sequential()
    if cudnn:
        lstm.add(CuDNNLSTM(n_neurons))
        n_epochs = 200
    else:
        lstm.add(Masking(mask_value=-1,input_shape=(s[1],s[2])))
        lstm.add(LSTM(n_neurons,dropout=dropout))
        n_epochs = 500

    lstm.add(Dense(1))
    #lstm.add(Activation('softmax'))
    lstm.compile(loss='mean_squared_error',optimizer='adam')
    return lstm

def create_df(dfin,fwd,lstmws):
    ''' Input Normalization '''
    idx = dfin.FISCAL_YEAR.values[fwd:]
    dfx = dfin[[varn]].copy()
    dfy = dfin[[varn]].copy()

    # LSTM window - use last lstmws values
    for i in range(0,lstmws-1):
        dfx = dfx.join(dfin[[varn]].shift(-i-1),how='left',rsuffix='{:02d}'.format(i+1))

    dfx = (dfx-vmnx).divide(vmxx-vmnx)
    dfx.fillna(-1,inplace=True) # replace missing values with -1

    dfy = (dfy-vmnx).divide(vmxx-vmnx)
    dfy.fillna(-1,inplace=True) # replace missing values with -1
    return dfx,dfy,idx

def forecast(dfin,dfx,lstm,idx,gapyr=1):
    ''' Model Forecast '''
    xhat = dfx.values
    xhat = xhat.reshape(xhat.shape[0],lstmws,int(xhat.shape[1]/lstmws))
    yhat = lstm.predict(xhat)

    yhat = yhat*(vmxx-vmnx)+vmnx
    dfout = pd.DataFrame(list(zip(idx+gapyr,yhat.reshape(1,-1)[0])),columns=['FISCAL_YEAR',varn])
    dfout = pd.concat([dfin.head(1),dfout],axis=0).reset_index(drop=True)
    #append last prediction to X and use for prediction
    dfin = pd.concat([dfin,dfout.tail(1)],axis=0).reset_index(drop=True)
    return dfin

def lstm_training(dfin,lstmws,fwd,num_years,batchsize=4,cudnn=False,n_neurons=47,dropout=0.05,retrain=False):
    ''' LSTM Parameter '''
    seed(2018)
    set_random_seed(2018)
    gapyr = 1 # Forecast +1 Year

    dfx,dfy,idx = create_df(dfin,fwd,lstmws)

    X,y = dfx.iloc[fwd:-gapyr].values,dfy[fwd+gapyr:].values[:,0]
    X,y = X.reshape(X.shape[0],lstmws,int(X.shape[1]/lstmws)),y.reshape(len(y), 1)

    lstm = build_model(n_neurons,dropout,X.shape)
    ''' LSTM Training Start '''
    if batchsize == 1:
        history_i = 
lstm.fit(X,y,epochs=25,batch_size=batchsize,verbose=0,shuffle=False)
    else:
        history_i = lstm.fit(X,y,epochs=n_epochs,batch_size=batchsize,verbose=0,shuffle=False)

    dfin = forecast(dfin,dfx,lstm,idx)


    lstm.reset_states()
    if not retrain:
        for fwd in range(1,num_years):

            dfx,dfy,idx = create_df(dfin,fwd,lstmws)

            dfin = forecast(dfin,dfx,lstm,idx)

            lstm.reset_states()

    del dfy,X,y,lstm
    gc.collect();
clear_session();
return dfin,history_i

varn = "VALS"
#LSTM-window
lstmws = 10
vmnx,vmxx = df[varn].astype(float).min(),df[varn].astype(float).max()
dfin,history_i = lstm_training(dfin,lstmws,0,2051-2018)

在我的第一个版本中,我每次在附加新预测后都会重新训练模型,并且预测从未收敛。但因为每次新观察后进行训练非常耗时,所以我必须做出改变。

我的结果:

dfin.VALS.values
array([  1341.9       ,   1966.95      ,   2085.75      ,   2087.1       ,
     2760.75      ,   3461.4       ,   3156.3       ,   3061.8       ,
     2309.85      ,   2320.65      ,   2535.3       ,   2964.6       ,
     2949.75      ,   2339.55      ,   2327.4       ,   2571.75      ,
     2299.05      ,   1560.6       ,   1370.25      ,   1301.4       ,
     1215.        ,   5691.6       ,   6281.55      ,   6529.95      ,
    17666.1       ,  14467.95      ,  15205.05      ,  14717.7       ,
    14426.1       ,  12946.5       ,  13000.5       ,  12761.55      ,
    13076.1       ,  13444.65      ,  13444.65      ,  13321.8       ,
    13536.45      ,  13331.25      ,  12630.6       ,  12741.3       ,
    12658.95      ,  10345.97167969,  12192.12792969,  13074.4296875 ,
    13264.40917969,  12956.1796875 ,  12354.1953125 ,  11659.03125   ,
    11044.06933594,  10643.19921875,  10552.52246094,  10552.52246094,
    10552.52246094,  10552.52246094,  10552.52246094,  10552.52246094,
    10552.52246094,  10552.52246094,  10552.52246094,  10552.52246094,
    10552.52246094,  10552.52246094,  10552.52246094,  10552.52246094,
    10552.52246094,  10552.52246094,  10552.52246094,  10552.52246094,
    10552.52246094,  10552.52246094,  10552.52246094,  10552.52246094,
    10552.52246094,  10552.52246094])

我怎样才能避免在过去 20 多年里得到相同的预测?

EDIT:

我预先添加了更多随机数据,看看是否是因为样本量太小,但一段时间后预测又保持不变。

df0 = pd.DataFrame([range(1900,1979),list(np.random.rand(1979-1900)*(vmxx-vmnx)+vmnx)],index=["FISCAL_YEAR","VALS"]).T
df = pd.concat([df0,df])
df["FISCAL_YEAR"] = df["FISCAL_YEAR"].astype(int)
df.index = range(1900,2020)

我观察到的一件奇怪的事情是,10 年后的预测(即窗口大小)是相同的,但如果我将 lstmws 增加到 20,则预测会在 20 年后收敛:

lstmws = 20

Result:

{'FISCAL_YEAR': [2020,  2021,  2022,  2023,  2024,  2025,  2026,  027,  028,  2029,  2030,  2031,  2032,  2033,  2034,  2035,  2036,  2037,  2038,  039,  2040,  2041,  2042,  2043,  2044,  2045,  2046,  2047,  2048,  2049,  050,  2051,  2052],
 'VALS': [11183.32421875,  12388.28125,  13151.013671875,  12543.6796875,  2590.0888671875,  12002.583984375,  11822.8857421875,  11479.6572265625,  1423.1279296875,  11444.5751953125,  11506.60546875,  11563.3173828125,  1595.0029296875,  11599.8955078125,  11586.8037109375,  11571.337890625,  1574.541015625,  11620.7900390625,  11734.2431640625,  11934.216796875,  1934.216796875,  11934.216796875,  11934.216796875,  11934.216796875,  1934.216796875,  11934.216796875,  11934.216796875,  11934.216796875,  1934.216796875,  11934.216796875,  11934.216796875,  11934.216796875,  1934.216796875]}

根据我使用 LSTM 的经验(我一直在生成舞蹈序列,例如this https://bl.ocks.org/duhaime/b035d551d816a608a58c3ea4f464891e),我发现有两件事特别有助于防止模型停滞并预测相同的输出。

添加混合密度层

首先,使用混合密度网络而不是 L2 损失(如您所用)会很有帮助。阅读克里斯托弗·毕晓普的著作MDN 层论文 https://publications.aston.ac.uk/373/1/NCRG_94_004.pdf详细信息,但基本上 L2 损失试图将某些输入的误差项的条件平均值预测为 y。如果对于一个值 x,您有多个可能的输出 y0、y1、y2,每个输出都有一定的概率(许多复杂系统都会如此),您将需要考虑 MDN 层和负对数似然损失。Here https://github.com/omimo/Keras-MDN是我正在使用的 Keras 实现。

现在更仔细地阅读您的情况,这可能对您的情况没有帮助,因为您似乎在预测一个时间序列,根据定义,每个 x 映射到单个 y。

向 LSTM 提供更长的序列

接下来,我发现喂养我的 LSTM 很有帮助n序列值先于我试图预测的序列值。 n 越大,我发现的结果就越好(尽管训练速度较慢)。我读过的许多论文都使用 1024 个先验序列值来预测下一个序列值。

您没有太多观察结果,但您可以尝试输入前 8 个观察结果来预测下一个观察结果。

确保输出数据与训练数据具有相同的结构

最后,几年后我来到这里,因为我正在训练一个具有分类交叉熵损失和一个热向量作为输入的模型。当我用训练好的模型生成序列时,我使用了:

# this predicts the same value over and over
predict_length = 100
sequence = X[0]
for i in range(predict_length):
  # note that z is a dense vector -- it needs to be converted to one hot!
  z = model.predict( np.expand_dims( sequence[-sequence_length:], 0 ) )
  sequence = np.vstack([sequence, z])

我应该将我的输出预测转换为一个热向量:

# this predicts new values :)
predict_length = 1000
sequence = X[0]
for i in range(predict_length):
  # z is still a dense vector; we'll convert it to one-hot below
  z = model.predict( np.expand_dims( sequence[-sequence_length:], 0 ) ).squeeze()
  # let's convert z to a one hot vector to match the training data
  prediction = np.zeros(len(types),)
  prediction[ np.argmax(z) ] = 1
  sequence = np.vstack([sequence, prediction])

我怀疑这最后一步是大多数人最终会看到这个帖子的原因!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LSTM - 一段时间后预测相同的常数值 的相关文章

  • 在numpy中,[:,None]选择有什么作用?

    我正在学习 Udacity 的深度学习课程 我遇到了以下代码 def reformat dataset labels dataset dataset reshape 1 image size image size astype np flo
  • 如何选择单选按钮?

    我在用mechanize我正在尝试从单选按钮列表中选择一个按钮 该列表有 5 项 如何选择第一项 文档没有帮助我 gt gt gt br form
  • OpenPyXL - 如何查询单元格边框?

    python 和 openpyxl 都是新的 编写一个 py 脚本来遍历大量 Excel 工作簿 工作表 并且需要找到由边框格式标识的某些单元格 我在网上看到几个关于如何设置单元格边框的示例 但我需要阅读它们 具体来说 当表内的数据不一致但
  • pandas 系列值之间的过滤

    If s is a pandas Series http pandas pydata org pandas docs stable dsintro html series 我知道我可以这样做 b s lt 4 or b s gt 0 但我做
  • 使用Python选择屏幕区域

    我正在用 Python 开发一个屏幕截图实用程序 目前它是专门针对 Linux 的 到目前为止 我已经能够拍摄完整桌面的屏幕截图 并将其上传到 Imgur 然后将链接复制到剪贴板 现在我想扩展到诸如活动窗口或特定选择的屏幕截图之类的功能 如
  • 我应该将Python的pyc文件添加到.dockerignore吗?

    我见过几个例子 dockerignorePython 项目的文件 其中 pyc文件和 或 pycache 文件夹被忽略 pycache pyc 由于无论如何这些文件 文件夹都会在容器中重新创建 我想知道这样做是否是一个好习惯 是的 这是一个
  • Python 2.7从非默认目录打开多个文件(对于opencv)

    我在 64 位 win7 上使用 python 2 7 并拥有 opencv 2 4 x 当我写 cv2 imread pic 时 它会在我的默认 python 路径中打开 pic 即C Users Myname 但是我如何设法浏览不同的目
  • Pandas系列矢量化文本处理

    我想使用矢量化操作改进我的 Pandas 代码 假设我有一个简单的 DataFrame 其中有一个文本列 其中可能包含 url Column1 0 hello http www google com 1 bye www mail com w
  • 如何使用列表理解从列表中删除重复的项目? [复制]

    这个问题在这里已经有答案了 如何使用列表理解从列表中删除重复的项目 我有以下代码 a 1 2 3 3 5 9 6 2 8 5 2 3 5 7 3 5 8 b b item for item in a if item not in b 但它不
  • 如何获取一个类的所有实例

    我是一名初学者 正在学习 Python 我想创建一个课程Person 在构造函数中 我想将我创建的每个实例放入一个名为 实例 的集合中 然后我希望实例 方法返回所有实例 我怎样才能做到这一点 class Person Type annota
  • 使用 Python 将 Json 转换为换行 Json 标准

    我有一个获取嵌套对象并删除所有嵌套的代码 使对象平坦 def flatten json y param y Unflated Json return Flated Json out def flatten x name if type x
  • 使用字符串迭代 url - python

    我现在完全被我的代码困住了 首先 我尝试从 volkskrant 的存档页面检索所有网址 这是我被打击的第一步 某一特定日期的 url 如下所示 http www volkskrant nl archief detail 01012016
  • 将多个 csv 文件连接成具有相同标头的单个 csv

    我目前正在使用以下代码导入 6 000 个 csv 文件 带标题 并将它们导出到单个 csv 文件 带单个标题行 import csv files from folder path r data US market merged data
  • Python 结构的 PHP 替代品

    我很高兴在我的 Python 项目中使用 Fabric 进行部署 现在我正在从事一个更大的 PHP 项目 想知道是否有类似 PHP 的 Fabric 之类的东西 唔 为什么这有关系 Fabric 只是 python 脚本 所以它与项目语言无
  • 在 Django 中删除特定用户的所有会话的最优化方法?

    我正在运行 Django 1 3 使用会话中间件和身份验证中间件 settings py SESSION ENGINE django contrib sessions backends db Persist sessions to DB S
  • 如何导入 boto3 ssm ParameterNotFound 异常?

    我想import the exception当一个boto3 ssm找不到参数get parameter 我正在尝试添加一些额外的内容ssm的功能moto图书馆 但我现在很困惑 gt gt gt import boto3 gt gt gt
  • 在绘图中的线间隙之间添加注释

    I have a graph like this 而不是在上面的日子symbol 我想知道是否有办法可以在行之间添加此注释 从一个点到另一个点 如果以防万一 这可能是重复的 我深表歉意 This is my expected output
  • python nltk从句子中提取关键字

    我们要做的第一件事 就是杀掉所有律师 威廉 莎士比亚 鉴于上面的引用 我想退出 kill and lawyers 作为两个突出的关键词来描述句子的整体含义 我提取了以下名词 动词 POS 标签 First NNP thing NN do V
  • Python DNS服务器IP地址查询

    我正在尝试使用 python 获取 DNS 服务器 IP 地址 要在 Windows 命令提示符下执行此操作 我将使用 ipconfig 全部 如下所示 我想使用 python 脚本做同样的事情 有什么方法可以提取这些值吗 我成功提取了设备
  • 我可以在某些网格中打印带有颜色的 pandas 数据框吗?

    我有一个 pandas DataFrame 我想突出显示一些数据 例如 In 1 import pandas as pd In 2 import numpy as np In 3 df pd DataFrame np reshape ran

随机推荐