上一篇博客【用tensorflow迁移学习猫狗分类】笔者讲到用tensorlayer的【VGG16模型】迁移学习图像分类,那麽问题来了,tensorlayer没提供的模型怎么办呢?别担心,tensorlayer提供了tensorflow中的【slim模型】导入功能,代码例子在tutorial_inceptionV3_tfslim
  那么什么是slim?slim到底有什么用?
slim是一个使构建,训练,评估神经网络变得简单的库。它可以消除原生tensorflow里面很多重复的模板性的代码,让代码更紧凑,更具备可读性。另外slim提供了很多计算机视觉方面的著名模型(VGG, AlexNet等),我们不仅可以直接使用,甚至能以各种方式进行扩展。(笔者注:总之功能跟tensorlayer差不多嘛)更多介绍可以看这篇文章:【Tensorflow】辅助工具篇——tensorflow slim(TF-Slim)介绍
  要进行迁移学习,首先需要slim模型代码以及预训练好的权重参数,这些谷歌都有提供下载,可以看到主页下面有各个模型以及在imagenet训练集下的参数地址。

列表还列出了各个模型的top1、top5的正确率,模型很多了。
  好了我们下载Inception-ResNet-v2以及inception_resnet_v2_2016_08_30.tar.gz,py文件和解压出来的.ckpt文件放到项目根目录下面。至于为什么不用tensorlayer例子提供的Inception V3?因为Inception-ResNet-v2正确率高啊。(哈哈真正原因最后来讲)。
  我们依旧进行猫狗分类,按照教程导入模型修改num_classes再导入训练数据,直接训练是会报错的,因为最后的Logits层几个参数在恢复时维度不匹配。
最后几个参数是不能恢复了,笔者也没有找到选择性恢复.ckpt参数的tensorflow方法。怎么办呢?幸好群里面有位朋友提供了一个方法,参见【Tensorflow 迁移学习】:

主要思想是:先把所有.ckpt参数恢复成npz格式,再选择恢复npz中的参数,恢复npz中的参数就跟前一篇博客操作一样的了。
所以整个过程分两步走:
1.将参数恢复然后保存为npz格式:
  下面是具体代码:

  1. import os
  2. import time
  3. from recordutil import *
  4. import numpy as np
  5. # from tensorflow.contrib.slim.python.slim.nets.resnet_v2 import resnet_v2_152
  6. # from tensorflow.contrib.slim.python.slim.nets.vgg import vgg_16
  7. import skimage
  8. import skimage.io
  9. import skimage.transform
  10. import tensorflow as tf
  11. from tensorlayer.layers import *
  12. # from scipy.misc import imread, imresize
  13. # from tensorflow.contrib.slim.python.slim.nets.alexnet import alexnet_v2
  14. from inception_resnet_v2 import (inception_resnet_v2_arg_scope, inception_resnet_v2)
  15. from scipy.misc import imread, imresize
  16. from tensorflow.python.ops import variables
  17. import tensorlayer as tl
  18.  
  19. slim = tf.contrib.slim
  20. try:
  21. from data.imagenet_classes import *
  22. except Exception as e:
  23. raise Exception(
  24. "{} / download the file from: https://github.com/zsdonghao/tensorlayer/tree/master/example/data".format(e))
  25.  
  26. n_epoch = 200
  27. learning_rate = 0.0001
  28. print_freq = 2
  29. batch_size = 32
  30. ## InceptionV3 / All TF-Slim nets can be merged into TensorLayer
  31. x = tf.placeholder(tf.float32, shape=[None, 299, 299, 3])
  32. # 输出
  33. y_ = tf.placeholder(tf.int32, shape=[None, ], name='y_')
  34. net_in = tl.layers.InputLayer(x, name='input_layer')
  35. with slim.arg_scope(inception_resnet_v2_arg_scope()):
  36. network = tl.layers.SlimNetsLayer(
  37. prev_layer=net_in,
  38. slim_layer=inception_resnet_v2,
  39. slim_args={
  40. 'num_classes': 1001,
  41. 'is_training': True,
  42. },
  43. name='InceptionResnetV2' # <-- the name should be the same with the ckpt model
  44. )
  45. # network = fc_layers(net_cnn)
  46. sess = tf.InteractiveSession()
  47. network.print_params(False)
  48. # network.print_layers()
  49. saver = tf.train.Saver()
  50.  
  51. # 加载预训练的参数
  52. # tl.files.assign_params(sess, npz, network)
  53.  
  54. tl.layers.initialize_global_variables(sess)
  55.  
  56. saver.restore(sess, "inception_resnet_v2.ckpt")
  57. print("Model Restored")
  58. all_params = sess.run(network.all_params)
  59. np.savez('inception_resnet_v2.npz', params=all_params)
  60. sess.close()

  执行成功之后,我们得到模型所有的908个参数。
