我正试图根据之前的50个输入来预测5种加密货币的定期价格。
>>> X_train.shape, X_test.shape, Y_train.shape, Y_test.shape
((291314, 50, 8), (72829, 50, 8), (291314, 5), (72829, 5))
这里我有50个以前的样本x 8个特征作为输入样本,接下来5个时段的价格作为输出
我已使用以下代码构建模型:
from tensorflow.keras.layers import GRU
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation
model = Sequential()
model.add(GRU(units=50, input_shape=X_train.shape[1:], return_sequences=False))
model.add(Activation('tanh'))
model.add(Dropout(0.2))
model.add(Dense(NFS))
model.add(Activation('relu'))
model.compile(loss='mse', optimizer='adam')
model.fit(X_train, Y_train, batch_size=50, validation_data=(X_test, Y_test), epochs=2)
那给了我输出:
Train on 291314 samples, validate on 72829 samples
Epoch 1/2
291314/291314 [==============================] - 487s 2ms/step - loss: 0.0107 - val_loss: 0.2502
Epoch 2/2
291314/291314 [==============================] - 463 2ms/step - loss: 0.0103 - val_loss: 0.2502
在此步骤之后,我尝试预测X_test的输出,但没有预测,而是得到了形状正确但充满零的矩阵,而不是任何预测:
>>> model.predict(X_test)
array([[-0., -0., -0., -0., -0.],
[-0., -0., -0., -0., -0.],
[-0., -0., -0., -0., -0.],
...,
[-0., -0., -0., -0., -0.],
[-0., -0., -0., -0., -0.],
[-0., -0., -0., -0., -0.]], dtype=float32)
为什么我变得如此糟糕?我是否使用正确的方式做我想做的事?
UPD :Here是完整的笔记本。
答案 0 :(得分:3)
首先,您需要扩展测试(X_test
)输入。您确实确实缩放了训练数据(X_train
),但没有扩展测试集。
因此,您需要像使用X_train
一样进行缩放:
X_test = preprocessing.MinMaxScaler().fit_transform(X_test.reshape(-1, 50*8)).reshape(-1, 50, 8)
在输出层中进一步使用'ReLU'
激活是有问题的。因为即使最后一层权重产生负输出,您也始终会得到正输出。
这里的问题是,由于损失非常低,负输出的权重不会更新得太多。
假设您的权重设置导致输出-23435235
,而目标是0.9
。在输出上使用'ReLU'
激活时,它会从-23435235
映射到0
,这会导致低损耗。但是低损失意味着更少的变化,而高损失则意味着体重的巨大变化。
因此,您想要很高的损失才能对自己的体重进行强有力的纠正。因为-23435235
不是您想要的。
所以不要在最后一层使用'ReLU'
,我在这里更改为'linear'
。
这样说(我将'tanh'
更改为'ReLU'
,然后)代码:
#somewhere before you need to normalize your `X_test`
X_test = preprocessing.MinMaxScaler().fit_transform(X_test.reshape(-1, 50*8)).reshape(-1, 50, 8)
from tensorflow.keras.layers import GRU
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation
model = Sequential()
model.add(GRU(units=50, input_shape=X_train.shape[1:], return_sequences=False))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(NFS))
model.add(Activation('linear'))
model.compile(loss='mse', optimizer='adam')
model.fit(X_train, Y_train, batch_size=4000, validation_data=(X_test, Y_test), epochs=15)
输出:
Train on 291314 samples, validate on 72829 samples
Epoch 1/15
291314/291314 [==============================] - 22s 75us/step - loss: 0.1523 - val_loss: 0.2442
Epoch 2/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0652 - val_loss: 0.2375
Epoch 3/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0420 - val_loss: 0.2316
Epoch 4/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0337 - val_loss: 0.2262
Epoch 5/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0271 - val_loss: 0.2272
Epoch 6/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0219 - val_loss: 0.2256
Epoch 7/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0179 - val_loss: 0.2245
Epoch 8/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0149 - val_loss: 0.2246
Epoch 9/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0125 - val_loss: 0.2244
Epoch 10/15
291314/291314 [==============================] - 16s 57us/step - loss: 0.0108 - val_loss: 0.2213
Epoch 11/15
291314/291314 [==============================] - 16s 57us/step - loss: 0.0096 - val_loss: 0.2197
Epoch 12/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0087 - val_loss: 0.2189
Epoch 13/15
291314/291314 [==============================] - 16s 57us/step - loss: 0.0080 - val_loss: 0.2178
Epoch 14/15
291314/291314 [==============================] - 16s 56us/step - loss: 0.0075 - val_loss: 0.2148
Epoch 15/15
291314/291314 [==============================] - 16s 57us/step - loss: 0.0072 - val_loss: 0.2129
<tensorflow.python.keras.callbacks.History at 0x7f8a93637b70>
另外X_test
个结果:
代码:
prediction = model.predict(X_test[:10])
prediction
输出:
array([[0.03562379, 0.06016447, 0.0987532 , 0.01986726, 0.0336756 ],
[0.03518523, 0.06041833, 0.0983481 , 0.01864071, 0.03437094],
[0.03487844, 0.06067847, 0.09811568, 0.0175517 , 0.03480709],
[0.03491565, 0.05986937, 0.09927133, 0.02029082, 0.03347992],
[0.03466946, 0.06018706, 0.09859383, 0.01869587, 0.03432 ],
[0.03459518, 0.06030918, 0.09850594, 0.01805007, 0.03444977],
[0.03448001, 0.06019764, 0.09864715, 0.01818896, 0.034256 ],
[0.03450274, 0.05936757, 0.10001318, 0.02131432, 0.03305689],
[0.03424717, 0.05954869, 0.09983289, 0.0208826 , 0.03378636],
[0.03426195, 0.05959999, 0.09991242, 0.02090426, 0.03394405]],
dtype=float32)
我如上所述使用了您的笔记本和数据来训练模型。
如您所见,在第15个阶段,验证损失仍在减少,并且测试输出现在看起来也很接近目标。
另外一个注意事项-我没有在笔记本中完成所有预处理代码,但是在我看来,您正在使用绝对值。
如果是这种情况,则应考虑改用百分比变化(例如,从当前时间点到将来的预测点)。这也会为您进行缩放。 (10%的变化= 0.1)
其他绝对值的确变化太大。如果十个月前的价格为~5.4324
,而今天的价格为~50.5534
,则这些数据对您没有用,而价格变化的相对模式可能仍然有效。
这只是一个旁注-希望对您有所帮助。
答案 1 :(得分:1)
嗯,我认为@ blue-phoenox的答案中建议的规范化方案是有缺陷的。这是因为您应该从不永远独立地标准化测试数据(即使用不同的统计信息)。相反,您应该使用在训练数据归一化期间计算出的统计数据来归一化测试数据。所以它一定是这样的:
mms = preprocessing.MinMaxScaler()
X_train = mms.fit_transform(X_train)
X_test = mms.transform(X_test) # you should not use fit_transform
这是有道理的,因为考虑以下情况,您已经训练了模型并将其部署到生产中以供实际使用。现在,用户用一个新样本来喂食它。您需要首先规范化这个新样本,但是如何?您不能单独缩放其值,因为它只是一个样本(即,如果使用最小-最大缩放器,则所有这些值将为1或0)。相反,您将使用(在使用最小-最大缩放器的情况下)在训练数据上计算出的“最小”和“最大”值来标准化此新测试数据。
这在图像模型中非常常见,例如:
X_train /= 255.
X_test /= 255.
请注意,我们将训练数据和测试数据除以相同的数字(即255)。或更复杂的标准化方案:
X_mean = X_train.mean(axis=0)
X_std = X_train.std(axis=0)
X_train -= X_mean
X_train /= X_std + 1e-8 # add a small constant to prevent division by zero
# Now to normalize test data we use the same X_mean and X_std already computed
X_test -= X_mean
X_test /= X_std + 1e-8
旁注(如我在my comment中所述):如果您在GPU上运行训练,则可以考虑使用CuDNNGRU
而不是GRU
(或CuDNNLSTM
而不是LSTM
),因为它专门针对GPU优化并加快了训练过程。
答案 2 :(得分:0)
对于任何有相同输出错误并且甚至现在仍在搜索此错误的人,要扩展@MBT提供的出色答案,您还可以尝试Leaky ReLU作为激活。
只需将model.add(Activation("relu"
更改为model.add(LeakyReLU(alpha=[enter alpha, default is 0.3]))
,并确保更改为from keras.layers.advanced_activations import LeakyReLU
。
我在这里找到了此解决方案:https://github.com/keras-team/keras/issues/3687