tensorflow学习,深入分析建立的识别CIFAR-10数据集物体的深度学习网络,如何看训练结果(17)

上一节我们参考官方例程建立了自己的深度学习网络,并且训练时,损失函数 loss 也是不断下降的,这说明我们的网络有可能是正常工作的。我现在非常想看训练过程中,网络的预测值和真实值的对比,该如何做呢?

代码回顾


我们是通过 NetworkRes 函数建立的网络,输入的是一个图片 batch,上一节,我们定义 batch = 50,因此输入是 50 张图片。根据代码,输出的形状应该是 [50,10],表示 50 张图片每张都有 10 类输出值。

def NetworkRes(images):
    # 第一层卷积
    kernel = tf.Variable(tf.zeros([5,5,3,64]))
    biases = tf.Variable(tf.random_normal( [64])) 
    ...
    # 第三层全连接层
    weights = tf.Variable(tf.zeros([192, NUM_CLASSES]))
    biases = tf.Variable(tf.random_normal( [NUM_CLASSES]))
    logits = tf.add(tf.matmul(res2, weights), biases)
    return logits

再来看看 Loss 函数,核心就是 tensorflow 的 sparse_softmax_cross_entropy_with_logits 方法。上一节,我们简要介绍了它的含义,主对比介绍了 softmax_cross_entropy_with_logits 方法,它俩的区别在哪里呢?

def Loss(logits, labels):
    # 求交叉熵loss的平均值
    labels = tf.cast(labels, tf.int64)
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
      labels=labels, logits=logits, name='cross_entropy_per_example')
    cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
    return cross_entropy_mean

sparse_softmax_cross_entropy_with_logits 适合互斥物体的分类,每一张图片应该只属于一种物体,而不可能包含两种及以上的物体种类。logits 必须具有shape [batch_size, num_classes] 并且 dtype (float32 or float64),labels 必须具有shape [batch_size],并且 dtype int64。这就解释了上一节的下面几行代码:

...
# 返回的是加工过的图片和标签的batch
    return images, tf.reshape(label_batch, [batch_size])
...
labels = tf.cast(labels, tf.int64)
...

softmax_cross_entropy_with_logits 需要的标签值是 one-hot 的,而 sparse_softmax_cross_entropy_with_logits 需要的标签值则是数字,介于 [0, 类别总数) 之间。

如何查看预测值和真实值的对比


首先要明确的是,预测值出自网络的输出,即 NetworkRes 函数的最终输出。上一部分已经分析过,它的输出是 [50, 10] 形状的值,预测信息在第二维。计划是这样的:计算 10 类值的概率,取最大值作为预测值。例如第一张图片的 10 类值如下

0.02, 0.33, 0.01, 0.05, 0.10, 0.05, 0.09, 0.12, 0.11, 0.08

从 0 开始计数的话,本次预测图片属于第 1 类。

经过这么多天的学习,知道 softmax 特别适合计算概率,于是在原有代码添加:

pp = tf.nn.softmax(logits)
prediction = tf.argmax(pp,1)

tf.argmax(pp,1) 方法返回传入的 pp 最大值对应的索引。这样一来,我们只需要打印出 prediction,再打印出 label_batch 即可对比。但是 50 个图片看着太乱了,咱们输出以第 0 个张量为例,print 部分的代码就可以如下写:

print 'prediction', sess.run(prediction)[[0]],' -- label_batch', sess.run(label_batch)[[0]]

最终,修改部分的代码如下:

def Train():
    # 创建文件名 list
    for i in range(1,6):
        filenames = [os.path.join('cifar10_data/cifar-10-batches-bin', 'data_batch_%d.bin' % i)]

    images, label_batch = Distorted_inputs(filenames, BATCH_SIZE)
    logits = NetworkRes(images)
    loss = Loss(logits, label_batch)

    pp = tf.nn.softmax(logits)
    prediction = tf.argmax(pp,1)
    train_step = tf.train.AdamOptimizer(5e-4).minimize(loss)

    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        threads = tf.train.start_queue_runners(sess=sess)
        for i in range(50000):
            # print 'times: %d' % i
            sess.run(train_step)
            if i%10 == 0:
                print 'i=%d, loss:' % i, sess.run(loss)
                print 'prediction', sess.run(prediction)[[0]],' -- label_batch', sess.run(label_batch)[[0]]

其他部分代码都与上一节一样,只有训练函数 Train 添加了一部分。每 10 次打印一次对比,运行之,打印结果如下:

$ python t2.py 
i=0, loss: 3.612214
prediction [0]  -- label_batch [1]
i=10, loss: 2.326826
prediction [7]  -- label_batch [9]
i=20, loss: 2.4405525
prediction [8]  -- label_batch [4]
i=30, loss: 2.3616848
prediction [1]  -- label_batch [7]
i=40, loss: 2.3330555
prediction [3]  -- label_batch [8]
i=50, loss: 2.3802912
prediction [6]  -- label_batch [9]
i=60, loss: 2.3155308
prediction [6]  -- label_batch [3]
i=70, loss: 2.289318
prediction [1]  -- label_batch [7]
...

通过对比,发现刚开始训练时,网络就没有正确分类的图片。但是随着训练的进行,通过打印结果:

...
i=11860, loss: 1.1613389
prediction [6]  -- label_batch [5]
i=11870, loss: 1.3516332
prediction [9]  -- label_batch [6]
i=11880, loss: 1.0219045
prediction [7]  -- label_batch [1]
i=11890, loss: 0.9904063
prediction [7]  -- label_batch [7]
i=11900, loss: 1.0699639
prediction [5]  -- label_batch [9]
...

发现损失函数 loss 减小了,也出现了正确分类的情况,而且即使预测错误,相差结果也接近了。当然,10000 次训练还是太少了,还要继续训练。

阅读更多:   tensorflow
已有 2 条评论
  1. […] 上一节我们又详细分析了16节建立的深度学习网络,并且尝试在训练中对比预测值和标签值。这一节将结合官方代码,对上一节的内容进行补充。 […]

  2. […] 建立 loss 非常简单,主要使用了 tensorflow 的 sparse_softmax_cross_entropy_with_logits 方法,这个方法我们在第17节有所介绍。代码如下 […]

添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif