【问题标题】:Udacity Deep Learning, Assignment 3, Part 3: Tensorflow dropout functionUdacity 深度学习,作业 3,第 3 部分:Tensorflow dropout 函数
【发布时间】:2017-12-20 06:35:08
【问题描述】:

我现在正在完成 Udacity 深度学习课程的作业 3。我已经完成了大部分工作并且它正在工作,但我注意到问题 3,即使用 tensorflow 的“dropout”,似乎降低了我的性能而不是提高它。

所以我认为我做错了什么。我会把我的完整代码放在这里。如果有人可以向我解释如何正确使用 dropout,我将不胜感激。 (或者确认我使用正确,在这种情况下它没有帮助。)。它将准确率从超过 94%(没有丢失)降低到 91.5%。如果不使用 L2 正则化,降级会更大。

def create_nn(dataset, weights_hidden, biases_hidden, weights_out, biases_out):
    # Original layer
    logits = tf.add(tf.matmul(tf_train_dataset, weights_hidden), biases_hidden)
    # Drop Out layer 1
    logits = tf.nn.dropout(logits, 0.5)
    # Hidden Relu layer
    logits = tf.nn.relu(logits)
    # Drop Out layer 2
    logits = tf.nn.dropout(logits, 0.5)
    # Output: Connect hidden layer to a node for each class
    logits = tf.add(tf.matmul(logits, weights_out), biases_out)
    return logits


# Create model
batch_size = 128
hidden_layer_size = 1024
beta = 1e-3

graph = tf.Graph()
with graph.as_default():
    # Input data. For the training data, we use a placeholder that will be fed
    # at run time with a training minibatch.
    tf_train_dataset = tf.placeholder(tf.float32,
                                    shape=(batch_size, image_size * image_size))
    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))
    tf_valid_dataset = tf.constant(valid_dataset)
    tf_test_dataset = tf.constant(test_dataset)

    # Variables.
    weights_hidden = tf.Variable(
        #tf.truncated_normal([image_size * image_size, num_labels]))
        tf.truncated_normal([image_size * image_size, hidden_layer_size]))
    #biases = tf.Variable(tf.zeros([num_labels]))
    biases_hidden = tf.Variable(tf.zeros([hidden_layer_size]))

    weights_out = tf.Variable(tf.truncated_normal([hidden_layer_size, num_labels]))
    biases_out = tf.Variable(tf.zeros([num_labels]))


    # Training computation.
    #logits = tf.matmul(tf_train_dataset, weights_out) + biases_out
    logits = create_nn(tf_train_dataset, weights_hidden, biases_hidden, weights_out, biases_out)

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=tf_train_labels, logits=logits))
    loss += beta * (tf.nn.l2_loss(weights_hidden) + tf.nn.l2_loss(weights_out))

    # Optimizer.
    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)

    # Predictions for the training, validation, and test data.
    train_prediction = tf.nn.softmax(logits)
    #valid_prediction = tf.nn.softmax(tf.matmul(tf_valid_dataset, weights_out) + biases_out)
    #test_prediction = tf.nn.softmax(tf.matmul(tf_test_dataset, weights_out) + biases_out)
    valid_prediction = tf.nn.softmax(tf.matmul(tf.nn.relu(tf.matmul(tf_valid_dataset, weights_hidden) + biases_hidden), weights_out) + biases_out)
    test_prediction = tf.nn.softmax(tf.matmul(tf.nn.relu(tf.matmul(tf_test_dataset, weights_hidden) + biases_hidden), weights_out) + biases_out)


num_steps = 10000

with tf.Session(graph=graph) as session:
  tf.global_variables_initializer().run()
  print("Initialized")
  for step in range(num_steps):
    # Pick an offset within the training data, which has been randomized.
    # Note: we could use better randomization across epochs.
    offset = (step * batch_size) % (train_labels.shape[0] - batch_size)
    #offset = (step * batch_size) % (3*128 - batch_size)
    #print(offset)
    # Generate a minibatch.
    batch_data = train_dataset[offset:(offset + batch_size), :]
    batch_labels = train_labels[offset:(offset + batch_size), :]
    # Prepare a dictionary telling the session where to feed the minibatch.
    # The key of the dictionary is the placeholder node of the graph to be fed,
    # and the value is the numpy array to feed to it.
    feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels}
    _, l, predictions = session.run([optimizer, loss, train_prediction], feed_dict=feed_dict)

    if (step % 500 == 0):
      print("Minibatch loss at step %d: %f" % (step, l))
      print("Minibatch accuracy: %.1f%%" % accuracy(predictions, batch_labels))
      print("Validation accuracy: %.1f%%" % accuracy(valid_prediction.eval(), valid_labels))

  print("Test accuracy: %.1f%%" % accuracy(test_prediction.eval(), test_labels))

