参考博客:https://cosx.org/2017/10/transfer-learning/


下面的例子中将示范如何将一个图像识别的深度卷积网络,VGG,迁移到识别花朵类型的新任务上,在原先的任务中,VGG 只能识别花,但是迁移学习可以让模型不但能识别花,还能识别花的具体品种。

VGG 介绍

VGG 的两个版本分别是 16 层网络版和 19 层网络版。VGG 的输入数据格式是 224 * 224 * 3 的像素数据,经过一系列的卷积神经网络和池化网络处理之后,输出的是一个 4096 维的特征数据,然后再通过 3 层全连接的神经网络处理,最终由 softmax 规范化得到分类结果。VGG模型是一个. npy 文件,本质上是一个巨大的 numpy 对象,包含了 VGG16 模型中的所有参数,该文件大约有 500M,所以可见如果是从头训练这样一个模型是非常耗时的,借助于迁移学习的思想,我们可以直接在这个模型的基础上进行训练。

在接下来的迁移学习实践中,我们会采用稍微简单的一些的 VGG16,他和 VGG19 有几乎完全一样的准确度,但是运算起来更快一些。

VGG 的结构图如下:

搭建属于自己的识花网络

整体思路:

首先我们会将所有的图片交给 VGG16,利用 VGG16 的深度网络结构中的五轮卷积网络层和池化层,对每张图片得到一个 4096 维的特征向量,然后我们直接用这个特征向量替代原来的图片,再加若干层全连接的神经网络,对花朵数据集进行训练。因此本质上,我们是将 VGG16 作为一个图片特征提取器,然后在此基础上再进行一次普通的神经网络学习,这样就将原先的 224 * 224 * 3 维度的数据转化为了 4096 维的,而每一维度的信息量大大提高,从而大大降低了计算资源的消耗,实现了把学习物体识别中得到的知识应用到特殊的花朵分类问题上。

代码存放位置:/home/wei/MyPaperCode/recognizeFlowersBaseOnDeeplearningAndTransferLearning

#导入需要用的 python 模块
import os
import numpy as np
import tensorflow as tf#从文件夹中导入文件
from tensorflow_vgg import vgg16
from tensorflow_vgg import utils#加载识花数据集。接下来我们将 flower_photos 文件夹中的花朵图片都载入到进来,并且用图片所在的子文件夹作为标签值。data_dir = 'flower_photos/'
#返回文件夹中,子文件及子文件夹 名称的列表,contents为['tulips', 'dandelion', 'LICENSE.txt', 'roses', 'sunflowers', 'daisy']
contents = os.listdir(data_dir)
#去掉子文件的名称,只保留子文件夹的名称
classes = [each for each in contents if os.path.isdir(data_dir + each)]
#classes即为['tulips', 'dandelion', 'roses', 'sunflowers', 'daisy']
#利用 VGG16 计算得到特征值# 首先设置计算batch的值,如果运算平台的内存越大,这个值可以设置得越高
batch_size = 10
# 用codes_list来存储特征值
codes_list = []
# 用labels来存储花的类别
labels = []
# batch数组用来临时存储图片数据
batch = []codes = Nonewith tf.Session() as sess:# 构建VGG16模型对象vgg = vgg16.Vgg16()  #调用vgg16文件中的Vgg16()input_ = tf.placeholder(tf.float32, [None, 224, 224, 3])with tf.name_scope("content_vgg"):# 载入VGG16模型vgg.build(input_)# 对每个不同种类的花分别用VGG16计算特征值for each in classes:print("Starting {} images".format(each))class_path = data_dir + eachfiles = os.listdir(class_path)for ii, file in enumerate(files, 1):# 载入图片并放入batch数组中img = utils.load_image(os.path.join(class_path, file)) #此时224*224*3batch.append(img.reshape((1, 224, 224, 3))) #添加到batch数组中labels.append(each)# 如果图片数量到了batch_size则开始具体的运算if ii % batch_size == 0 or ii == len(files):images = np.concatenate(batch)#沿现有轴加入数组序列feed_dict = {input_: images}# 计算特征值codes_batch = sess.run(vgg.relu6, feed_dict=feed_dict)# 将结果放入到codes数组中if codes is None:codes = codes_batchelse:codes = np.concatenate((codes, codes_batch))# 清空数组准备下一个batch的计算batch = []print('{} images processed'.format(ii))#以上我们就可以得到一个 codes 数组,和一个 labels 数组,分别存储了所有花朵的特征值和类别#用如下的代码将这两个数组保存到硬盘上
with open('codes', 'w') as f:codes.tofile(f)import csv
with open('labels', 'w') as f:writer = csv.writer(f, delimiter='\n')writer.writerow(labels)

以上代码讲解:

enumerate()枚举

