运行环境

python3.6.3、tensorflow1.10.0

Intel@AIDevCloud:Intel Xeon Gold 6128 processors集群

数据和模型来源

思路

数据集分析及处理

数据集文件解压后共有五个文件夹,每个文件夹都包含一定数量的花的图片,一个文件夹对应一个品种,图片各种尺寸都有,均为jpg格式,均为彩色图片。这里利用tensorflow提供的图片处理工具将所有图片转为300×300×3的格式,然后将所有图片的80%当作训练集,10%当作验证集,10%当作测试集,并且将训练集进行随机打乱,将得到的数据存在一个numpy文件中,以待后续训练使用。

模型构建

这里采用了ResNet-V1-50卷积神经网络来进行训练,模型结构在slim中都提供好了,另外采用官方已经训练好的参数进行迁移学习,只是在模型的最后根据问题的实际需要再定义一层输出层,只训练最后的自定义的全连接输出层的参数,训练500次,每次batch样本数取32,学习率取0.0001。

源代码

load_data.py

# -*- coding: UTF-8 -*-

#Author:Yinli

import glob

import os.path

import numpy as np

import tensorflow as tf

from tensorflow.python.platform import gfile

#定义输入文件夹和数据存储文件名

INPUT_DATA = 'flower_photos'

OUTPUT_FILE = 'flower_processed_data.npy'

#设定验证集和测试集的百分比

VALIDATION_PERCENTAGE = 10

TEST_PERCENTAGE = 10

def create_image_list(sess, testing_percentage, validation_percentage):

#列出输入文件夹下的所有子文件夹,此时sub_dirs里面除了有子文件夹还有它自身,在第一个

sub_dirs = [x[0] for x in os.walk(INPUT_DATA)]

#设置一个bool值,指定第一次循环的时候跳过母文件夹

is_root_dir = True

#print(sub_dirs)

#初始化数据矩阵

training_images = []

training_labels = []

testing_images = []

testing_labels = []

validation_images = []

validation_labels= []

current_label = 0

#分别处理每个子文件夹

for sub_dir in sub_dirs:

#跳过第一个值,即跳过母文件夹

if is_root_dir:

is_root_dir = False

continue

#获取子目录中的所有图片文件

extensions = ['jpg', 'jpeg', 'JPG', 'JPEG']

#用列表记录所有图片文件

file_list = []

#获取此子目录的名字比如daisy

dir_name = os.path.basename(sub_dir)

#对此子目录中所有图片后缀的文件

for extension in extensions:

#获取每种图片的所有正则表达式

file_glob = os.path.join(INPUT_DATA, dir_name, '*.' + extension)

print(file_glob)

#将所有符合正则表达式的文件名加入文件列表

file_list.extend(glob.glob(file_glob))

print(file_list)

#如果没有文件跳出循环

if not file_list:

continue

print("processing ", dir_name)

i = 0

#对于每张图片

for file_name in file_list:

i+=1

#打开图片文件

#print("process num : ",i," processing", file_name, file=f)

image_raw_data = gfile.FastGFile(file_name,'rb').read()

#解码

image = tf.image.decode_jpeg(image_raw_data)

#如果图片格式不是float32则转为float32

if image.dtype != tf.float32:

image = tf.image.convert_image_dtype(image, dtype=tf.float32)

#将图片源数据转为299*299

image = tf.image.resize_images(image, [300,300])

#得到此图片的数据

image_value = sess.run(image)

print(np.shape(image_value))

#生成一个100以内的数

chance = np.random.randint(100)

#按概率随机分到三个数据集中

if chance < validation_percentage:

validation_images.append(image_value)

validation_labels.append(current_label)

elif chance < (testing_percentage + validation_percentage):

testing_images.append(image_value)

testing_labels.append(current_label)

else:

training_images.append(image_value)

training_labels.append(current_label)

if i%200 == 0:

print("processing...")

#处理完此种品种就将标签+1

current_label += 1

#将训练数据和标签以同样的方式打乱

state = np.random.get_state()

np.random.shuffle(training_images)

np.random.set_state(state)

np.random.shuffle(training_labels)

#返回所有数据

return np.asarray([training_images, training_labels,

validation_images, validation_labels, testing_images, testing_labels])

def main():

with tf.Session() as sess:

processed_data = create_image_list(sess, TEST_PERCENTAGE, VALIDATION_PERCENTAGE)

#将数据存到文件中

np.save(OUTPUT_FILE, processed_data)

if __name__ == "__main__":

main()

resnet.py

# -*- coding: UTF-8 -*-

# Author:Yinli

import numpy as np

import tensorflow as tf

import tensorflow.contrib.slim as slim

# 加载通过slim定义好的resnet_v1模型

import tensorflow.contrib.slim.python.slim.nets.resnet_v1 as resnet_v1

# 数据文件

INPUT_DATA = "./flower_processed_data.npy"

# 保存训练好的模型

TRAIN_FILE = "./save_model/my_model"

# 提供的已经训练好的模型

CKPT_FILE = "./resnet_v1_50.ckpt"

# 定义训练所用参数

LEARNING_RATE = 0.0001

STEPS = 500

BATCH = 32

N_CLASSES = 5

# 这里指出了不需要从训练好的模型中加载的参数,就是最后的自定义的全连接层

CHECKPOINT_EXCLUDE_SCOPES = 'Logits'

# 指定最后的全连接层为可训练的参数

TRAINABLE_SCOPES = 'Logits'

# 加载所有需要从训练好的模型加载的参数

def get_tuned_variables():

##不需要加载的范围

exclusions = [scope.strip() for scope in CHECKPOINT_EXCLUDE_SCOPES.split(",")]

# 初始化需要加载的参数

variables_to_restore = []

# 遍历模型中的所有参数

for var in slim.get_model_variables():

# 先指定为不需要移除

excluded = False

# 遍历exclusions,如果在exclusions中,就指定为需要移除

for exclusion in exclusions:

if var.op.name.startswith(exclusion):

excluded = True

break

# 如果遍历完后还是不需要移除,就把参数加到列表里

if not excluded:

variables_to_restore.append(var)

return variables_to_restore

# 获取所有需要训练的参数

def get_trainable_variables():

# 同上

scopes = [scope.strip() for scope in TRAINABLE_SCOPES.split(",")]

variables_to_train = []

# 枚举所有需要训练的参数的前缀,并找到这些前缀的所有参数

for scope in scopes:

variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope)

variables_to_train.extend(variables)

return variables_to_train

def main():

# 加载数据

processed_data = np.load(INPUT_DATA)

training_images = processed_data[0]

n_training_example = len(training_images)

training_labels = processed_data[1]

validation_images = processed_data[2]

validation_labels = processed_data[3]

testing_images = processed_data[4]

testing_labels = processed_data[5]

print("there is %d training examples, %d validation examples, %d testing examples" %

(n_training_example, len(validation_labels), len(testing_labels)))

# 定义数据格式

images = tf.placeholder(tf.float32, [None, 300, 300, 3], name='input_images')

labels = tf.placeholder(tf.int64, [None], name='labels')

# 定义模型,因为给出的只有参数,并没有模型,这里需要指定模型的具体结构

with slim.arg_scope(resnet_v1.resnet_arg_scope()):

# logits就是最后预测值,images就是输入数据,指定num_classes=None是为了使resnet模型最后的输出层禁用

logits, _ = resnet_v1.resnet_v1_50(images, num_classes=None)

#自定义的输出层

with tf.variable_scope("Logits"):

#将原始模型的输出数据去掉维度为2和3的维度,最后只剩维度1的batch数和维度4的300*300*3

#也就是将原来的二三四维度全部压缩到第四维度

net = tf.squeeze(logits, axis=[1,2])

#加入一层dropout层

