【问题标题】:Multilayer perceptron in Keras weird predictionKeras 奇怪预测中的多层感知器
【发布时间】:2018-10-05 18:53:27
【问题描述】:

我在 R 中使用 Keras 来预测金融序列。我需要用 2 个隐藏层训练 MLP,每个隐藏层有 40 个神经元来预测股票价格。目标数据由股票价格组成,训练数据由该价格的四个滞后组成。

input_data 看起来像:

               price_lag_4 price_lag_3 price_lag_2 price_lag_1  price
    2018-04-13      157.73      161.21      160.28      162.21 161.37
    2018-04-16      161.21      160.28      162.21      161.37 162.60
    2018-04-17      160.28      162.21      161.37      162.60 166.10
    2018-04-18      162.21      161.37      162.60      166.10 166.44
    2018-04-19      161.37      162.60      166.10      166.44 164.91
    2018-04-20      162.60      166.10      166.44      164.91 162.30

我进一步将数据分为训练集和目标集

    train_data = input_data["2014::2017",1:4]
    train_targets = input_data["2014::2017",5]

并使用最小-最大归一化对其进行归一化

    train_data = as.matrix(train_data)
    train_targets = as.matrix(train_targets)

    train_data = (train_data - min(train_data)) / (max(train_data) - 
    min(train_data))
    train_targets = (train_targets - min(train_targets)) / 
    (max(train_targets) - min(train_targets))

然后我构造了 MLP,输入层有 4 个神经元,2 个隐藏层,每个隐藏层有 40 个神经元,输出层有一个神经元。然后我适合它:

    validation_split = 0.05
    model = keras_model_sequential() %>%

    layer_dense(units = 40, activation = "relu", input_shape = 
    dim(train_data)[2]) %>%
    layer_dense(units = 40, activation = "relu") %>%  
    layer_dense(units = 1, activation = "relu")

    model %>% compile(optimizer = optimizer_sgd(), loss = "mse", metrics = 
    c("mae"))

    fit(x = train_data, y = train_targets, epochs = 60, batch_size = 32, 
    validation_split = validation_split)

拟合已经收敛:

Trained on 956 samples, validated on 51 samples (batch_size=32, epochs=60)
Final epoch (plot to see history):
           val_loss: 0.0004162
val_mean_absolute_error: 0.0159
               loss: 0.0002706
mean_absolute_error: 0.01215

进一步预测我在 2018 年使用的价格

validation_data = input_data["2018",1:4]
tail(validation_data)
           price_lag_4 price_lag_3 price_lag_2 price_lag_1
2018-04-13      157.73      161.21      160.28      162.21
2018-04-16      161.21      160.28      162.21      161.37
2018-04-17      160.28      162.21      161.37      162.60
2018-04-18      162.21      161.37      162.60      166.10
2018-04-19      161.37      162.60      166.10      166.44
2018-04-20      162.60      166.10      166.44      164.91

prediction_sgd = predict(object = model, x = validation_data)

tail(prediction_sgd)
          [,1]
[71,] 147.2574
[72,] 148.6506
[73,] 148.6407
[74,] 149.8874
[75,] 150.8464
[76,] 151.8221

预测在某种程度上接近价格

validation_targets = prices["2018"]
tail(validation_targets)
         [,1]
2018-04-13 161.37
2018-04-16 162.60
2018-04-17 166.10
2018-04-18 166.44
2018-04-19 164.91
2018-04-20 162.30

所以,这个 MLP 架构以某种方式工作,但是当我将激活函数更改为 tanh 时,模型变为:

   validation_split = 0.05
   model = keras_model_sequential() %>%

   layer_dense(units = 40, activation = "tanh", input_shape = 
   dim(train_data)[2]) %>%
   layer_dense(units = 40, activation = "tanh") %>%  
   layer_dense(units = 1)

   model %>% compile(optimizer = optimizer_sgd(), loss = "mse", metrics = 
   c("mae"))

   history = model %>% fit(x = train_data, y = train_targets, epochs = 60, 
   batch_size = 32, validation_split = validation_split)

   Trained on 956 samples, validated on 51 samples (batch_size=32, 
   epochs=60)
   Final epoch (plot to see history):
                  val_loss: 0.0306
   val_mean_absolute_error: 0.1728
                    loss: 0.001923
       mean_absolute_error: 0.0343

我得到了奇怪的预测:

    prediction_sgd = predict(object = model, x = validation_data)
    tail(prediction_sgd)
               [,1]
    [71,] 0.9751762
    [72,] 0.9749264
    [73,] 0.9750333
    [74,] 0.9750219
    [75,] 0.9747972
    [76,] 0.9749493

当我使用sigmoid 传递函数时,我也会得到奇怪的预测

因此,我有以下问题:

1) 为什么第二种情况下的预测数据如此奇怪?我做错了吗?

2) 是否需要对目标数据进行归一化,即yfit 函数中输入?

【问题讨论】:

    标签: r deep-learning keras time-series forecasting


    【解决方案1】:

    问题在于 tanh 和 sigmoid 的输出范围分别为 [-1, 1] 和 [0, 1]。因此,如果 y 不在该范围内,则网络无法学习,因为它无法预测这些值。它会尝试尽可能高地预测网络,但这只是 1。

    因此,您需要使用一个函数作为最终激活,该函数能够在您想要的输出范围内产生值,例如线性激活或 ReLU。不过这不适用于中间层。

    【讨论】:

    • 我已经尝试制作最后一层layer_dense(units = 1),默认激活是线性的并且 layer_dense(units = 1, activation = "relu")。预测值接近 1.3 或 1.4,所以这不起作用
    猜你喜欢
    • 2014-08-11
    • 2017-06-25
    • 2017-06-28
    • 1970-01-01
    • 2017-04-12
    • 2021-01-29
    • 2019-09-28
    • 2015-08-14
    • 2017-07-03
    相关资源
    最近更新 更多