2 (自我拓展)部署花的识别模型(学习tensorflow实战google深度学习框架)
kaggle竞赛的inception模型已经能够提取图像很好的特征,后续训练出一个针对当前图片数据的全连接层,进行花的识别和分类。这里见书即可,不再赘述。
书中使用google参加Kaggle竞赛的inception模型重新训练一个全连接神经网络,对五种花进行识别,我姑且命名为模型flower_photos_model。我进一步拓展,将lower_photos_model模型进一步保存,然后部署和应用。然后,我们直接调用迁移之后又训练好的模型,对花片进行预测。
这里讨论两种方式:使用import_meta_graph和使用saver()
首先,原书的迁移学习的代码需要做一些改动。
writer = tf.summary.FileWriter('./graphs/flower_photos_model_graph', sess.graph)
saver.save(sess, "Saved_model/flower_photos_model.ckpt")
Saver()方式
我相较于训练flower_photos_model模型时,增添了一个变量的定义:
即label_index=tf.argmax(final_tensor,1)
def main():
#先定义相同的计算图再加载迁移学习的模型
bottleneck_input = tf.placeholder(tf.float32, [None, BOTTLENECK_TENSOR_SIZE], name='BottleneckInputPlaceholder')
with tf.name_scope('final_training_ops'):
weights = tf.Variable(tf.truncated_normal([BOTTLENECK_TENSOR_SIZE, n_classes], stddev=0.001))
biases = tf.Variable(tf.zeros([n_classes]))
logits = tf.matmul(bottleneck_input, weights) + biases
final_tensor = tf.nn.softmax(logits)
label_index=tf.argmax(final_tensor,1)
#利用import_meta_graph和import_graph_def加载的变量均不允许与当前定义计算图有冲突。
#saver = tf.train.Saver()则只加载当前计算图中定义的。
saver = tf.train.Saver() gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.700)
with tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) as sess:
saver.restore(sess, "Saved_model/flower_photos_model.ckpt")
#还是要加载一下inception模型
MODEL_DIR = './inception_dec_2015'
MODEL_FILE= 'tensorflow_inception_graph.pb'
with gfile.FastGFile(os.path.join(MODEL_DIR, MODEL_FILE), 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
bottleneck_tensor, jpeg_data_tensor = tf.import_graph_def(graph_def, return_elements=[BOTTLENECK_TENSOR_NAME, JPEG_DATA_TENSOR_NAME])
print (bottleneck_tensor)
print (jpeg_data_tensor)
#为了在tensorboard中观察加载的计算图。
writer = tf.summary.FileWriter('./graphs/flower_photos_model_graph_use', sess.graph)
writer.close()
#image_path='./data/xiaojie_application/xiaojie_rose.jpg'
image_path='./data/xiaojie_application/xiaojie_sunflowers.jpg'
#image_path='./data/xiaojie_application/5547758_eea9edfd54_n.jpg' """测试一张图片,能否获取瓶颈向量。
image_data = gfile.FastGFile(image_path, 'rb').read()
print (sess.run(jpeg_data_tensor,{jpeg_data_tensor:image_data}))
print ("xiaojie1")
print (sess.run(bottleneck_tensor,{jpeg_data_tensor:image_data}))
"""
label_index_value=evalution_xiaojie(sess,image_path,jpeg_data_tensor,bottleneck_tensor,bottleneck_input,label_index)
#print (label_index_value)
classes=['daisy','dandelion','roses','sunflowers','tulips']
print ("预测的花的类型:",classes[label_index_value[0]])
相关的函数的定义:
evalution_xiaojie输出预测的分类index。
def evalution_xiaojie(sess,image_path,jpeg_data_tensor,bottleneck_tensor,bottleneck_input,label_index):
#输出一张图片的预测结果 bottleneck_values=get_bottleneck_values_xiaojie(sess,image_path,jpeg_data_tensor,bottleneck_tensor)
bottlenecks = []
bottlenecks.append(bottleneck_values)
label_index_value = sess.run(label_index, feed_dict={
bottleneck_input: bottlenecks})
return label_index_value
获取瓶颈向量(关于瓶颈向量,见书)
def get_bottleneck_values_xiaojie(sess,image_path,jpeg_data_tensor,bottleneck_tensor):
#瓶颈向量
if not os.path.exists(CACHE_DIR): os.makedirs(CACHE_DIR)
bottleneck_path = get_bottleneck_path_xiaojie(CACHE_DIR,image_path)
print (bottleneck_path)
if not os.path.exists(bottleneck_path):
image_data = gfile.FastGFile(image_path, 'rb').read()
bottleneck_values = run_bottleneck_on_image(sess, image_data, jpeg_data_tensor, bottleneck_tensor)
bottleneck_string = ','.join(str(x) for x in bottleneck_values)
with open(bottleneck_path, 'w') as bottleneck_file:
bottleneck_file.write(bottleneck_string)
else:
with open(bottleneck_path, 'r') as bottleneck_file:
bottleneck_string = bottleneck_file.read()
bottleneck_values = [float(x) for x in bottleneck_string.split(',')]
return bottleneck_values
使用inception模型计算瓶颈向量
def run_bottleneck_on_image(sess, image_data, image_data_tensor, bottleneck_tensor):
print("yes")
bottleneck_values = sess.run(bottleneck_tensor, {image_data_tensor: image_data})
bottleneck_values = np.squeeze(bottleneck_values)
print("no")
return bottleneck_values
瓶颈向量有一个缓存文件,这也是类似于原书训练迁移学习模型时的做法
def get_bottleneck_path_xiaojie(CACHE_DIR,image_path):
file_name_suffix=image_path.split('/')[-1]
file_name_no_suffix=file_name_suffix.split('.')[0]
bottleneck_file_name=file_name_no_suffix+('_cache.txt')
bottleneck_path=os.path.join(CACHE_DIR, bottleneck_file_name)
return bottleneck_path
定义的全局变量
BOTTLENECK_TENSOR_SIZE = 2048
n_classes = 5
BOTTLENECK_TENSOR_NAME = 'pool_3/_reshape:0'
JPEG_DATA_TENSOR_NAME = 'DecodeJpeg/contents:0'
CACHE_DIR='./data/xiaojie_application/cache_bottleneck/'
Saver方式的说明:
Saver只能导出持久化模型中与当前代码定义计算图相匹配的部分。
因此,对于之前inception也需要再一次重新加载。
此外,当前代码定义计算图,比持久化模型flower_photos_model多定义了一个变量,即label_index=tf.argmax(final_tensor,1),即输出预测的分类index。
import_meta_graph方式
import_meta_graph方式与saver方式的不同点在于会导入完整的计算图,因此当前代码不能定义和要加载计算图相互冲突的部分。
相关函数定义的代码均不变。只将main函数的内容和全局变量改为:
def main():
#如果使用tf.train.import_meta_graph的话,就会重复加载计算图。因此,避免重复,当前代码中不能定义重复的。 #saver = tf.train.Saver()
saver = tf.train.import_meta_graph("Saved_model/flower_photos_model.ckpt.meta")
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.700)
with tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) as sess:
#with tf.Session() as sess:
#如果直接使用saver = tf.train.Saver()和restore还原一个model.ckpt文件,是不可能将之前迁移学习那个模型利用import_graph_def加载的inception模型加载进来的。
saver.restore(sess, "Saved_model/flower_photos_model.ckpt") bottleneck_tensor= sess.graph.get_tensor_by_name(import_BOTTLENECK_TENSOR_NAME)
jpeg_data_tensor = sess.graph.get_tensor_by_name(import_JPEG_DATA_TENSOR_NAME)
print (bottleneck_tensor)
print (jpeg_data_tensor) writer = tf.summary.FileWriter('./graphs/flower_photos_model_graph_use', sess.graph)
writer.close()
image_path='./data/xiaojie_application/xiaojie_rose.jpg'
#image_path='./data/xiaojie_application/xiaojie_sunflowers.jpg'
#image_path='./data/xiaojie_application/5547758_eea9edfd54_n.jpg' """测试一张图片
image_data = gfile.FastGFile(image_path, 'rb').read()
print (sess.run(jpeg_data_tensor,{jpeg_data_tensor:image_data}))
print ("xiaojie1")
print (sess.run(bottleneck_tensor,{jpeg_data_tensor:image_data}))
"""
bottleneck_input= sess.graph.get_tensor_by_name("BottleneckInputPlaceholder:0")
final_tensor = sess.graph.get_tensor_by_name("final_training_ops/Softmax:0")
label_index=tf.argmax(final_tensor,1)
label_index_value=evalution_xiaojie(sess,image_path,jpeg_data_tensor,bottleneck_tensor,bottleneck_input,label_index)
print (label_index_value)
classes=['daisy','dandelion','roses','sunflowers','tulips']
print ("预测的花的类型:",classes[label_index_value[0]])
全局变量改为:
import_BOTTLENECK_TENSOR_NAME = 'import/pool_3/_reshape:0'
import_JPEG_DATA_TENSOR_NAME = 'import/DecodeJpeg/contents:0'
这是因为,使用import_meta_graph方式的话,当前代码不能定义任何与持久化模型中计算图冲突的节点。此外,在flower_photos_model模型对全连接层进行训练的过程中,已经利用import_graph_def的方式导入google Inception v3的持久化模型pb文件,因此,已经包括了google的模型。通过在tensorboard中查看,会发现,所有导入的模块节点之前会带上import节点。因此,在训练flower_photos_model模型时,使用的是pool_3/_reshape:0获取张量,而此时,只能使用import/pool_3/_reshape:0'获取张量。
只能使用import/pool_3/_reshape:0'获取张量。
final_tensor = sess.graph.get_tensor_by_name("final_training_ops/Softmax:0")
然后,我们再定义一个label_index
label_index=tf.argmax(final_tensor,1)
因此,同saver模型一样,所有的其它函数接口和实现都不用变。
最后的结果很nice。可以识别五种花朵,可以直接部署应用。
程序附件
链接:https://pan.baidu.com/s/11YtyDEyV84jONPi9tO2TCw 密码:8mfj
2 (自我拓展)部署花的识别模型(学习tensorflow实战google深度学习框架)的更多相关文章
- 1 如何使用pb文件保存和恢复模型进行迁移学习(学习Tensorflow 实战google深度学习框架)
学习过程是Tensorflow 实战google深度学习框架一书的第六章的迁移学习环节. 具体见我提出的问题:https://www.tensorflowers.cn/t/5314 参考https:/ ...
- TensorFlow+实战Google深度学习框架学习笔记(11)-----Mnist识别【采用滑动平均,双层神经网络】
模型:双层神经网络 [一层隐藏层.一层输出层]隐藏层输出用relu函数,输出层输出用softmax函数 过程: 设置参数 滑动平均的辅助函数 训练函数 x,y的占位,w1,b1,w2,b2的初始化 前 ...
- Tensorflow 实战Google深度学习框架 第五章 5.2.1Minister数字识别 源代码
import os import tab import tensorflow as tf print "tensorflow 5.2 " from tensorflow.examp ...
- TensorFlow+实战Google深度学习框架学习笔记(12)------Mnist识别和卷积神经网络LeNet
一.卷积神经网络的简述 卷积神经网络将一个图像变窄变长.原本[长和宽较大,高较小]变成[长和宽较小,高增加] 卷积过程需要用到卷积核[二维的滑动窗口][过滤器],每个卷积核由n*m(长*宽)个小格组成 ...
- 实战Google深度学习框架-C5-MNIST数字识别问题
5.1 MNIST数据处理 MNIST是NIST数据集的一个子集,包含60000张图片作为训练数据,10000张作为测试数据,其中每张图片代表0~9中的一个数字,图片大小为28*28(可以用一个28* ...
- 论文阅读:Face Recognition: From Traditional to Deep Learning Methods 《人脸识别综述:从传统方法到深度学习》
论文阅读:Face Recognition: From Traditional to Deep Learning Methods <人脸识别综述:从传统方法到深度学习> 一.引 ...
- 机器学习如何选择模型 & 机器学习与数据挖掘区别 & 深度学习科普
今天看到这篇文章里面提到如何选择模型,觉得非常好,单独写在这里. 更多的机器学习实战可以看这篇文章:http://www.cnblogs.com/charlesblc/p/6159187.html 另 ...
- 『高性能模型』Roofline Model与深度学习模型的性能分析
转载自知乎:Roofline Model与深度学习模型的性能分析 在真实世界中,任何模型(例如 VGG / MobileNet 等)都必须依赖于具体的计算平台(例如CPU / GPU / ASIC 等 ...
- tensorflow模型持久化保存和加载--深度学习-神经网络
模型文件的保存 tensorflow将模型保持到本地会生成4个文件: meta文件:保存了网络的图结构,包含变量.op.集合等信息 ckpt文件: 二进制文件,保存了网络中所有权重.偏置等变量数值,分 ...
随机推荐
- 认识CSS中高级技巧之元素的显示与隐藏
前端之HTML,CSS(八) CSS高级技巧 元素的显示与隐藏 CSS中有三个属性可以设置元素的显示于隐藏,分别是:display.visibility和overflow. display 隐藏元素: ...
- python自动化 协程函数、二分查找、模块搜索
协程函数 yiled: 把函数的执行结果封装好__iter__和__next__得到一个迭代器 与return功能类似,都可以返回值,但是return只能返回一次只 def fun(count): p ...
- date时间设置
date +%F时间日期 date +%Y -%m-%d 年月日 date +%T 显示时间 HMS几点几分几秒 -%H 为小时 %w 周几 date -d “-1da ...
- signed char型内存位bit表示
signed char型内存 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9 ...
- [转] Hive函数大全
1.内置运算符 1.1关系运算符 运算符 类型 说明 A = B 所有原始类型 如果A与B相等,返回TRUE,否则返回FALSE A == B 无 失败,因为无效的语法. SQL使用”=”,不使用”= ...
- db2 monitor event
1.创建事件监控器至少需要哪些权限? DBADM authority SQLADM authority 2.事件监控器的种类有哪些? 3. db2 flush event monitor eventm ...
- (转)nginx location在配置中的优先级
原文:https://www.bo56.com/nginx-location%E5%9C%A8%E9%85%8D%E7%BD%AE%E4%B8%AD%E7%9A%84%E4%BC%98%E5%85%8 ...
- select for update和select for update wait和select for update nowait的区别
CREATE TABLE "TEST6" ( "ID" ), "NAME" ), "AGE" ,), "SEX ...
- 【javascript】jq之display:none与visible:hidden
今天学习到jquery的hide()部分时,突然有一个想法,jquery中的隐藏/显示部分的实现是给目标元素附加一个"display: none"属性,那么如果在类似于下面的布局中 ...
- Android ListView中EditView再次焦点获取
问题:在ListView中使用EditView,当第一次将焦点给到EditView的时候弹出小键盘.使得EditView失去焦点. 分析:因为在第一次使用EditView弹出小键盘之后,会重新的调用一 ...