net = slim.dropout(net, keep_prob=0.5,scope='dropout_scope')

#加入一层全连接层,指定最后输出大小

logits = slim.fully_connected(net, num_outputs=N_CLASSES, scope='fc')

# 获取需要训练的变量

trainable_variables = get_trainable_variables()

# 定义损失,模型定义的时候已经考虑了正则化了

tf.losses.softmax_cross_entropy(tf.one_hot(labels, N_CLASSES), logits, weights=1.0)

# 定义训练过程

train_step = tf.train.RMSPropOptimizer(LEARNING_RATE).minimize(tf.losses.get_total_loss())

# 定义测试和验证过程

with tf.name_scope('evaluation'):

correct_prediction = tf.equal(tf.argmax(logits, 1), labels)

evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 定义加载模型的函数,就是重新定义load_fn函数,从文件中获取参数,获取指定的变量,忽略缺省值

load_fn = slim.assign_from_checkpoint_fn(CKPT_FILE, get_tuned_variables(), ignore_missing_vars=True)

# 定义保存新的训练好的模型的函数

saver = tf.train.Saver()

with tf.Session() as sess:

# 初始化没有加载进来的变量,一定要在模型加载之前,否则会将训练好的参数重新赋值

init = tf.global_variables_initializer()

sess.run(init)

# 加载训练好的模型

print("加载谷歌训练好的模型...")

load_fn(sess)

start = 0

end = BATCH

for i in range(STEPS):

# 训练...

sess.run(train_step, feed_dict={images: training_images[start:end],

labels: training_labels[start:end]})

# 间断地保存模型,并在验证集上验证

if i % 50 == 0 or i + 1 == STEPS:

saver.save(sess, TRAIN_FILE, global_step=i)

validation_accuracy = sess.run(evaluation_step, feed_dict={images: validation_images,

labels: validation_labels})

print("经过%d次训练后,在验证集上的正确率为%.3f" % (i, validation_accuracy))

# 更新起始和末尾

start = end

if start == n_training_example:

start = 0

end = start + BATCH

if end > n_training_example:

end = n_training_example

# 训练完了在测试集上测试正确率

testing_accuracy = sess.run(evaluation_step, feed_dict={images: testing_images,

labels: testing_labels})

print("最后在测试集上的正确率为%.3f" % testing_accuracy)

if __name__ == '__main__':

main()

运行结果

result.png

结果分析

从结果中可以看到,利用已经训练好的复杂模型的参数,再根据问题加上一层自定义的输出层,可以在短时间内利用较少的资源将模型迁移到不同的问题上,在200次训练的时候就可以在这个问题上达到90%的正确率,经过500次训练后可以在测试集上达到接近95%的正确率,验证了目前的主流卷积神经网络具有很好的普适性和迁移性。

