Tensorflow(五)用Inception-ResNet-v1实现迁移学习(代码实现)

1. Inception-ResNet-v1简介

2.实验代码


import  inception_resnet_v1
import tensorflow.contrib.slim as slim
import numpy as np
import  cv2
import face_image_input
import tensorflow as tf
from datetime import datetime
import math
import time
import os

import matplotlib.pyplot as plt

# 配置神经网络的参数
BATCH_SIZE = 128
batch_size = 128
LEARNING_RATE_BASE = 0.01   #0.8   #
LEARNING_RATE_DECAY =   0.0005     # 0.99
REGULARAZTION_RATE = 0.0001
TRAIN_STEPS = 10000    #3000
MOVING_AVERAGE_DECAY = 0.99


MODEL_SAVE_PATH = "./model/"
MODEL_NAME = "model3.ckpt"

slim = tf.contrib.slim

DATA_DIR = './datasets/data/flowers'
# 输出类别
NUM_CLASSES = 5

# 获取图片大小
IMAGE_SIZE = 160


def face_fine_tuning():
    '''
    1.设置参数,并加载数据
    '''
    # 用于保存微调后的检查点文件和日志文件路径
    train_log_dir = './finetune_face'
    train_log_file = 'face_fine_tune.ckpt'

    # 官方下载的检查点文件路径
    checkpoint_file = './20180402-114759/model-20180402-114759.ckpt-275'  # -275.index
                      # './20180402-114759/model-20180402-114759.ckpt-275'

    learning_rate = 1e-4
    # 设置batch_size
    batch_size =32  # 32  #128  #256

    # 训练集数据长度
    n_train =  120 #3320
    # 测试集数据长度
    # n_test = 350
    # 迭代轮数
    training_epochs = 500  #100

    display_epoch = 1

    if not tf.gfile.Exists(train_log_dir):
        tf.gfile.MakeDirs(train_log_dir)

    # 加载数据
    train_images, train_labels = face_image_input.distorted_inputs("",batch_size)
    test_images, test_labels = face_image_input.inputs(eval_data=False, data_dir="", batch_size=batch_size)

    # 获取模型参数的命名空间
    #arg_scope = inception_resnet_v1.vgg_arg_scope()
    #arg_scope = inception_resnet_v2_arg_scope()
    # 创建网络
    #with  slim.arg_scope(""):
    if 1==1:
        '''
        2.定义占位符和网络结构
        '''
        # 输入图片
        input_images = tf.placeholder(dtype=tf.float32, shape=[None, IMAGE_SIZE, IMAGE_SIZE, 3])
        # 图片标签
        input_labels = tf.placeholder(dtype=tf.float32, shape=[None, 5])
        #input_labels = tf.placeholder(dtype=tf.int32, shape=[batch_size])
        label_holder = tf.placeholder(tf.int32, [batch_size], name='y-input')
        # 训练还是测试?测试的时候弃权参数会设置为1.0
        is_training = tf.placeholder(dtype=tf.bool)

        # 创建vgg16网络  如果想冻结所有层,可以指定slim.conv2d中的 trainable=False
        logits, end_points = inception_resnet_v1.inception_resnet_v1(input_images, is_training=is_training)
        # print(end_points)  每个元素都是以vgg_16/xx命名


        # Restore only the convolutional layers: 从检查点载入当前图除了fc8层之外所有变量的参数
        params = slim.get_variables_to_restore(exclude=['Logits','InceptionResnetV1/Bottleneck'])
        variables_to_restore = slim.get_variables_to_restore(exclude=['Logits','InceptionResnetV1/Bottleneck'])
                                                                             #InceptionResnetV1/Bottleneck
        print("输出变量000:")
        print(variables_to_restore)
        # 用于恢复模型  如果使用这个保存或者恢复的话,只会保存或者恢复指定的变量
        restorer = tf.train.Saver(params)
        init_assign_op, init_feed_dict = slim.assign_from_checkpoint(checkpoint_file, variables_to_restore,ignore_missing_vars=True)

        # 预测标签
        pred = tf.argmax(logits, axis=1)

        '''
定义代价函数和优化器
        '''
        # 代价函数
        cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=input_labels, logits=logits))

        # 设置优化器
        optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)  #全部参数重新训练

        # 预测结果评估
        correct = tf.equal(pred, tf.argmax(input_labels, 1))  # 返回一个数组 表示统计预测正确或者错误
        accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))  # 求准确率

        num_batch = int(np.ceil(n_train / batch_size))

        # 用于保存检查点文件
        save = tf.train.Saver(max_to_keep=1)

        # 恢复模型
        with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())
            variables_to_restore1 = sess.run(variables_to_restore)
            #print("输出变量:")
            #print(variables_to_restore1)
            # 检查最近的检查点文件
            ckpt = tf.train.latest_checkpoint(train_log_dir)
            if ckpt != None:
                save.restore(sess, ckpt)
                print('从上次训练保存后的模型继续训练!')
            else:
                #restorer.restore(sess, checkpoint_file)
                sess.run(init_assign_op, init_feed_dict)   # 添加
                print('从官方模型加载训练!')

            # 创建一个协调器,管理线程
            coord = tf.train.Coordinator()

            # 启动QueueRunner, 此时文件名才开始进队。
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)

            '''
            查看预处理之后的图片
            imgs, labs = sess.run([train_images, train_labels])
            print('原始训练图片信息:', imgs.shape, labs.shape)
            print("lable:",labs)
            labs = tf.one_hot(labs, depth=5, axis=-1)
            print('原始测试图片信息:', imgs.shape, labs.shape)
            print("lable:", labs)
            show_img = np.array(imgs[0], dtype=np.uint8)
            plt.imshow(show_img)
            plt.title('Original train image')
            plt.show()

            imgs, labs = sess.run([test_images, test_labels])
            print('原始测试图片信息:', imgs.shape, labs.shape)
            labs = tf.one_hot(labs, depth=5, axis=-1)
            print('原始测试图片信息:', imgs.shape, labs.shape)
            show_img = np.array(imgs[0], dtype=np.uint8)
            plt.imshow(show_img)
            plt.title('Original test image')
            plt.show()
            '''


            print('开始训练!')
            for epoch in range(training_epochs):
                total_cost = 0.0
                print("训练111111!!!")
                for i in range(num_batch):
                    print("批次:"+str(i))
                    print("训练222222!!!")
                    imgs, labs = sess.run([train_images, train_labels])
                    labs = tf.one_hot(labs, depth=5, axis=-1)
                    print('原始训练图片信息,程序运行中:', imgs.shape, labs.shape)
                    labs = sess.run(labs)
                    #print(labs)
                    #print(type(labs))
                    _, loss = sess.run([optimizer, cost],
                                       feed_dict={input_images: imgs, input_labels: labs, is_training: True})
                    total_cost += loss
                print("训练ing!!!")
                # 打印信息
                if epoch % display_epoch == 0:
                    print('Epoch {}/{}  average cost {:.9f}'.format(epoch + 1, training_epochs, total_cost / num_batch))

                # 进行预测处理
                imgs, labs = sess.run([test_images, test_labels])
                labs = tf.one_hot(labs, depth=5, axis=-1)
                labs =  sess.run(labs)
                print('原始测试图片信息,程序运行中:', imgs.shape, labs.shape)
                #print(labs)
                #labs = labs.eval()
                #print(type(labs))
                cost_values, accuracy_value = sess.run([cost, accuracy],
                                                       feed_dict={input_images: imgs, input_labels: labs,
                                                                  is_training: False})
                print('Epoch {}/{}  Test cost {:.9f}'.format(epoch + 1, training_epochs, cost_values))
                print('准确率:', accuracy_value)

                # 保存模型
                save.save(sess, os.path.join(train_log_dir, train_log_file), global_step=epoch)
                print('Epoch {}/{}  模型保存成功'.format(epoch + 1, training_epochs))

            print('训练完成')

            # 终止线程
            coord.request_stop()
            coord.join(threads)