2.部分恢复npz参数然后训练模型:
  首先我们修改模型最后一层参数,由于进行的是2分类学习,所以做如下修改:

  1. with slim.arg_scope(inception_resnet_v2_arg_scope()):
  2. network = tl.layers.SlimNetsLayer(
  3. prev_layer=net_in,
  4. slim_layer=inception_resnet_v2,
  5. slim_args={
  6. 'num_classes': 2,
  7. 'is_training': True,
  8. },
  9. name='InceptionResnetV2' # <-- the name should be the same with the ckpt model
  10. )

  num_classes改为2,is_training为True。
  接着定义输入输出以及损失函数:

  1. sess = tf.InteractiveSession()
  2. # saver = tf.train.Saver()
  3. y = network.outputs
  4. y_op = tf.argmax(tf.nn.softmax(y), 1)
  5. cost = tl.cost.cross_entropy(y, y_, name='cost')
  6. correct_prediction = tf.equal(tf.cast(tf.argmax(y, 1), tf.float32), tf.cast(y_, tf.float32))
  7. acc = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

  下面是定义训练参数,我们只训练最后一层的参数,打印参数出来我们看到:

  1. [TL] param 900: InceptionResnetV2/AuxLogits/Conv2d_2a_5x5/weights:0 (5, 5, 128, 768) float32_ref
  2. [TL] param 901: InceptionResnetV2/AuxLogits/Conv2d_2a_5x5/BatchNorm/beta:0 (768,) float32_ref
  3. [TL] param 902: InceptionResnetV2/AuxLogits/Conv2d_2a_5x5/BatchNorm/moving_mean:0 (768,) float32_ref
  4. [TL] param 903: InceptionResnetV2/AuxLogits/Conv2d_2a_5x5/BatchNorm/moving_variance:0 (768,) float32_ref
  5. [TL] param 904: InceptionResnetV2/AuxLogits/Logits/weights:0 (768, 2) float32_ref
  6. [TL] param 905: InceptionResnetV2/AuxLogits/Logits/biases:0 (2,) float32_ref
  7. [TL] param 906: InceptionResnetV2/Logits/Logits/weights:0 (1536, 2) float32_ref
  8. [TL] param 907: InceptionResnetV2/Logits/Logits/biases:0 (2,) float32_ref
  9. [TL] num of params: 56940900

  从param 904开始训练就行了,参数恢复到param 903
  下面是训练函数以及恢复部分参数,加载样本数据:

  1. # 定义 optimizer
  2. train_params = network.all_params[904:]
  3. print('训练参数:', train_params)
  4. # # 加载预训练的参数
  5. # tl.files.assign_params(sess, params, network)
  6. train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost, var_list=train_params)
  7. img, label = read_and_decode("D:\\001-Python\\train299.tfrecords")
  8. # 使用shuffle_batch可以随机打乱输入
  9. X_train, y_train = tf.train.shuffle_batch([img, label],
  10. batch_size=batch_size, capacity=200,
  11. min_after_dequeue=100)
  12. tl.layers.initialize_global_variables(sess)
  13. params = tl.files.load_npz('', 'inception_resnet_v2.npz')
  14. params = params[0:904]
  15. print('当前参数大小:', len(params))
  16. tl.files.assign_params(sess, params=params, network=network)

  下面依旧是训练模型的代码,跟上一篇一样:

  1. # # 训练模型
  2. coord = tf.train.Coordinator()
  3. threads = tf.train.start_queue_runners(sess=sess, coord=coord)
  4. step = 0
  5. filelist = getfilelist()
  6. for epoch in range(n_epoch):
  7. start_time = time.time()
  8. val, l = sess.run([X_train, y_train])#next_data(filelist, batch_size) #
  9. for X_train_a, y_train_a in tl.iterate.minibatches(val, l, batch_size, shuffle=True):
  10. sess.run(train_op, feed_dict={x: X_train_a, y_: y_train_a})
  11. if epoch + 1 == 1 or (epoch + 1) % print_freq == 0:
  12. print("Epoch %d of %d took %fs" % (epoch + 1, n_epoch, time.time() - start_time))
  13. train_loss, train_acc, n_batch = 0, 0, 0
  14. for X_train_a, y_train_a in tl.iterate.minibatches(val, l, batch_size, shuffle=True):
  15. err, ac = sess.run([cost, acc], feed_dict={x: X_train_a, y_: y_train_a})
  16. train_loss += err
  17. train_acc += ac
  18. n_batch += 1
  19. print(" train loss: %f" % (train_loss / n_batch))
  20. print(" train acc: %f" % (train_acc / n_batch))
  21. # tl.files.save_npz(network.all_params, name='model_vgg_16_2.npz', sess=sess)
  22. coord.request_stop()
  23. coord.join(threads)

  batchsize为20训练200代,部分结果如下:

  1. Epoch 156 of 200 took 12.568609s
  2. train loss: 0.382517
  3. train acc: 0.950000
  4. Epoch 158 of 200 took 12.457161s
  5. train loss: 0.382509
  6. train acc: 0.850000
  7. Epoch 160 of 200 took 12.385407s
  8. train loss: 0.320393
  9. train acc: 1.000000
  10. Epoch 162 of 200 took 12.489218s
  11. train loss: 0.480686
  12. train acc: 0.700000
  13. Epoch 164 of 200 took 12.388841s
  14. train loss: 0.329189
  15. train acc: 0.850000
  16. Epoch 166 of 200 took 12.446472s
  17. train loss: 0.379127
  18. train acc: 0.900000
  19. Epoch 168 of 200 took 12.888571s
  20. train loss: 0.365938
  21. train acc: 0.900000
  22. Epoch 170 of 200 took 12.850605s
  23. train loss: 0.353434
  24. train acc: 0.850000
  25. Epoch 172 of 200 took 12.855129s
  26. train loss: 0.315443
  27. train acc: 0.950000
  28. Epoch 174 of 200 took 12.906666s
  29. train loss: 0.460817
  30. train acc: 0.750000
  31. Epoch 176 of 200 took 12.830738s
  32. train loss: 0.421025
  33. train acc: 0.900000
  34. Epoch 178 of 200 took 12.852572s
  35. train loss: 0.418784
  36. train acc: 0.800000
  37. Epoch 180 of 200 took 12.951322s
  38. train loss: 0.316057
  39. train acc: 0.950000
  40. Epoch 182 of 200 took 12.866213s
  41. train loss: 0.363328
  42. train acc: 0.900000
  43. Epoch 184 of 200 took 13.012520s
  44. train loss: 0.379462
  45. train acc: 0.850000
  46. Epoch 186 of 200 took 12.934583s
  47. train loss: 0.472857
  48. train acc: 0.750000
  49. Epoch 188 of 200 took 13.038168s
  50. train loss: 0.236005
  51. train acc: 1.000000
  52. Epoch 190 of 200 took 13.056378s
  53. train loss: 0.266042
  54. train acc: 0.950000
  55. Epoch 192 of 200 took 13.016137s
  56. train loss: 0.255430
  57. train acc: 0.950000
  58. Epoch 194 of 200 took 13.013147s
  59. train loss: 0.422342
  60. train acc: 0.900000
  61. Epoch 196 of 200 took 12.980659s
  62. train loss: 0.353984
  63. train acc: 0.900000
  64. Epoch 198 of 200 took 13.033676s
  65. train loss: 0.320018
  66. train acc: 0.950000
  67. Epoch 200 of 200 took 12.945982s
  68. train loss: 0.288049
  69. train acc: 0.950000

  好了,迁移学习Inception-ResNet-v2结束。
  作者说SlimNetsLayer是能导入任何Slim Model的。笔者已经验证过导入Inception-ResNet-v2和VGG16成功,Inception V3导入后训练了两三天,正确率一直在10到70之间波动(跟笔者的心情一样不稳定),笔者一直找不出原因,心累,希望哪位朋友再去验证一下Inception V3咯。

