源字典命令在训练循环中的作用



我试图理解训练循环。在计算训练和测试准确性时,我们用训练和测试集替换xy_,但在打印交叉熵的结果时,为什么我们分别按batch_xsbatch_ys馈送xy_?我知道我们必须为占位符分配一个值,但在计算测试准确性时batch_xsbatch_ys保持不变,并且两者都使用训练集值。

x = tf.placeholder(tf.float32, [None, nPixels])
y_ = tf.placeholder(tf.float32, [None, nLabels])
cross_entropy = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(y, y_))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
with tf.Session() as sess:
tf.initialize_all_variables().run()
for j in range(nSteps):
i = nstep % nSteps
batch_xs = np.reshape(x_train,(nSteps,bSize,nPixels))
batch_ys = np.reshape(y_train,(nSteps,bSize,nLabels))
sess.run(train_step, feed_dict={x: batch_xs[i], y_: batch_ys[i]})
if j % 100 ==0:
train_acc = sess.run(accuracy, feed_dict={x: x_train,y_: y_train})
test_acc = sess.run(accuracy, feed_dict={x: x_test, y_: y_test}))
loss = sess.run(cross_entropy, feed_dict={x: batch_xs[i], y_: batch_ys[i]})

您可以在执行训练步骤的同时计算训练损失(这样您就不必进行单独的调用,稍后再次传递批处理(,如下所示:

for j in range(nSteps):
# ...
_, train_loss = sess.run([train_step, cross_entropy],
feed_dict={x: batch_xs[i], y_: batch_ys[i]})

至于为什么在计算准确性时不需要调整训练/测试集的大小,让我们看看整个代码中的数据维度。您从以下方面开始:

x = tf.placeholder(tf.float32, [None, nPixels])
y_ = tf.placeholder(tf.float32, [None, nLabels])

这意味着x的维度是[num_samples, nPixels]的,y_的维度是[num_samples, nLabels]的。我认为x_trainy_train只是其中的一些子样本,所以分别[num_train, nPixels][num_train, nLabels]。接下来,为批次重塑这些内容:

batch_xs = np.reshape(x_train,(nSteps,bSize,nPixels))
batch_ys = np.reshape(y_train,(nSteps,bSize,nLabels))

现在batch_xs具有维度[num_steps, batch_size, nPixels]batch_ys具有维度[num_steps, batch_size, nLabels]。请注意,最后一个维度(要素数或输出维度(未更改。

现在,对于训练循环的每次迭代,您从这些列表的第一个维度中获取一个元素,其中包含batch_xs[i]batch_ys[i]。这些家伙的尺寸现在分别是[batch_size, nPixels][batch_size, nLables]。同样,最后一个维度没有改变。

最后,你在一个批次或整个训练集上调用你的accuracycross_entropy操作,TF 不在乎它是哪个!这是因为您为其提供的特征/标签数量无论哪种方式都相同,并且所改变的只是您传递的数据元素的数量。在一种情况下,您传递的是batch_size元素,而在另一种情况下,您传递的是num_trainnum_test元素,但指定每个示例外观的最后一个维度是相同的!TF是神奇的,并弄清楚如何处理差异。

旧答案

看起来你只是想把训练损失从循环中解脱出来,因此你正在将训练批次传递给你的cross_entropy函数。很多时候,您可能会在每批中评估此值并存储结果,以便以后可以绘制一段时间内的训练损失,但有时此计算需要很长时间,以至于您只想每隔一段时间计算一次。您的代码似乎就是这种情况。

通常,最好在训练循环运行时同时查看训练测试(或验证(损失。这是因为您能够更好地看到过度拟合的影响,其中训练损失继续减少,测试损失水平下降或开始增加。像这样:

if j % 100 == 0:
train_loss = sess.run(cross_entropy, feed_dict={x: batch_xs[i], y_: batch_ys[i]})
test_loss = sess.run(cross_entropy, feed_dict={x: x_test, y_: y_test})
# print or store your training and test loss

监控测试损失的主要原因之一是在过度拟合的情况下尽早停止训练。为此,您可以存储最佳测试损失,然后将每个新的测试损失与存储的最佳测试损失进行比较。每次你得到一个新的测试损失,没有超过你的最佳水平,你就会增加一个计数器,当计数器达到某个数字(比如 10 或 20(时,你会杀死训练循环并称它为好。通过这种方式,您可以捕获训练何时在验证/测试集上停滞不前,这可以更好地指示何时不再更好地推广到新数据。

如果您遇到比最佳更好的新验证损失,请存储它并重置计数器。

最后,通常最好保留两组数据,一组称为验证集,另一组称为测试集。当你像这样拆分它时,你通常在训练时使用验证集来寻找过度拟合并执行早期停止,然后你对网络以前从未见过的测试集运行一个准确性/损失的最终测试,以让你了解它的整体泛化性能。它看起来像:

for epoch:
for batch in batches:
x = batch.x
y = batch.y
sess.run(train_step, feed_dict={x: x, y_: y})
if j % 100 == 0:
train_loss = sess.run(cross_entropy, feed_dict={x: x, y_: y})
test_loss = sess.run(cross_entropy, feed_dict={x: x_val, y_: y_val})  # note validation data
# print or store your training and test loss
# check for early stopping
test_loss = sess.run(cross_entropy, feed_dict={x: x_test, y_: y_test})
# Or test accuracy or whatever you want to evaluate.
# Point is the network never saw this data until now.

最新更新