如何使TensorFlow RNN训练更加健壮?

时间:2018-01-28 08:52:29

标签: python tensorflow machine-learning recurrent-neural-network

我正按时间序列训练RNN。我将RNNCell子类化,我在dynamic_rnn中使用它。 RNNCell的拓扑结构如下:

  1. 输入(形状[15, 100, 3]
  2. 1x3卷积(5个内核),ReLu(形状[15, 98, 5]
  3. 1x(剩余)卷积(20个内核),ReLu(形状[15, 1, 20]
  4. 连接上一个输出(shape [15, 1, 21]
  5. 挤压和1x1卷积(1个内核),ReLu(形状[15, 1]
  6. 挤压和softmax(形状[15]
  7. dynamic_rnn的批量大小约为100(与上述描述中的100不同,即数据窗口中的时间段数)。时代由大约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
    

1 个答案:

答案 0 :(得分:1)

很可能你正面临消失的渐变问题。

使用ReLU和少量参数进行调整可能会导致不稳定。据我所知,根据描述,例如在第一层中只有1x3x5 = 15可训练参数。如果假设初始化大约为零,则平均50%参数的梯度将始终保持为零。一般来说ReLU在一个邪恶的小网络上,特别是在RNN的情况下。

  1. 尝试使用Leaky ReLU(但你可以面对爆炸的渐变)
  2. 尝试使用tanh,但检查参数的初始值,它们实际上是零,否则你的渐变也会很快消失。
  3. 在步骤0中检索未经训练但刚刚初始化的网络的结果。通过正确的初始化和NN构造,您应该获得正常分布的值.5如果您有严格的,零或混合它们,您的NN架构是错误的。所有值都严格.5也不好。
  4. 考虑更强大的方法,例如LSTM