【问题标题】:TensorFlow dropout: how to apply different values to Train vs Test?TensorFlow dropout:如何将不同的值应用于训练与测试?
【发布时间】:2017-10-18 06:07:11
【问题描述】:

我正在尝试在 TensorFlow 中实现 dropout,以实现一个简单的 3 层神经网络进行分类,但遇到了问题。更具体地说,我在训练与测试时尝试应用不同的 dropout 参数 pkeep 值。

我采取的方法如下:

1) def create_placeholders(n_x, n_y):

X = tf.placeholder("float", [n_x, None])
Y = tf.placeholder("float", [n_y, None])   
pkeep = tf.placeholder(tf.float32)
return X,Y,pkeep

2) 在函数 forward_propagation(X, parameters, pkeep) 中,我执行以下操作:

Z1 = tf.add(tf.matmul(W1, X), b1)
A1 = tf.nn.relu(Z1)
A1d = tf.nn.dropout(A1, pkeep)
Z2 = tf.add(tf.matmul(W2, A1d),b2)
A2 = tf.nn.relu(Z2)
A2d = tf.nn.dropout(A2, pkeep)
Z3 = tf.add(tf.matmul(W3, A2d),b3)

return Z3

3) 稍后调用 tensorflow 会话时(为清楚起见,在代码行之间省略):

X, Y, pkeep = create_placeholders(n_x, n_y)

Z3 = forward_propagation(X, parameters, pkeep)

sess.run([optimizer,cost], feed_dict={X:minibatch_X, Y:minibatch_Y, pkeep: 0.75})

上面将运行而不会出现任何错误。但是,我认为以上将pkeep 值设置为 0.75 用于训练和测试运行。 Minibatching 仅在训练数据集上完成,但我没有在其他任何地方设置 pkeep 值。

我想设置pkeep = 0.75 用于训练,pkeep = 1.0 用于测试。

4) 当我做这样的事情时它确实会出错:

x_train_eval = Z3.eval(feed_dict={X: X_train, Y: Y_train,  pkeep: 0.75})

x_test_eval = Z3.eval(feed_dict={X: X_test, Y: Y_test,  pkeep: 1.0})

我得到的错误信息是:

InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor 'Placeholder_2' with dtype float
     [[Node: Placeholder_2 = Placeholder[dtype=DT_FLOAT, shape=[], _device="/job:localhost/replica:0/task:0/cpu:0"]()]]

将不同的pkeep 值传递给训练和测试的最佳方法是什么?非常感谢您的建议。

【问题讨论】:

    标签: python tensorflow


    【解决方案1】:

    假设您有一些定义为test_op 的测试操作(例如,评估输入数据和标签准确性的操作),您可以执行以下操作:

    for i in range(num_iters):
        # Run your training process.
        _, loss = sess.run([optimizer, cost],
                           feed_dict={X:minibatch_X, Y:minibatch_Y, pkeep: 0.75})
    # Test the model after training
    test_accuracy = sess.run(test_op,
                             feed_dict={X:test_X, Y:test_Y, pkeep: 1.0})
    

    基本上,您在训练模型时不会对其进行测试,因此您可以在准备好测试时调用您的 test_op,并为其提供不同的超参数,例如 pkeep。在对保留数据集进行训练期间定期验证模型也是如此:每隔一段时间在保留数据集上运行评估操作,传递与训练期间使用的不同的超参数,然后您可以保存配置或提前停止根据您的验证准确性。

    您的test_op 可能会返回分类器的预测准确度之类的信息:

    correct = tf.equal(tf.argmax(y, 1), tf.argmax(predict, 1))
    test_op = tf.reduce_mean(tf.cast(correct, tf.float32))
    

    其中y 是您的目标标签,predict 是您的预测操作的名称。

    【讨论】:

    • 谢谢工程师。这很有帮助。我让它工作了。
    • @BrightOrange 太棒了!如果任何答案有帮助,请将其标记为正确,以便将来遇到相同问题的人知道什么对您有用。
    • 如果将其标记为“正确”意味着将“答案标记为有帮助”,我被告知我需要至少 15 个声望点才能做到这一点。一旦我积累了 15 分,我就会回来这样做。我昨天刚加入 =) 非常感谢。
    【解决方案2】:

    在神经网络中,您前向传播以计算 logits(每个标签的概率)并将其与实际值进行比较以获得错误。

    训练涉及最小化误差,方法是向后传播,即找到误差相对于每个权重的导数,然后从权重值中减去该值。

    当您将训练和评估模型所需的操作分开时,应用不同的 dropout 参数会更容易。

    训练只是最小化损失:

    def loss(logits, labels):
        '''
        Calculate cross entropy loss
        '''
        cross_entropy = tf.nn.softmax_cross_entropy_with_logits(
            labels=labels, logits=logits)
        return tf.reduce_mean(cross_entropy, name='loss_op')
    
    
    def train(loss, learning_rate):
        '''
        Train model by optimizing gradient descent
        '''
        optimizer = tf.train.AdamOptimizer(learning_rate)
        train_op = optimizer.minimize(loss, name='train_op')
        return train_op
    

    评估只是计算准确性:

    def accuracy(logits, labels):
        '''
        Calculate accuracy of logits at predicting labels
        '''
        correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(labels, 1))
        accuracy_op = tf.reduce_mean(tf.cast(correct_prediction, tf.float32),
                                     name='accuracy_op')
        return accuracy_op
    

    然后在您的 Tensorflow 会话中,在生成占位符并向图表添加必要的操作等之后,只需将不同的 keep_prob_pl 值输入到运行方法中:

    # Train model
    sess.run(train_op, feed_dict={x_pl: x_train, y_train: y, keep_prob_pl: 0.75}})
    
    # Evaluate test data
    batch_size = 100
    epoch = data.num_examples // batch_size
    acc = 0.0
    for i in range(epoch):
        batch_x, batch_y = data.next_batch(batch_size)
        feed_dict = {x_pl: batch_x, y_pl: batch_y, keep_prob_pl: 1}
        acc += sess.run(accuracy_op, feed_dict=feed_dict)
    
    print(("Epoch Accuracy: {:.4f}").format(acc / epoch))
    

    【讨论】:

    • 谢谢你,索夫。您的详细回答帮助我理解了工程师下面的评论。我能够让它工作=)
    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 2019-08-21
    • 2019-09-06
    • 2017-10-08
    • 2016-10-09
    • 2018-09-26
    • 2018-02-08
    • 2017-12-30
    相关资源
    最近更新 更多