【问题讨论】:

    标签: python-3.x tensorflow deep-learning anaconda


    【解决方案1】:

    您需要在推理期间关闭 dropout。一开始可能并不明显,但在 NN 架构中 dropout 是硬编码的,这意味着它会在推理过程中影响测试数据。您可以通过创建占位符keep_prob 来避免这种情况,而不是直接提供值0.5。例如:

    keep_prob = tf.placeholder(tf.float32)
    logits = tf.nn.dropout(logits, keep_prob)
    

    要在训练期间打开 dropout,请将 keep_prob 值设置为 0.5:

    feed_dict = {tf_train_dataset : batch_data, tf_train_labels : batch_labels, keep_prob: 0.5}
    

    在推理/评估期间,您应该能够执行以下操作将keep_prob 设置为eval 中的1.0:

    accuracy.eval(feed_dict={x: test_prediction, y_: test_labels, keep_prob: 1.0}
    

    编辑:

    由于问题似乎不是在推理时使用了 dropout,因此下一个罪魁祸首是 dropout 对于这个网络规模来说太高了。您可以尝试将 dropout 降低到 20%(即 keep_prob=0.8),或者增加网络的大小以使模型有机会学习表示。

    我实际上用你的代码试了一下,在这种网络规模下,我得到了大约 93.5% 的结果,有 20% 的 dropout。我在下面添加了一些额外的资源,包括原始的 Dropout 论文,以帮助阐明其背后的直觉,并扩展了使用 dropout 时的更多技巧,例如提高学习率。

    参考资料:

    【讨论】:

    • 我认为我感到困惑的原因是因为我有一个 valid_prediction 和 test_prediction 不是来自硬编码的 NN 架构:
    • valid_prediction = tf.nn.softmax(tf.matmul(tf.nn.relu(tf.matmul(tf_valid_dataset, weights_hidden) + biases_hidden), weights_out) + biases_out)
    • test_prediction = tf.nn.softmax(tf.matmul(tf.nn.relu(tf.matmul(tf_test_dataset, weights_hidden) + biases_hidden), weights_out) + biases_out)
    • 所以当我得到一个测试或验证集预测时,没有丢失。我假设这将避免需要这样做。我显然错过了一些东西。
    • 你是对的,在这种情况下不会出现辍学。我已经用我认为可能有用的其他提示编辑了上面的答案。主要是玩弄 dropout 的值,因为对于这个网络规模来说它可能太高了,或者可能会增加网络的规模。
    【解决方案2】:

    我认为可能导致问题的两件事。

    首先,我不建议在第一层使用 dropout(太 50%,使用更低,如果必须的话,在 10-25% 范围内))因为当您使用如此高的 dropout 时,甚至更高级别的功能都不是学习并传播到更深层。还可以尝试从 10% 到 50% 的一系列 dropout,看看准确性如何变化。没有办法事先知道什么值会起作用

    其次,您通常不会在推理时使用 dropout。修复 dropout 的 keep_prob 参数作为占位符的传递,并在推理时将其设置为 1。

    此外,如果您声明的准确度值是训练准确度,那么首先可能不会有太大问题,因为 dropout 通常会少量降低训练准确度,因为您没有过度拟合,它的测试/验证准确度需要密切关注

    【讨论】:

    • 我在报告测试准确性。
    • “其次,你通常不会在推理时使用 dropout。为了修复这个 pass in dropout 的 keep_prob 参数作为占位符,并在推理时将其设置为 1。”我不明白你在这里的意思。你能澄清一下吗?
    • 我认为这可能是我做得不对的部分。我一直在阅读这方面的内容,但我不清楚这意味着什么。据我所知,我在测试和验证评估中根本没有辍学。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    • 2023-03-27
    • 2017-12-09
    • 1970-01-01
    • 2016-11-12
    • 2017-09-27
    • 2020-04-18
    相关资源
    最近更新 更多