【问题标题】:Error in reverse scaling outputs predicted by a LSTM RNNLSTM RNN 预测的反向缩放输出错误
【发布时间】:2021-08-11 10:23:18
【问题描述】:

我使用 LSTM 模型来预测股票的未来open 价格。在这里对数据进行了预处理,并且模型的构建和训练没有任何错误,我使用 Standard Scaler 来缩小 DataFrame 中的值。但是在从模型中检索预测时,当我使用 scaler.reverse() 方法时,它给出了以下错误。

ValueError: non-broadcastable output operand with shape (59,1) doesn't match the broadcast shape (59,4)

完整代码是jupyter notebook太大,无法直接展示,所以我上传到了git repository

【问题讨论】:

    标签: python tensorflow keras lstm recurrent-neural-network


    【解决方案1】:

    这是因为模型预测形状为 (59, 1) 的输出。但是您的 Scaler 适合 (251, 4) 数据框。在 y 值形状的数据框上创建一个新的缩放器,或者将模型密集层输出更改为 4 维而不是 1。 适合缩放器的数据形状,仅在 scaler.inverse_transform 期间才会采用该形状。

    旧代码 - 形状 (n,1)

    trainY.append(df_for_training_scaled[i + n_future - 1:i + n_future, 0])

    更新代码 - 形状 (n,4) - 使用所有 4 个输出

    trainY.append(df_for_training_scaled[i + n_future - 1:i + n_future,:])

    【讨论】:

    • 感谢您的帮助!这在你的电脑上有效吗?
    【解决方案2】:

    通常,您会重新调整自变量(特征),因为比例差异会影响模型计算,但您尝试预测的因变量通常不会受到影响。通常没有理由重新缩放因变量,并且缩放它会使结果非常难以解释。

    StandardScaler 类文档的第一行甚至指定了这么多:

    通过去除均值并缩放到单位方差来标准化特征

    您也可以选择缩放标签,但通常不需要这样做。

    所以我会代替你做的是(假设你的原始数据框包含 3 个自变量和 1 个目标变量)是这样的:

    X = some_df.iloc[:, :3].values
    y = some_df.iloc[3].values
    
    scaler = StandardScaler()
    X = scaler.fit_transform(X)
    # And then goes everything as usual
    

    现在,当您要预测值时,您只需使用缩放器以与以前相同的方式转换输入。

    不过,更好的方法是在模型中添加标准化层作为预处理步骤。这样,您只需将原始数据输入估算器,它就会为您处理所有细节。同样,您在生成预测时不需要对数据进行规范化,模型将为您完成所有工作。您可以添加如下内容:

    from tensorflow.keras.layers.experimental.preprocessing import Normalization
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Input, Dense
    from tensorflow.keras import Model
    
    # this is your default batch_size
    BATCH_SIZE = 128
    
    # Here's your raw (non-normalized) X data
    X = some_df.iloc[:, :3].values
    
    norm = Normalization()
    norm.adapt(X)
    preprocess = Sequential([
        Input(shape=(BATCH_SIZE, 3)),
        norm
    ])
    
    # Now finally, when you build your actual model you add 
    # pre-processing step in the beginning
    inp = preprocess()
    x = Dense(64)(input)
    x = Dense(128)(x)
    x = Dense(1)(x)  
    model = Model(inputs=inp, outputs=x) 
    

    这里的预处理步骤是模型本身的一部分,所以一旦你这样做了,你可以直接提供原始数据而无需任何额外的转换。

    这就是它的作用:

    # Skipping the imports as they are the same as above + numpy
    
    X = np.array([[1, 2, 3], [10, 20, 40], [100, 200, 400]])
    
    norm = Normalization()
    norm.adapt(X)
    preprocess = Sequential([
        Input(shape=(3, 3)),
        norm
    ]) 
    
    x_new = preprocess(X)
    print(x_new)
    
    Out: tf.Tensor(
    [[-0.80538726 -0.80538726 -0.807901  ]
     [-0.60404044 -0.60404044 -0.6012719 ]
     [ 1.4094278   1.4094278   1.4091729 ]], shape=(3, 3), dtype=float32)
    

    【讨论】:

      猜你喜欢
      • 2017-01-01
      • 2017-05-24
      • 2018-06-15
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2021-09-21
      • 2021-06-30
      • 2021-11-03
      相关资源
      最近更新 更多