def face_test():
    '''
    使用微调好的网络进行测试
    '''
    '''
    1.设置参数,并加载数据
    '''
    # 微调后的检查点文件和日志文件路径
    save_dir = './finetune_face'

    # 设置batch_size
    batch_size = 64 #128

    # 加载数据
    train_images, train_labels = face_image_input.distorted_inputs("", batch_size)
    test_images, test_labels = face_image_input.inputs(eval_data=False, data_dir="", batch_size=batch_size)

    # 获取模型参数的命名空间
    #arg_scope = inception_resnet_v1.vgg_arg_scope()

    # 创建网络
    #with  slim.arg_scope(arg_scope):
    if 1==1:
        '''
        2.定义占位符和网络结构
        '''
        # 输入图片
        input_images = tf.placeholder(dtype=tf.float32, shape=[None, IMAGE_SIZE, IMAGE_SIZE, 3])
        # 训练还是测试?测试的时候弃权参数会设置为1.0
        is_training = tf.placeholder(dtype=tf.bool)

        # 创建vgg16网络
        logits, end_points = inception_resnet_v1.inception_resnet_v1(input_images, is_training=False)

        # 预测标签
        pred = tf.argmax(logits, axis=1)

        restorer = tf.train.Saver()

        # 恢复模型
        with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())
            ckpt = tf.train.latest_checkpoint(save_dir)
            if ckpt != None:
                # 恢复模型
                restorer.restore(sess, ckpt)
                print("Model restored.")

            # 创建一个协调器,管理线程
            coord = tf.train.Coordinator()

            # 启动QueueRunner, 此时文件名才开始进队。
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)

            '''
            查看预处理之后的图片
            '''
            imgs, labs = sess.run([test_images, test_labels])
            print('原始测试图片信息:', imgs.shape, labs.shape)
            show_img = np.array(imgs[0], dtype=np.uint8)
            plt.imshow(show_img)
            plt.title('Original test image')
            plt.show()

            pred_value = sess.run(pred, feed_dict={input_images: imgs, is_training: False})
            print('预测结果为:', pred_value)
            print('实际结果为:', labs)
            correct = np.equal(pred_value, labs)
            print('准确率为:', np.mean(correct))

            # 终止线程
            coord.request_stop()
            coord.join(threads)


