【问题标题】:Trend in timeseriesdata时间序列数据趋势
【发布时间】:2021-07-15 16:06:41
【问题描述】:

我正在使用带有时间序列数据的 LSTM 层的 Keras 顺序模型来预测未来值。为此,我在某个时间点将我的数据拆分为训练和验证数据。时间序列数据有一个积极的趋势,因此我的训练数据中的平均值低于我的验证数据中的平均值,因为我使用更新的数据作为验证。

初始模型每次预测0.5,这是一个不好的模型。在下一个 epoch,模型将通过训练数据学习并预测平均低于 0.5 的值,这会减少训练损失,但会增加验证损失。 只有在很多时期之后,我才会看到验证损失开始下降,并且在更多时期之后,验证损失将首次低于第一个错误的总是预测 0.5 模型。

我将 Keras 调谐器与 Hyperband 调谐器一起用于超参数验证。这不适用于这个时间序列,因为在第一轮中,所有模型都会显示出比初始 0.5 模型更差的验证损失。

有没有办法结合 Keras 以及拆分训练和验证数据来处理时间序列中的趋势?我不可能将时间序列打乱然后拆分数据,因为我真的很想使用更新的数据进行验证。

【问题讨论】:

    标签: python tensorflow machine-learning keras


    【解决方案1】:

    查看Tensorflowthis example,他们提供的课程可让您轻松地将时间序列转变为监督学习问题(即训练和测试数据集)。

    如果您查看that same example,您还会发现一些数据转换步骤可以帮助您获得更好的模型。

    对您的数据进行编码,以便数字表示在您的输入数据中找到的关系,即如果您的列描述风向,则编码使得 360 度与 359 度的距离与 0 度的距离完全相同。他们通过乘以风速,然后获取这些列的 sin 和 cos 分量来做到这一点。时间序列数据预处理是一个广泛的主题,您可以花费大量时间来研究。

    另一个可能帮助您的模型摆脱在每一步都预测训练数据平均值的步骤是标准化:压缩 0 到 1 之间的所有值并从数据集中移除平均值。

    我不是 Keras Sequential 模型的权威,但这里有一些东西可以帮助您入门:

    这个模型至少可以预测未来 30 步的 sin 函数。

    import tensorflow as tf
    import tensorflow.keras as keras
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import LSTM
    from tensorflow.keras.layers import Activation
    from tensorflow.keras.layers import Dense
    from tensorflow.keras.layers import Dropout
    
    def make_model(x_train, y_train, print_summary = True):
                        
            model = Sequential()
            model.add(keras.Input(shape = (x_train.shape[1], x_train.shape[2])))
            
            model.add(LSTM(units = 100, return_sequences = False))
            model.add(Activation('tanh'))
            
            model.add(Dense(units = 100, activation = 'relu')
            model.add(Dropout(rate = 0.2))
            
            model.add(Dense(units = y_train.shape[1], activation = 'relu')
            
            model.compile(loss = 'mse', optimizer = keras.optimizers.Adam())
            
            if print_summary: model.summary()
            return model
    

    您应该尝试激活函数,添加归一化和 dropout。

    如果我给它这个输入:

    sin_df = pd.DataFrame(index = pd.date_range('2015-01-01 00:00:00', '2015-12-31 
    23:00:00', freq = 'H'))
    sin_df['data'] = np.float32(np.sin(range(len(sin_df))))
    

    我用这个函数把它切成样本:

    def multivariate_data(df, start_index, end_index, history_size, target_size,
                              remove_na = True, target = 0, step = 1, single_step=False):
            
            target = df[:,target]
            data = []
            labels = []
            start_index = start_index + history_size
            
            if end_index is None:
                end_index = len(df) - target_size
    
            for i in range(start_index, end_index, step):
                indices = range(i-history_size, i)
                data.append(df[indices])
    
                if single_step:
                    labels.append(target[i+target_size])
                else:
                    labels.append(target[i:i+target_size])
                
            return np.array(data), np.array(labels)
    
    train_test_split = '2015-06-01'
    train_test_index = len(self.df.loc[:train_test_split])-target_size
    
    x_train, y_train = multivariate_data(sin_df.values, 0, train_test_index-1, 100, 30)
    x_test, y_test = multivariate_data(sin_df.values, train_test_index+1, None, 100, 30)
    

    然后我可以调用 fit:

    history = model.fit(x_train, y_train,
                                            epochs          = 25, 
                                            batch_size      = 24,
                                            validation_data = (x_test, y_test),
                                            callbacks       = [],
                                            verbose         = 2,
                                            shuffle         = False)
    

    这就是我的输出 V y_test 的样子:

    predictions = model.predict(x_test)
    

    【讨论】:

    • 感谢您提供极其广泛的回答。因为这是我第一个使用 Keras 的实际项目,所以我的问题可能有点含糊。将我遇到的问题转化为您的示例时,我想预测 f=2x,而不是您的示例中的 f=sin(x)。
    • 别担心,把它写下来作为你问题的答案也有助于我的过程,大部分代码都是从我一直在研究的东西中复制粘贴的,你遇到了我大约 12 个月前遇到的同样问题。只要坚持下去,在某些时候,您的一个模型会给您一个输出,让您兴奋不已,6 个月后您将在 stackoverflow 上帮助其他人。支持我的第一个答案,以便将其移至顶部:)
    【解决方案2】:

    您可以尝试对函数进行差分,这样模型将预测每个时间步的值相对于前一个时间步的变化:

    import pandas as pd
    import numpy as np
    
    def difference_column(df, target_col):
        yesterday = df.loc[:,target_col].shift()
        return yesterday.diff()
    
    df = pd.DataFrame(range(1,100), columns = ['target_var']) * 2
    df_diff = difference_column(df, 'target_var')
    
    print(df, df_diff)
    

    输出:

        target_var
    0            2
    1            4
    2            6
    3            8
    4           10
    ..         ...
    94         190
    95         192
    96         194
    97         196
    98         198
    
    [99 rows x 1 columns] 0     NaN
    1     NaN
    2     2.0
    3     2.0
    4     2.0
         ... 
    94    2.0
    95    2.0
    96    2.0
    97    2.0
    98    2.0
    Name: target_var, Length: 99, dtype: float64
    

    在这个初步实验之后,前往here

    【讨论】:

    • 这是一个很好的解决方案。我已经将它与缩放训练数据范围内的所有数据相结合,这是我的一个朋友建议的。该模型现在似乎可以工作了,谢谢。不幸的是,我还不能为帖子投票,所以我不能投票给你的答案。
    • 你朋友的好建议! :) 建模快乐!
    猜你喜欢
    • 2020-02-05
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 2021-10-11
    • 2021-11-22
    • 2014-09-04
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多