caicloud / tensorflow-tutorial

Example TensorFlow codes and Caicloud TensorFlow as a Service dev environment.
2.93k stars 2.08k forks source link

有关第六章的迁移学习,如何实现在训练以后将整个模型保存并使用保存好的模型预测新的图片? #23

Closed LukeALee closed 7 years ago

LukeALee commented 7 years ago

我将以下代码从main函数中提取出来并实现模型的训练与保存: `def train(bottleneck_tensor, jpeg_data_tensor): image_lists = create_image_lists(TEST_PERCENTAGE, VALIDATION_PERCENTAGE) n_classes = len(image_lists.keys())

# 定义新的神经网络输入
bottleneck_input = tf.placeholder(tf.float32, [None, BOTTLENECK_TENSOR_SIZE],
                                  name='BottleneckInputPlaceholder')
ground_truth_input = tf.placeholder(tf.float32, [None, n_classes], name='GroundTruthInput')

logits=last_layer(n_classes,bottleneck_input)
final_tensor = tf.nn.softmax(logits)

# 定义交叉熵损失函数。
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=ground_truth_input)
cross_entropy_mean = tf.reduce_mean(cross_entropy)
train_step = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cross_entropy_mean)

# 计算正确率。
with tf.name_scope('evaluation'):
    correct_prediction = tf.equal(tf.argmax(final_tensor, 1), tf.argmax(ground_truth_input, 1))
    evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

saver = tf.train.Saver(tf.global_variables(), write_version=tf.train.SaverDef.V1)

with tf.Session() as sess:
    init = tf.global_variables_initializer()
    sess.run(init)
    print("重新训练模型")
    for i in range(STEPS):
        train_bottlenecks, train_ground_truth = get_random_cached_bottlenecks(
            sess, n_classes, image_lists, BATCH, 'training', jpeg_data_tensor, bottleneck_tensor)
        sess.run(train_step,
                 feed_dict={bottleneck_input: train_bottlenecks, ground_truth_input: train_ground_truth})
        # 在验证数据上测试正确率
        if i % 100 == 0 or i + 1 == STEPS:
            validation_bottlenecks, validation_ground_truth = get_random_cached_bottlenecks(
                sess, n_classes, image_lists, BATCH, 'validation', jpeg_data_tensor, bottleneck_tensor)
            validation_accuracy = sess.run(evaluation_step, feed_dict={
                bottleneck_input: validation_bottlenecks, ground_truth_input: validation_ground_truth})
            print('Step %d: Validation accuracy on random sampled %d examples = %.1f%%' %(i, BATCH, validation_accuracy * 100))
    print('Beginning Test')
    # 在最后的测试数据上测试正确率。
    test_bottlenecks, test_ground_truth = get_tst_bottlenecks(
        sess, image_lists, n_classes, jpeg_data_tensor, bottleneck_tensor)
    test_accuracy = sess.run(evaluation_step, feed_dict={
        bottleneck_input: test_bottlenecks, ground_truth_input: test_ground_truth})
    print('Final test accuracy = %.1f%%' % (test_accuracy * 100))

    saver.save(sess, 'F:/_pythonWS/imageClassifier/ckpt/imagesClassFilter.ckpt')`

