本文为系列博客tensorflow模型部署系列的一部分,用于实现通用模型的部署。本文主要实现用JAVA接口调用tensorflow模型进行推理。相关源码见链接
本文为系列博客tensorflow模型部署系列的一部分,用于JAVA
语言实现通用模型的部署。本文主要使用pb格式的模型文件,其它格式的模型文件请先进行格式转换,参考tensorflow模型部署系列————预训练模型导出。从模型文件中获取输入输出op名请参考博客tensorflow模型部署系列————单机python部署
上一篇博文tensorflow模型部署系列————单机C++部署就如何使用C/C++语言加载模型文件并利用模型文件进行推理进行讲解,博文中也开放了使用python
进行模型推理的代码,本文参照python模型部署代码进行C++模型部署。
有两种方案可以做tensorflow的java部署
进入网页下载jar包和jni文件,目前已编译的jni支持linux-x86 windows-x86 macOS, arm处理器并不支持,需要自行编译。关于tensorflow源码编译过程请关注我的博客,后续会有专门博文讲解
tensorflow的java接口详见官方文档。这里针对常用接口做一个说明,并跟将JAVA接口与tensorflow模型部署系列————单机python部署](https://blog.csdn.net/chongtong/article/details/90693787)中的python代码进行对应,以便于读者更好地理解接口
创建图,直接使用java封装类Graph即可
Graph graph = new Graph()
加载模型文件,对应python代码tensors = tf.import_graph_def(output_graph_def, name="")
graph.importGraphDef()
创建session,直接使用java封装类Graph即可,对应python代码self.__sess = tf.Session()
Session session = new Session(graph)
获取输入输出OP,对应python代码self.__input = graph.get_tensor_by_name("input:0")
op名称的获取方式见tensorflow模型部署系列————单机python部署。
java代码直接使用op名称作为参数即可
张量填充,无对应python代码,python可直接赋值
java需创建Tensor,在创建的同时进行数据填充
Tensor<T> input = Tensor.create()
运行OP,对应python代码output = self.__sess.run(self.__output, feed_dict={self.__input: input})
使用
session.runner().run()
运行sessiontenss= session.runner().feed("sequential_1_input", input).fetch("output/Softmax").run() 其中 runner()用于获取运行对象 feed()用于填充输入占位符 fetch()用于指定需获取的tensor run()用于运行session
获取张量值,无对应python代码,因python可直接获取
op运行完毕后就可以通过
TF_TensorData
找到张量的数据缓冲区地址,并获取输出数据了Tensor<Float> output = tenss.get(0).expect(Float.class) 其中 get()用于获取运行后的张量值 expect()作用为类型检查
本文为系列博客tensorflow模型部署系列的一部分,用于实现通用模型的部署。本文主要实现用C++接口调用tensorflow模型进行推理。相关源码见链接
本文为系列博客tensorflow模型部署系列的一部分,用于C++
语言实现通用模型的部署。本文主要使用pb格式的模型文件,其它格式的模型文件请先进行格式转换,参考tensorflow模型部署系列————预训练模型导出。从模型文件中获取输入输出op名请参考博客tensorflow模型部署系列————单机python部署
上一篇博文tensorflow模型部署系列————单机python部署就如何使用python语言加载模型文件并利用模型文件进行推理进行讲解,博文中也开放了使用python
进行模型推理的代码,本文参照python模型部署代码进行C++模型部署。
tensorflow官方同时提供了C++接口和C接口,目前不能直接使用C++接口的调用,使用之前需要使用TensorFlow bazel build
编译;而C接口tensorflow官方提供了预编译库,可直接下载。本文重点在于使用C接口库进行模型部署。关于tensorflow源码编译过程请关注我的博客,后续会有专门博文讲解
库文件在获取和安装可参考tensorflow 官方 C库安装教程
下载
下载完毕后只需将解压后的库文件和头文件添加到系统环境变量中即可
编译
如果以上列表中没有我们想要的平台库,或者我们需要开启一些未开启的加速选项,就需要从源代码编译C库了。具体编译环境搭建可参考官方文档linux/macOS windows 树莓派,编译命令可参考官方文档
关于tensorflow的编译因为东西比较多,我会在后续专门写一个博客进行说明。本篇博客主要聚焦在使用C++调用模型文件进行推理这一块
本文为系列博客tensorflow模型部署系列的一部分,用于实现通用模型的部署。通用主要体现在通过tensorboard图从已保存的模型中还原并查看模型详细结构,以及自定义模型的输入输出tensor。相关源码见链接
本文为系列博客
tensorflow模型部署系列的一部分,用于python
语言实现通用模型的部署。通用主要体现在通过tensorboard
图从已保存的模型中还原并查看模型详细结构,以及自定义模型的输入输出tensor。本文主要使用keras和pb两种模型文件,其它格式的模型文件请先进行格式转换tensorflow模型部署系列————预训练模型导出
上一篇博文tensorflow模型部署系列————预训练模型导出就如何将模型导出为文件以及如何利用模型文件进行推理进行讲解,博文中也开放了使用python
进行模型推理的代码,本文也是使用python进行模型推理。主要区别在于:
打印模型结构model.summary()
绘制简单的模型图keras.utils.plot_model(model,'./keras/model.png')
生成tensorboard文件
tensorboard_callback = keras.callbacks.TensorBoard('./keras')
tensorboard_callback.set_model(model)
tensorboard_callback.writer.flush()
生成tensorboard文件
file_writer = tf.summary.FileWriter('./pb')
file_writer.add_graph(graph)
file_writer.flush()
然后输入命令行tensorboard --logdir=./
查看tensorboard模型图
在网页中点击图的输入和输入即可看到输入和输出的详细属性。注意:如果输出是矩形框,说明它是组合操作,要双击进入到它的内部,找到最后的椭圆形才是模型可识别的tensor
最终代码要在tensor名后加上:0
上图中输入tensor名称为input:0
,输出tensor名称为output/Softmax:0
通过代码查看所有op名称
op = graph.get_operations()
for i, m in enumerate(op):
print('op{}:'.format(i), m.values())
以上代码会打印出很多图,如下格式
op0: (<tf.Tensor 'sequential_1_input:0' shape=(?, 784) dtype=float32>,)
op1: (<tf.Tensor 'fc1/random_uniform/shape:0' shape=(2,) dtype=int32>,)
op2: (<tf.Tensor 'fc1/random_uniform/min:0' shape=() dtype=float32>,)
op3: (<tf.Tensor 'fc1/random_uniform/max:0' shape=() dtype=float32>,)
.
.
.
op的打印顺序大致以 以下顺序排列:
我们查找输入输出op时只要在前向传播op里面寻找就行了。一般来说,打印的第一个op是输入op,前向传播op的最后一个op为输出op。当然,我们也可以根据需要用中间一些op做为输入和输出,这在提取特征和迁移学习场景会用到
以第一行为例。'sequential_1_input:0'
为张量名称,float32
为张量类型,(?, 784)
为张量维度
模型封装类主要包括两个方法:初始化和推理。
初始化只用于处理与sess.run
无关的所有操作,以减少推理时的操作,保证模型推理高效运行。初始化主要进行的操作包括:模型文件加载、获取计算图和计算session、根据输入输出tensor名称获取输入输出tensor
推理仅仅执行sesson.run
操作
经过模型封装类封装以后,示例代码就很简单了。只用准备数据,然后推理就行了。
模型文件分析
python部署
本文为系列博客tensorflow模型部署系列的一部分,用于为模型部署提供最开始的输入————标准化的模型文件。相关源码见链接
本文为系列博客tensorflow模型部署系列的一部分,用于为模型部署提供最开始的输入————标准化的模型文件。相关示例代码放在gdyshi的github上
可保存的模型格式有多种,本文仅针对 tensorflow
的默认格式ckpt
、 keras
的默认格式h5
和tensorflow
例程常用格式pb
进行说明
ckpt
是checkpoint
的简称,是tensorflow
官方使用的模型文件。保存模型时会同时生成4个文件,这些文件实质上是代码,有被注入的风险,详见SECURITY
checkpoint
checkpoint
是文本文件,里面记录了保存的最新的checkpoint文件以及其它checkpoint文件列表。在inference时,可以通过修改这个文件,指定使用哪个model
*.meta
meta文件是pb(protocol buffer)格式文件,保存的是图结构。包含变量、op、集合等
*.index
*.data-*
ckpt文件和index文件是二进制文件,保存了所有的weights、biases、gradients等数据。
ckpt文件的保存语句为
saver = tf.train.Saver()
saver.save(sess, './saved_tf/tf_model')
ckpt文件的恢复语句为
new_saver = tf.train.import_meta_graph('./saved_tf/tf_model.meta')
new_saver.restore(sess, tf.train.latest_checkpoint(''./saved_tf'))
h5格式是keras框架所使用的保存格式,使用HDF5编码。
h5文件的保存语句为
# 保存模型和权重
model.save('./saved_keras/save.h5')
# 仅保存模型
model.save_weights('./saved_keras/save_weights.h5')
h5文件的恢复语句为
# 恢复模型和权重
model = keras.models.load_model( filepath )
# 恢复权重
model.load_weights('my_model_weights.h5',by_name=True)
前面所述在ckpt文件变量数据和图是各自独立的文件存储的。这种解耦形式存在的方法对以后的迁移学习以及对程序进行微小的改动提供了极大的便利性。但是对于已经训练好,需要部署的模型来说,把整个模型保存为一个文件则更方便。tensorflow例程常见的是pb文件的形式。pb文件实际上是一个较广范围的概念,泛指以protocol buffer
格式存储的文件,我写的tensorflow模型部署系列中所说的pb文件是狭义的概念,指protocol buffer
格式存储的模型图和模型参数文件,这一系列博客也将以pb格式为主要格式来进行部署
pb文件可以保存整个图表(元+数据),并将所有的变量固化为常量
tensorflow模型转换为pb格式文件的语句为
frozen_graph = convert_variables_to_constants(session, input_graph_def,
output_names, freeze_var_names)
graph_io.write_graph(frozen_graph, output_path, pb_model_name, as_text=False)
模型训练&保存代码
模型转换为pb文件
模型恢复&推理代码
本文开始我将要写几篇针对tensorflow系列模型的导出方法和步骤,此文为立贴文。一来确定后续研究路线,二来用于鞭策自己将路线坚持写完。相关示例代码放在gdyshi的github上
模型部署的第一步就是要有模型,所以我首先把模型导出方法做一下梳理,部署主要有两种:单机版和服务器版。单机版可以在单机上进行模型推理,主要应用在离线的智能终端、边缘计算产品上;单机版我先从最简单的python开始,依次深入到C++版、JAVA版、嵌入式版、浏览器前端版。服务器版可以在服务器上进行模型推理,终端或客户端通过网络调用传输数据给服务器,并从服务器获取推理后的预测结果;服务器版我先手动搭建一个简单的flask服务,然后深入到TensorFlow Serving,最后是分布式服务器部署。
分布式服务器部署博文因为TensorFlow Serving已经做进去了,就不再单独写了。感谢大家的支持和鼓励,tensorflow模型部署系列博文已完成。后续我会不断完善本系列博文内容及示例代码,请继续关注。近期有一个在海思平台上移植人脸识别模型的项目,我会将一些通用技术放入本系列博文中。
本文记录我个人研究自编码的过程
最近拜读三位大神的力作deep learning引言部分,从中做出如下推演:
当前数据
本文在旧的tensorflow版本上先进行模式导出和试验,成功后再部署到新的tensorflow版本上,先采用最基础的meta方式进行导入导出