用tensorlayer导入Slim模型迁移学习的更多相关文章

  1. 第二十四节,TensorFlow下slim库函数的使用以及使用VGG网络进行预训练、迁移学习(附代码)

    在介绍这一节之前,需要你对slim模型库有一些基本了解,具体可以参考第二十二节,TensorFlow中的图片分类模型库slim的使用.数据集处理,这一节我们会详细介绍slim模型库下面的一些函数的使用 ...

  2. Gluon炼丹(Kaggle 120种狗分类,迁移学习加双模型融合)

    这是在kaggle上的一个练习比赛,使用的是ImageNet数据集的子集. 注意,mxnet版本要高于0.12.1b2017112. 下载数据集. train.zip test.zip labels ...

  3. 基于深度学习和迁移学习的识花实践——利用 VGG16 的深度网络结构中的五轮卷积网络层和池化层,对每张图片得到一个 4096 维的特征向量,然后我们直接用这个特征向量替代原来的图片,再加若干层全连接的神经网络,对花朵数据集进行训练(属于模型迁移)

    基于深度学习和迁移学习的识花实践(转)   深度学习是人工智能领域近年来最火热的话题之一,但是对于个人来说,以往想要玩转深度学习除了要具备高超的编程技巧,还需要有海量的数据和强劲的硬件.不过 Tens ...

  4. 1 如何使用pb文件保存和恢复模型进行迁移学习(学习Tensorflow 实战google深度学习框架)

    学习过程是Tensorflow 实战google深度学习框架一书的第六章的迁移学习环节. 具体见我提出的问题:https://www.tensorflowers.cn/t/5314 参考https:/ ...

  5. 基于TensorFlow Object Detection API进行迁移学习训练自己的人脸检测模型(二)

    前言 已完成数据预处理工作,具体参照: 基于TensorFlow Object Detection API进行迁移学习训练自己的人脸检测模型(一) 设置配置文件 新建目录face_faster_rcn ...

  6. ML.NET 示例:图像分类模型训练-首选API(基于原生TensorFlow迁移学习)

    ML.NET 版本 API 类型 状态 应用程序类型 数据类型 场景 机器学习任务 算法 Microsoft.ML 1.5.0 动态API 最新 控制台应用程序和Web应用程序 图片文件 图像分类 基 ...

  7. PV3D学习笔记-导入DAE模型

      网上关于PV3D导入DAE模型的例子都非常多,可惜我研究了半天,一个都没成功,或者是破面问题,或者是贴图不显示,再或者贴图乱掉了.今天晚上终于搞定,心得发上来. 制作模型的软件是SketchUp ...

  8. 【深度学习系列】迁移学习Transfer Learning

    在前面的文章中,我们通常是拿到一个任务,譬如图像分类.识别等,搜集好数据后就开始直接用模型进行训练,但是现实情况中,由于设备的局限性.时间的紧迫性等导致我们无法从头开始训练,迭代一两百万次来收敛模型, ...

  9. 用tensorflow迁移学习猫狗分类

    笔者这几天在跟着莫烦学习TensorFlow,正好到迁移学习(至于什么是迁移学习,看这篇),莫烦老师做的是预测猫和老虎尺寸大小的学习.作为一个有为的学生,笔者当然不能再预测猫啊狗啊的大小啦,正好之前正 ...