if __name__ == '__main__':
    tf.reset_default_graph()
    face_fine_tuning()
    tf.reset_default_graph()
    face_test()

3.实验结果

3.1

batch_size =16  
# 训练集数据长度
n_train =  163 
# 迭代轮数
training_epochs =10

(1)准确率为: 0.40625

3.2

batch_size =32 
# 训练集数据长度
n_train =  163 #3320
# 迭代轮数
training_epochs = 50

(2)训练: Epoch 50/50 Test cost 3.713762522
准确率: 0.4375
Epoch 50/50 模型保存成功

准确率为: 0.390625

3.3 Epoch 100/100 Test cost 4.668624878

准确率: 0.46875
Epoch 100/100 模型保存成功
训练完成

原始测试图片信息: (64, 160, 160, 3) (64,)
预测结果为: [1 3 1 2 2 0 2 1 1 0 2 2 4 4 2 3 1 2 2 2 2 4 4 2 2 4 4 1 1 4 3 4 1 1 2 2 4
2 0 2 0 1 3 2 4 2 2 2 1 2 2 2 4 2 4 1 4 4 4 1 3 2 1 1]
实际结果为: [0 0 0 0 0 2 2 1 1 2 2 1 1 1 2 2 2 2 2 2 2 3 4 3 4 4 4 4 0 4 0 4 1 0 0 2 1
0 2 1 2 1 2 2 1 2 2 2 2 2 2 3 3 4 4 4 4 4 4 0 0 0 0 1]
准确率为: 0.4375

3.4 Epoch 500/500 average cost 0.000000050

原始测试图片信息,程序运行中: (32, 160, 160, 3) (32, 5)
Epoch 500/500 Test cost 6.768644810
准确率: 0.4375
Epoch 500/500 模型保存成功
训练完成
['./bin/face_train_160_tf']
开始读取lable:
Tensor("data_augmentation/Cast:0", shape=(?,), dtype=int32)
读取数据完成!
<class 'face_image_input.read_cifar10.<locals>.CIFAR10Record'>
Filling queue with 203 CIFAR images before starting to train. This will take a few minutes.
shuffle1111
开始读取lable:
Tensor("input/Cast:0", shape=(?,), dtype=int32)
shuffle0000
Model restored.
原始测试图片信息: (64, 160, 160, 3) (64,)
预测结果为: [1 2 1 1 2 3 4 2 1 1 2 0 3 2 0 4 4 2 2 1 4 2 2 2 1 4 4 2 2 1 1 2 4 1 2 1 1
2 3 4 2 1 0 2 2 3 0 4 2 2 1 1 4 4 1 2 4 2 4 4 4 2 2 2]
实际结果为: [0 0 1 0 0 0 1 2 1 1 2 2 2 1 2 2 3 3 2 2 4 2 2 2 4 4 4 0 1 1 1 2 4 4 4 0 0
0 0 1 2 1 2 2 2 2 2 2 3 2 4 2 4 3 4 4 4 1 4 4 1 2 2 0]
准确率为: 0.421875

3.5

Epoch 1000/1000 Test cost 20.401565552
准确率: 0.375
Epoch 1000/1000 模型保存成功
训练完成
['./bin/face_train_160_tf']
开始读取lable:
Tensor("data_augmentation/Cast:0", shape=(?,), dtype=int32)
读取数据完成!
<class 'face_image_input.read_cifar10.<locals>.CIFAR10Record'>
Filling queue with 203 CIFAR images before starting to train. This will take a few minutes.
shuffle1111
开始读取lable:
Tensor("input/Cast:0", shape=(?,), dtype=int32)
shuffle0000
Model restored.
原始测试图片信息: (64, 160, 160, 3) (64,)
预测结果为: [1 2 4 1 1 4 0 0 4 1 2 4 0 2 4 1 2 2 1 2 2 2 3 2 4 4 2 2 4 4 1 4 1 2 1 4 0
0 4 1 2 0 2 4 1 4 2 1 2 2 3 2 2 4 2 4 2 4 2 2 1 4 1 4]
实际结果为: [0 0 0 0 1 0 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 2 4 4 4 4 4 4 4 0 0 0 0 1 0 1
1 1 1 2 2 2 2 2 2 2 2 2 2 2 3 3 4 4 4 4 4 0 4 0 4 0 0]
准确率为: 0.34375

参考资料

Inception-ResNet-v1

[1] 深度学习--Inception-ResNet-v1网络结构
[2] ResNet-V1-50卷积神经网络迁移学习进行不同品种的花的分类识别
[3] 【Tensorflow系列】使用Inception_resnet_v2训练自己的数据集并用Tensorboard监控
[4] 使用TensorFlow打造自己的图像识别模型
[5] tensorflow实现迁移学习 此例程出自《TensorFlow实战Google深度学习框架》6.5.2小节 卷积神经网络迁移学习

官方代码

[1] davidsandberg/facenet
[2] Classifier training of inception resnet v1
[3] facenet/src/models/inception_resnet_v1.py

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容