我正在时间序列上训练 RNN。我对 RNNCell
进行了子类化,并在 dynamic_rnn
中使用它。 RNNCell
的拓扑结构如下:
- 输入(形状
[15, 100, 3]
) - 1x3 卷积(5 个内核)、ReLu(形状
[15, 98, 5]
) - 1x(剩余)卷积(20 个内核),ReLu(形状
[15, 1, 20]
) - 连接之前的输出(形状
[15, 1, 21]
) - 挤压和 1x1 卷积(1 个内核)、ReLu(形状
[15, 1]
) - 挤压和softmax(形状
[15]
)
dynamic_rnn
的批量大小约为 100(与上面描述的 100 不同,它是数据窗口中的时间段数)。 Epoch 由大约 200 个批处理组成。
我想尝试超参数和正则化,但我尝试的很多时候会完全停止学习,我不明白为什么。这些是发生的一些奇怪的事情:
Adagrad 可以工作,但如果我使用 Adam 或 Nadam,梯度全部为零。
我被迫设置一个巨大的学习率(~1.0)来观察从一个时代到另一个时代的学习。
如果我尝试在任何卷积后添加 dropout,即使我将 keep_prob 设置为 1.0,它也会停止学习。
如果我调整卷积中的内核数量,对于某些看起来同样好的选择(例如 5、25、1 与 5、20、1),网络将再次完全停止学习。
为什么这个模型如此脆弱?是RNNCell
的拓扑吗?
编辑:
这是RNNCell
的代码:
class RNNCell(tf.nn.rnn_cell.RNNCell):
def __init__(self):
super(RNNCell, self).__init__()
self._output_size = 15
self._state_size = 15
def __call__(self, X, prev_state):
network = X
# ------ 2 convolutional layers ------
network = tflearn.layers.conv_2d(network, 5, [1, 3], activation='relu', weights_init=tflearn.initializations.variance_scaling(), padding="valid", regularizer=None)
width = network.get_shape()[2]
network = tflearn.layers.conv_2d(network, 20, [1, width], [1, 1], activation='relu', weights_init=tflearn.initializations.variance_scaling(), padding="valid", regularizer=None)
# ------ concatenate the previous state ------
_, height, width, features = network.get_shape()
network = tf.reshape(network, [-1, int(height), 1, int(width * features)])
network = tf.concat([network, prev_state[..., None, None]], axis=3)
# ------ last convolution and softmax ------
network = tflearn.layers.conv_2d(network, 1, [1, 1], activation='relu', weights_init=tflearn.initializations.variance_scaling(), padding="valid", regularizer=None)
network = network[:, :, 0, 0]
predictions = tflearn.layers.core.activation(network, activation="softmax")
return predictions, predictions
@property
def output_size(self):
return self._output_size
@property
def state_size(self):
return self._state_size
最佳答案
您很可能面临梯度消失的问题。
不稳定可能是由于将 ReLU 与少量需要调整的参数结合使用而引起的。据我从描述中了解到,例如第一层中只有 1x3x5 = 15
可训练参数。如果假设初始化大约为零,那么平均 50% 的参数的梯度将始终保持为零。一般来说,小型网络上的 ReLU 是一种邪恶,特别是在 RNN 的情况下。
- 尝试使用 Leaky ReLU(但您可能会面临梯度爆炸)
- 尝试使用 tanh,但检查参数的初始值,确保它们确实在零附近,否则你的梯度也会很快消失。
- 检索未经训练但刚刚在第 0 步初始化的网络的结果。通过正确的初始化和神经网络构造,您应该得到 0.5 左右的正态分布值。如果您严格使用 1、0 或它们的混合,则您的神经网络架构是错误的。所有值严格限制为 0.5 也很糟糕。
- 考虑更稳健的方法,例如 LSTM
关于python - 如何使 TensorFlow RNN 训练更加稳健?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48484664/