随机推荐

  1. XSS和CSRF的理解

    声明:转自 http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html XSS攻击:跨站脚本攻击(Cross Site Scripting ...

  2. 谈谈spring-boot不同包结构下,同样的类名冲突导致服务启动失败解决方案

    项目背景: 某日,有需求要在三天的时间内完成两个大项目的项目合并,因为之前两个项目的包结构和类名都很多相同,于是开始考虑使用加一级包进行隔离,类似于这种结构 但是在启动的过程中,抛出来这样的异常: C ...

  3. css常见属性

    css常见属性 1.颜色属性 1.1 color属性定义文本的颜色 1.2 color:green 1.3 color:#ff6600 可简写为#f60 1.4 color:rgb(255,255,2 ...

  4. view-xpath

    https://addons.mozilla.org/en-US/firefox/ WebDriver Element Locator

  5. JS面向对象特性和值类型与复合类型

      JS面向对象之特性已经值类型与复合类型 一些属性 空对象 空对象也是对象, 只是有存变量的变量名, 没有对象属性 var o ={}; 参数传递 值类型: 函数内外两个变量, 两个数据, 都不相同 ...

  6. hue集成hive访问报database is locked

    这个问题这应该是hue默认的SQLite数据库出现错误,你可以使用mysql postgresql等来替换 hue默认使用sqlite作为元数据库,不推荐在生产环境中使用.会经常出现database ...

  7. 申请安装阿里云免费SSL证书

    微信小程序已经全面要求使用HTTPS服务了,还有苹果商店也是,所以,实现网站HTTPS已经很有必要.要实现HTTPS就需要一个SSL证书,证书大部分都很贵,不过也有一些免费的证书服务供个人开发者使用. ...

  8. python打包工具distutils、setuptools分析

    在上一篇博文中总结了python中导入包,安装包一条完整的线路.其中有一个有意思的知识点,安装包的方式有很多种,模块和包管理中打包,发布,安装也是值得研究的内容. python中安装包的方式有很多种: ...

  9. 2018.4.16Spring.Net入门学习内容

    三大方面: IoC:Inversion of Control 控制翻转:就是创建对象的权利由开发人员自己控制New,转到了由容器来控制. DI:Dependency InjectionIt is a ...

  10. 是否有必要学习使用纯Verilog写一个SDRAM控制器

    在做这个SDRAM控制器之前,博主有一个疑问,对于学生来说,是否有必要学习用纯Verilog写一个SDRAM控制器?因为目前X家和A家都有了DDR IP Core,对于要实现一个应用可以直接调用IP ...