使用以下代码尝试恢复模型并使用测试图片再次预测测试图片的分类, `def image_Classfier(bottleneck_tensor, jpeg_data_tensor):

image_lists = create_image_lists(TEST_PERCENTAGE, VALIDATION_PERCENTAGE)
n_classes = len(image_lists.keys())

# 定义新的神经网络输入
bottleneck_input = tf.placeholder(tf.float32, [None, BOTTLENECK_TENSOR_SIZE],
                                  name='BottleneckInputPlaceholder')
ground_truth_input = tf.placeholder(tf.float32, [None, n_classes], name='GroundTruthInput')

logits=last_layer(n_classes,bottleneck_input)
final_tensor = tf.nn.softmax(logits)

# 计算正确率。
with tf.name_scope('evaluation'):
    correct_prediction = tf.equal(tf.argmax(final_tensor, 1), tf.argmax(ground_truth_input, 1))
    evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

saver = tf.train.Saver(tf.global_variables(), write_version=tf.train.SaverDef.V1)
with tf.Session() as sess:
    # init = tf.global_variables_initializer()
    # sess.run(init)
    if os.path.exists('F:/_pythonWS/imageClassifier/ckpt/imagesClassFilter.ckpt'):
        saver.restore(sess, 'F:/_pythonWS/imageClassifier/ckpt/imagesClassFilter.ckpt')
        print("ckpt file already exist!")

    # 在最后的测试数据上测试正确率。
    test_bottlenecks, test_ground_truth = get_tst_bottlenecks(
        sess, image_lists, n_classes, jpeg_data_tensor, bottleneck_tensor)
    test_accuracy = sess.run(evaluation_step, feed_dict={
        bottleneck_input: test_bottlenecks, ground_truth_input: test_ground_truth})
    print('Final test accuracy = %.1f%%' % (test_accuracy * 100))

    with tf.name_scope('kind'):
        # image_kind=image_lists.keys()[tf.arg_max(final_tensor,1)]
        image_order_step = tf.arg_max(final_tensor, 1)
    label_name_list = list(image_lists.keys())
    for label_index, label_name in enumerate(label_name_list):
        category = 'testing'
        for index, unused_base_name in enumerate(image_lists[label_name][category]):
            bottlenecks = []
            ground_truths = []
            print("真实值%s:" % label_name)
            # print(unused_base_name)
            bottleneck = get_or_create_bottleneck(sess, image_lists, label_name, index, category,
                                                  jpeg_data_tensor, bottleneck_tensor)
            ground_truth = np.zeros(n_classes, dtype=np.float32)
            ground_truth[label_index] = 1.0
            bottlenecks.append(bottleneck)
            ground_truths.append(ground_truth)
            image_kind = sess.run(image_order_step, feed_dict={
                bottleneck_input: bottlenecks, ground_truth_input: ground_truths})
            image_kind_order = int(image_kind[0])
            print("预测值%s:" % label_name_list[image_kind_order])`

`def main(): graph_def = load_inception_v3() bottleneck_tensor, jpeg_data_tensor = tf.import_graph_def( graph_def, return_elements=[BOTTLENECK_TENSOR_NAME, JPEG_DATA_TENSOR_NAME]) train(bottleneck_tensor, jpeg_data_tensor) image_Classfier(bottleneck_tensor, jpeg_data_tensor)

if name == 'main': main()` 但是失败了,似乎并没能将保存的模型正确的恢复,请问我哪里做错了,又该如何实现?

LukeALee commented 7 years ago

使用第五章中的方法即可实现save与restore,但需要注意的是如果需要保存训练好的模型用于直接分类,每次重新巡行不能使用dict类型的result(即书中例子构造的的图片)而要使用Orderdict(即有序字典),否则每次lable的顺序不一致而导致下次用的时候预测的分类和ground_truth的分类不一致,那么正确率无论如何都会很低了

j081mm commented 7 years ago

请问书友是否已经实现了,在训练以后将整个模型保存并使用保存好的模型预测新的图片呢?

LukeALee commented 7 years ago

你好,已经实现了,具体的代码因为要用到某些工作上所以目前不太方便公开,实现的方式就是如之前我所说的,首先将代码中的result重新使用Orderdict的类型构建,自己编写一个函数生成bottleneck_values, 然后预测时使用该函数生成需要预测的图片的bottleneck_values,定义image_order_step = tf.arg_max(final_tensor, 1), 使用sess.run运行该tensor,其返回值就是在result列表中该图片所属分类的序号。

LukeALee commented 7 years ago

至于保存和恢复的方式和书上说的并没有什么区别。

j081mm commented 7 years ago

谢谢