myfiles = ['A', 'B', 'C']
for nn in enumerate(myfiles, 1):  #1表示序号从1开始print(nn)for mm, myfile in enumerate(myfiles, 5):  #5表示序号从5开始print(mm)print(myfile)

输出为:

(1, 'A')
(2, 'B')
(3, 'C')
5
A
6
B
7
C    

os.path.join()函数

语法:  os.path.join(path1[,path2[,......]])

返回值:将多个路径组合后返回

注:第一个绝对路径之前的参数将被忽略

os.path.join(class_path, file)表示的是路径,比如class_path = flower_photos/tulips, file = 111.jpg时其表示为flower_photos/tulips/111.jpg

print('{} images processed'.format(ii))

往字符串'{} images processed'中传入数据,ii为50时输出为 50 images processed


#准备训练集,验证集和测试集
#首先把 labels 数组中的分类标签用 One Hot Encode 的方式替换。from sklearn.preprocessing import LabelBinarizerlb = LabelBinarizer()
lb.fit(labels)labels_vecs = lb.transform(labels)

labels为       ['tulips', 'tulips', 'tulips',......., 'daisy', 'daisy']

labels_vecs为

[[0 0 0 0 1][0 0 0 0 1][0 0 0 0 1]...[1 0 0 0 0][1 0 0 0 0][1 0 0 0 0]]
# 接下来就是抽取数据,因为不同类型的花的数据数量并不是完全一样的,而且 labels 数组中的数据也还没有被打乱,所
# 以最合适的方法是使用 StratifiedShuffleSplit 方法来进行分层随机划分。假设我们使用训练集:验证集:测试集
# = 8:1:1,那么代码如下:from sklearn.model_selection import StratifiedShuffleSplitss = StratifiedShuffleSplit(n_splits=1, test_size=0.2)train_idx, val_idx = next(ss.split(codes, labels))half_val_len = int(len(val_idx)/2)
val_idx, test_idx = val_idx[:half_val_len], val_idx[half_val_len:]train_x, train_y = codes[train_idx], labels_vecs[train_idx]
val_x, val_y = codes[val_idx], labels_vecs[val_idx]
test_x, test_y = codes[test_idx], labels_vecs[test_idx]print("Train shapes (x, y):", train_x.shape, train_y.shape)#x表示特征图,y表示labels
print("Validation shapes (x, y):", val_x.shape, val_y.shape)
print("Test shapes (x, y):", test_x.shape, test_y.shape)

输出为:

('Train shapes (x, y):', (2936, 4096), (2936, 5))
('Validation shapes (x, y):', (367, 4096), (367, 5))
('Test shapes (x, y):', (367, 4096), (367, 5))

next()函数: 返回迭代器的下一个项目。

