Python LSTM/GRU时间序列多输出策略预测给出下降值

Python LSTM/GRU时间序列多输出策略预测给出下降值,python,tensorflow,keras,lstm,recurrent-neural-network,Python,Tensorflow,Keras,Lstm,Recurrent Neural Network,目前,我正在玩股票预测任务,我试图用LSTM/GRU解决这个任务 问题:在训练LSTM/GRU后,我得到的预测值大幅下降 模型培训流程 训练、测试数据只需使用pd.shift串联\u至\u监督功能生成。 df['Mid']=df['Low']+df['High']/2 n_lag=1#向后滞后列 n_seq=1*50#预测时间步 seq_col='中间' seq_col_t=f'{seq_col}(t)' 拆分日期='2018-01-01' def系列_至_受监控(数据:pd.DataFr

目前,我正在玩股票预测任务,我试图用LSTM/GRU解决这个任务

问题:在训练LSTM/GRU后,我得到的预测值大幅下降

模型培训流程

训练、测试数据只需使用
pd.shift
串联\u至\u监督功能生成。

df['Mid']=df['Low']+df['High']/2
n_lag=1#向后滞后列
n_seq=1*50#预测时间步
seq_col='中间'
seq_col_t=f'{seq_col}(t)'
拆分日期='2018-01-01'
def系列_至_受监控(数据:pd.DataFrame,
序号:str,
n_in:int=1,
n_out:int=1,
drop_seq_col:bool=True,
dropna:bool=True):
“”“将时间序列转换为监督学习问题
{输入序列,预测序列}
"""
#输入序列(t-n,…t-1)->初始移位
对于范围内的i(n_in,0,-1):
数据[f'{seq_col}(t-{i})]=data[seq_col].shift(i)
#无顺序->无移位
数据[f'{seq_col}(t)]=数据[seq_col]
对于范围内的i(1,n_out+1):
#预测序列(t,t+1,…t+n)->负偏移
数据[f'{seq_col}(t+{i})]=data[seq_col].shift(-i)
如果删除顺序列:
数据=数据下降(顺序列,轴=1)
如果是dropna:
data.dropna(inplace=True)
返回数据
df=序列到监督序列(df,序列列=序列列,n列输入=n列滞后,n列输出=n列)
掩码=df.index<拆分日期
列车,测试=测向[遮罩],测向[~遮罩]
X_cols=['Mid(t-1)']
y_cols=train.filter(比如class='Mid(t+')。列
X列,y列,X列测试,y列测试=列[X列],列[y列],测试[X列],测试[y列]
从sklearn.preprocessing导入MinMaxScaler
scaler=MinMaxScaler(特征值范围=(-1,1))
#还返回np.ndarray
X_序列=缩放器。拟合变换(X_序列)
X_测试=缩放器.拟合变换(X_测试)
y_列=y_列值
y_测试=y_测试值
从keras.models导入顺序
从keras.layers导入稠密、脱落、LSTM、GRU
从keras.optimizers导入Adam、RMSprop和Adamax
从keras.callbacks导入模型检查点
def get_型号(X、y、n_批次):
num_classes=y.shape[1]
#设计网络
模型=顺序()
#对于库存预测,必须使用LSTM stateful=True
model.add(GRU(10,batch\u input\u shape=(n\u batch,X.shape[1],X.shape[2]),stateful=True))
模型。添加(辍学(0.3))
添加模型(密集(num_类))
opt=Adam(学习率=0.01)
#opt=RMSprop(学习率=0.001)
compile(loss='mean_squared_error',optimizer=opt)
回归模型
def重塑_批次(X_系列、y_系列、X_测试、y_测试、n_批次):
#将培训重塑为[样本、时间步、特征]
X_-train=X_-train.shape重塑(X_-train.shape[0],1,X_-train.shape[1])
X_测试=X_测试。重塑(X_测试。形状[0],1,X_测试。形状[1])
#切割成等分n_批次(无需提醒)。
#LSTM stateful需要=True
系列切割=X系列形状[0]%n\u批次
测试切割=X测试形状[0]%n\u批次
如果列车切割>0:
X_列=X_列[:-列切]
y_列=y_列[:-列切]
如果测试切割>0:
X_测试=X_测试[:-测试切]
y_测试=y_测试[:-测试切]
返回X_列,y_列,X_测试,y_测试
#将LSTM网络与训练数据相匹配
def fit_lstm(X_列:np.ndarray,
y_列车:np.ndarray,
n_lag:int,
序号:整数,
n_批次:int,
新纪元:int,,
X_检验:np.ndarray=无,
y_检验:np.ndarray=None):
模型=获取模型(X\U系列、y\U系列、n\U批次)
#拟合网络
历史=模型.fit(X_序列,y_序列,验证数据=(X_测试,y_测试),回调=无,
epochs=nb\u epoch,batch\u size=n\u batch,verbose=1,shuffle=False)
打印('Predict:',model.Predict(X_测试,批次大小=n_批次))
model.reset_states()
回归模型、历史
n_批次=32
nb_epoch=40
X_系列,y_系列,X_测试,y_测试=重塑_批次(X_系列,y_系列,X_测试,y_测试,n_批次)
模型,历史=拟合(X_序列,y_序列,n_滞后,n_序列,n_批次,nb_历元,X_测试=X_测试,y_测试=y_测试)
我尝试过的

  • 不同的优化器(keras中几乎都有)
  • 不同的循环网络结构(GRU/LSTM)
  • 不同的学习率
  • 从1世纪到1500年的不同时期
  • 添加/删除具有不同参数(0.1-0.7)的放置层
  • 不同LSTM/GRU神经元数量(1-100)
  • LSTM/GRU层的数量,通过具有更多放置层的返回序列参数
  • 不同数量的预测(t+1、t+2…t+n)功能从1到365
  • 不同数量的滞后(t-1、t-2、t-n…)特征从1到5
  • 不同的比例规格化边界(0,1)和(-1,1)
  • 不同的n_批次值:1,8,16,32

    什么会影响LSTM/GRU给出如此奇怪的行为?我还应该尝试什么使其正常工作


  • X_train的‘特征’(最后一个维度)是你系列的滞后……我理解正确了吗?@Marco Cerliani Hello;)。目前中等价格为(t)。特征-使用“负移位”获得,这给了我们(t+n)。滞后-使用“正位移”得到相反的结果,该位移给出了(t-n)。你可以轻松地看这里,故意理解所有的东西。好的,您正在连接最后一个维度上的shift变量。。。这不是rnn的常见场景。我向你推荐这个@Marco Cerliani,谢谢你的建议,我会在解决它之后尝试,并给你答案。X_系列的“特征”(最后尺寸)是你系列的滞后。。。我理解对了吗?@Marco Cerliani你好;)。目前中等价格为(t)。特征-使用“负移位”获得,这给了我们(t+n)。滞后-使用“正位移”得到相反的结果,该位移给出了(t-n)。你可以轻松地看看这里
    df['Mid'] = df['Low'] + df['High'] / 2
    
    n_lag = 1 # Lag columns back
    n_seq = 1*50 # TimeSteps to predict
    seq_col = 'Mid'
    seq_col_t = f'{seq_col}(t)'
    split_date = '2018-01-01'
    
    
    def series_to_supervised(data: pd.DataFrame, 
                             seq_col: str, 
                             n_in: int = 1, 
                             n_out: int = 1, 
                             drop_seq_col: bool = True, 
                             dropna: bool = True):
        """Convert time series into supervised learning problem 
            {input sequence, forecast sequence}
        """
        # input sequence (t-n, ... t-1) -> pisitive shift
        for i in range(n_in, 0, -1):
            data[f'{seq_col}(t-{i})'] = data[seq_col].shift(i)
        # no sequence -> no shift
        data[f'{seq_col}(t)'] = data[seq_col]
        for i in range(1, n_out+1):
            # forecast sequence (t, t+1, ... t+n) -> negative shift
            data[f'{seq_col}(t+{i})'] = data[seq_col].shift(-i)
        if drop_seq_col:
            data = data.drop(seq_col, axis=1)
        if dropna:
            data.dropna(inplace=True) 
        return data
    
    df = series_to_supervised(df, seq_col=seq_col, n_in=n_lag, n_out=n_seq)
    
    mask = df.index < split_date
    train, test = df[mask], df[~mask]
    
    X_cols = ['Mid(t-1)']
    y_cols = train.filter(like='Mid(t+').columns
    
    X_train, y_train, X_test, y_test = train[X_cols], train[y_cols], test[X_cols], test[y_cols]
    
    from sklearn.preprocessing import MinMaxScaler
    scaler = MinMaxScaler(feature_range=(-1, 1))
    
    # also returns np.ndarray
    X_train = scaler.fit_transform(X_train)
    X_test = scaler.fit_transform(X_test)
    y_train = y_train.values
    y_test = y_test.values
    
    from keras.models import Sequential
    from keras.layers import Dense, Dropout, LSTM, GRU
    from keras.optimizers import Adam, RMSprop, Adamax
    from keras.callbacks import ModelCheckpoint
    
    def get_model(X, y, n_batch):
        num_classes=y.shape[1]
        # design network
        model = Sequential()
        # For Stock Predictions has to be used LSTM stateful=True
        model.add(GRU(10, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True))
        model.add(Dropout(0.3))
        model.add(Dense(num_classes))
        opt = Adam(learning_rate=0.01)
        # opt = RMSprop(learning_rate=0.001)
        model.compile(loss='mean_squared_error', optimizer=opt)
        return model
    
    def reshape_batch(X_train, y_train, X_test, y_test, n_batch):
        # reshape training into [samples, timesteps, features]
        X_train = X_train.reshape(X_train.shape[0], 1, X_train.shape[1])
        X_test = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])
    
        # cut to equally divided n_batches (without reminder). 
        # needed for LSTM stateful=True
        train_cut = X_train.shape[0] % n_batch
        test_cut = X_test.shape[0] % n_batch
    
        if train_cut > 0:
            X_train = X_train[:-train_cut]
            y_train = y_train[:-train_cut]
    
        if test_cut > 0:
            X_test = X_test[:-test_cut]
            y_test = y_test[:-test_cut]
    
        return X_train, y_train, X_test, y_test
    
    # fit an LSTM network to training data
    def fit_lstm(X_train: np.ndarray, 
                 y_train: np.ndarray, 
                 n_lag: int,
                 n_seq: int, 
                 n_batch: int, 
                 nb_epoch: int, 
                 X_test: np.ndarray=None, 
                 y_test: np.ndarray=None):
    
        model = get_model(X_train, y_train, n_batch)
        # fit network    
        history = model.fit(X_train, y_train, validation_data=(X_test, y_test), callbacks=None,
                            epochs=nb_epoch, batch_size=n_batch, verbose=1, shuffle=False)
        print('Predict:', model.predict(X_test, batch_size=n_batch))
        model.reset_states()
        return model, history
    
    n_batch = 32
    nb_epoch = 40
    
    X_train, y_train, X_test, y_test = reshape_batch(X_train, y_train, X_test, y_test, n_batch)
    model, history = fit_lstm(X_train, y_train, n_lag, n_seq, n_batch, nb_epoch, X_test=X_test, y_test=y_test)