迁移学习resnet_ResNet-V1-50卷积神经网络迁移学习进行不同品种的花的分类识别相关推荐

  1. 深度学习(四)卷积神经网络入门学习(1)

    卷积神经网络入门学(1) 原文地址:http://blog.csdn.net/hjimce/article/details/47323463 作者:hjimce 卷积神经网络算法是n年前就有的算法,只 ...

  2. pytorch卷积神经网络_资源|卷积神经网络迁移学习pytorch实战推荐

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 一.资源简介 这次给大家推荐一篇关于卷积神经网络迁移学习的实战资料,卷积神经网络迁移学 ...

  3. 《解析卷积神经网络—深度学习实践手册》—学习笔记

    书籍链接 百度网盘 谷歌云盘 绪论 机器学习是人工智能的一个分支,它致力于研究如何通过计算的手段,利用经验(experience)来改善计算机系统自身的性能.通过从经验中获取知识(knowledge) ...

  4. 深度学习(DL)与卷积神经网络(CNN)学习笔记随笔-04-基于Python的LeNet之MLP

    原文地址可以查看更多信息 本文主要参考于:Multilayer Perceptron  python源代码(github下载 CSDN免费下载) 本文主要介绍含有单隐层的MLP的建模及实现.建议在阅读 ...

  5. 深度学习(DL)与卷积神经网络(CNN)学习笔记随笔-03-基于Python的LeNet之LR

    原地址可以查看更多信息 本文主要参考于:Classifying MNIST digits using Logistic Regression  python源代码(GitHub下载 CSDN免费下载) ...

  6. 学习笔记:深度学习(3)——卷积神经网络(CNN)理论篇

    学习时间:2022.04.10~2022.04.12 文章目录 3. 卷积神经网络CNN 3.1 卷积神经网络的概念 3.1.1 什么是CNN? 3.1.2 为什么要用CNN? 3.1.3 人类的视觉 ...

  7. 《Python 深度学习》5.4 卷积神经网络的可视化(代码)

    Visualizing what convnets learn 卷积神经网络的可视化 人们常说,深度学习模型是"黑盒",即模型学到的表示很难用人类可以理解的方式来提取和呈现.虽然对 ...

  8. 深度学习时间序列预测:卷积神经网络(CNN)算法构建单变量时间序列预测模型预测空气质量(PM2.5)+代码实战

    深度学习时间序列预测:卷积神经网络(CNN)算法构建单变量时间序列预测模型预测空气质量(PM2.5)+代码实战 神经网络(neual networks)是人工智能研究领域的一部分,当前最流行的神经网络 ...

  9. 【深度学习】Tensorflow搭建卷积神经网络实现情绪识别

    [深度学习]Tensorflow搭建卷积神经网络实现情绪识别 文章目录 1 Tensorflow的基本使用方法1.1 计算图1.2 Feed1.3 Fetch1.4 其他解释 2 训练一个Tensor ...

最新文章

  1. 测量接线导通问题解决方案
  2. python3 tcp 文件传输源码
  3. 马尔可夫“折棍子”过程 Markovian Stick-breaking Process 简介
  4. 好用的Perl包 Class::Ref
  5. 仿iphone触屏手机界面
  6. android应用程序的生命周期,Android应用程序的生命周期.doc
  7. (36)FPGA原语设计(BUFIO)
  8. c语言中不能编译,为什么`int;`可以在C语言中很好地编译,而在C ++中却不能?
  9. Julia : 如何在Atom中能用上go to definition?
  10. cad面积累计lisp怎么用_CAD连续面积标注lisp插件
  11. 元学习提高黑盒对抗攻击
  12. Eclipse官网查找历史版本Eclipse
  13. 充分利用 cpu_充分利用设计学校(已更新)
  14. 浅谈大数据平台架构设计
  15. 【AGC004E】Salvage Robots【动态规划dp】
  16. 惠普战66二代 amd 处理器耳机插入后没声音的问题解决
  17. m基于改进PSO粒子群优化的RBF神经网络解耦控制算法matlab仿真
  18. Arduino 按键传感器检测实验带原理图说明
  19. 2019华为软件精英挑战赛参赛心得
  20. C# 多张JPG合成PDF 基于iTextSharp5.5.13.3

热门文章

  1. KMP的字幕用法之調時同步及保存
  2. 电脑对皮肤的3大致命伤害 电脑对皮肤的伤害—— 第一:皮肤干燥有细纹肤色变黄。 第二:长有斑点。 第三:眼部有细纹、黑眼圈严重。 许多朋友一直向我提出,长期的电脑工作,使皮肤出现了以
  3. KVM虚拟化技术实战
  4. 白天、暗夜双重模式+自作潜水俱乐部前端小项目+学习经验总结(一)
  5. PAT 基础练习题 7-1 厘米换算英尺英寸 (15 分)
  6. H5上传照片调用相册拍照(附源码)
  7. C#开发之——Directoryinfo(10.2)
  8. 新的linux桌面,Linux桌面的新款式
  9. 开机直接进入bios解决方法
  10. 程浩[迅雷网创始人]