# 分好了数据集之后,就可以开始对数据集进行训练了,假设我们使用一个 256 维的全连接层,一个 5 维的全连接层
#(因为我们要分类五种不同类的花朵),和一个 softmax 层。当然,这里的网络结构可以任意修改,你可以不断尝试
# 其他的结构以找到合适的结构。# 输入数据的维度
inputs_ = tf.placeholder(tf.float32, shape=[None, codes.shape[1]])
# 标签数据的维度
labels_ = tf.placeholder(tf.int64, shape=[None, labels_vecs.shape[1]])# 加入一个256维的全连接的层
fc = tf.contrib.layers.fully_connected(inputs_, 256)# 加入一个5维的全连接层
logits = tf.contrib.layers.fully_connected(fc, labels_vecs.shape[1], activation_fn=None)# 计算cross entropy值
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=labels_, logits=logits)# 计算损失函数
cost = tf.reduce_mean(cross_entropy)# 采用用得最广泛的AdamOptimizer优化器
optimizer = tf.train.AdamOptimizer().minimize(cost)# 得到最后的预测分布
predicted = tf.nn.softmax(logits)# 计算准确度
correct_pred = tf.equal(tf.argmax(predicted, 1), tf.argmax(labels_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
print(shape(l))#输出l的行列值
print(l.shape[0])#输出l的行数值
print(l.shape[1])#输出l的列数值
tf.contrib.layers.fully_connected(inputs, num_outputs, activation_fn=None)这个函数就是全链接成层,inputs是输入,num_outputs是下一层单元的个数,activation_fn是激活函数

迁移学习1——基于深度学习和迁移学习的识花实践相关推荐

  1. 【深度学习】基于深度神经网络进行权重剪枝的算法(二)

    [深度学习]基于深度神经网络进行权重剪枝的算法(二) 文章目录 1 摘要 2 介绍 3 OBD 4 一个例子 1 摘要 通过从网络中删除不重要的权重,可以有更好的泛化能力.需求更少的训练样本.更少的学 ...

  2. 【深度学习】基于深度神经网络进行权重剪枝的算法(一)

    [深度学习]基于深度神经网络进行权重剪枝的算法(一) 1 pruning 2 代码例子 3 tensorflow2 keras 权重剪裁(tensorflow-model-optimization)3 ...

  3. 学习分享——基于深度学习的NILM负荷分解(四)深度学习实现,代码讲解

    QQ群1070535031 跟随上一篇的思路,本篇我们来实现整个流程. 实验需求 跟随本文进行学习和实验,需要前面博文中的环境,以及提取出来的UK数据.(学习分享--基于深度学习的NILM负荷分解(二 ...

  4. 学习分享——基于深度学习的NILM负荷分解(三)深度学习处理,基础思路

    我来继续填坑了~~ 给大家两周时间自习深度学习(磨蹭了两周) 不知道同学们的基础打得如何了哈 QQ群1070535031 我分两篇写网络训练的相关,本文介绍整个思路流程,下一篇提供实操代码和相关注释讲 ...

  5. 学习分享——基于深度学习的NILM负荷分解(二)电器数据提取

    前一阵参加比赛,NILM就放了放,开始填坑... GOGOGO~ 数据准备 根据上一篇中提到的,我这里使用的是UK-DALE 没有下载的同学可以回到上一篇看一下(学习分享--基于深度学习的NILM负荷 ...

  6. 基于深度学习和迁移学习的识花实践

    深度学习是人工智能领域近年来最火热的话题之一,但是对于个人来说,以往想要玩转深度学习除了要具备高超的编程技巧,还需要有海量的数据和强劲的硬件.不过 TensorFlow 和 Keras 等框架的出现大 ...

  7. 【深度学习】基于深度学习的目标检测研究进展

    原文出处:http://chuansong.me/n/353443351445 开始本文内容之前,我们先来看一下上边左侧的这张图,从图中你看到了什么物体?他们在什么位置?这还不简单,图中有一个猫和一个 ...

  8. 三维重建 几何方法 深度学习_基于深度学习的三维重建算法:MVSNet、RMVSNet、PointMVSNet、Cascade系列...

    欢迎关注微信公众号"3D视觉学习笔记",分享博士期间3D视觉学习收获 MVSNet:香港科技大学的权龙教授团队的MVSNet(2018年ECCV)开启了用深度做多视图三维重建的先河 ...

  9. 学习分享——基于深度学习的NILM负荷分解(一)对DL的看法准备工作

    好啦,我来填坑啦哈哈 经过了几个月的对深度学习的学习.了解和实践, 对于用深度学习来做NILM的经验也是积累了不少. 在此,做以小结. 在此,感谢~柳柳,小张,小田,小刘的支持和鼓励. 话不多说,下面 ...

最新文章

  1. 【 C 】高级字符串查找之查找标记(token)函数 strtok介绍
  2. python中文叫什么意思-python中文读什么
  3. UVA 10245 The Closest Pair Problem
  4. PHP默认识别的数据类型是application/x-www.form-urlencoded标准的数据类型
  5. java封装的快捷_Fast-boot:针对SpringBoot 封装的一系列的快捷包
  6. Ubuntu 12.04 如何切换回英文
  7. 在浏览器中进行深度学习:TensorFlow.js (十二)异常检测算法
  8. 微智魔盒骗局_微智魔盒官宣
  9. 局域主机做服务器,安装DNN,外网访问的解决办法
  10. 【名额有限】云开发AI拓展能力等你来体验!
  11. 剑指Offer - 面试题54. 二叉搜索树的第k大节点(二叉树循环遍历)
  12. mysql5.7.28下载_MySql5.7.28下载、安装、登陆详解
  13. tar 命令详解 / xz 命令
  14. linux postgresql 恢复数据库,PostgreSQL数据库备份和恢复
  15. Spring IoC-02
  16. 游戏策划关于游戏概念和游戏原型设计
  17. vue.js毕业设计,基于vue.js前后端分离电影院售票小程序系统设计与实现
  18. Oracle中并行parallel详解
  19. VC删除IE缓存、COOKIE及浏览记录
  20. NR PRACH (七)Type 2(2-step) RA 参数及相关规定

热门文章

  1. 如何自学python知乎-如何快速学习python?
  2. python与office结合可以干什么-python与office(一)
  3. 一种连续语音识别系统的制作方法
  4. java 可变 不可变_java中的不可变类型的探究
  5. Vue动态设置Style属性
  6. 在设备上添加项目失败_使用VisualGDB将Keil项目导入VisualStudio
  7. Red5开发第一步-Hello World
  8. 华为摄像头搜索软件_华为Mate 40 Pro评测:硬件和软件表现都近乎完美
  9. 存数据返回他的序列号id_雪花般的分布式唯一ID雪花算法
  10. php列表顺序,保存列表的顺序(php / zend / jquery)