Tensorflow Lite介绍

50次阅读

共计 6145 个字符,预计需要花费 16 分钟才能阅读完成。

简介
Tensorflow Lite 是针对移动设备和嵌入式设备的轻量化解决方案,占用空间小,低延迟。Tensorflow Lite 在 android8.1 以上的设备上可以通过 ANNA 启用硬件加速。

支持浮点运算和量化模型,并已针对移动平台进行优化,可以用来创建和运行自定义模型。开发者也可以在模型中添加自定义操作。
FlatBuffer 格式
具有在移动设备运行更快的内核解释器
支持通过 Tensorflow 训练好的模型转换为 Tensorflow Lite 格式(pd,h5 等都可以)
当支持所有优化操作时,模型小于 300k,当仅支持 inception v3 和 mobilenet 模型优化时,模型小于 200k

预训练模型:

inception v3:用于目标检测
MobileNets:专门针对移动端的模型,具有低延迟,高速度,低内存,可用于图像识别,目标检测,图像分割,但是精度小于 inception v3
量化版本的 MobileNets,通过将 float-32 转为 int-8,在 CPU 上拥有更快的速度
支持 java,c++API

以上谈到的预训练模型基于 ImageNet 数据集训练,支持 1000 种类别。如果此数据集不能满足你的项目需要,你需要准备自己的数据集和标签,使用迁移学习重新训练模型。
模型结构

Tensorflow Lite 模型的数据格式与 Tensorflow 桌面端不同,需要使用 Tensorflow Lite 转换为.tflite 格式,然后应用到移动端。模型结构:

java-API:包装 C ++API, 以便在 android 上使用 java 调用
C++-API: 加载 Tensorflow Lite 模型和解释器
解释器:执行模型一系列核心操作,支持选择内核加载。全部加载 300kb,不加载只有 100kb
在 android8.1 以上设备,可通过相关 api 进行硬件加速(硬件支持的情况下),否则在 CPU 执行

转换模型格式
Tensorflow Lite 转换器支持以下格式:

使用 python API 执行 SavedModel 保存的模型文件
tf.keras 保存的.h5 模型文件
转换后的 GraphDef 文件

转换 GraphDef 文件
Tensorflow 模型一般保存为.pd 或.pdtxt 格式的文件,要转换为 Tensorflow Lite 支持的文件,首先需要进行 frozen 操作。此操作处理多个不同格式的文件:

tf.GraphDef(pd,pdtxt):图文件,包含操作,张量,变量的定义
checkpoint(.ckpt):包含变量,不包含解释器
tensorflow lite(.tflite):序列化的 FlatBuffer 文件,包含所有需要的文件

checkpoint 文件包含训练权重,tf.graphdef 文件包含图结构。冻结操作就是将上述文件进行合并操作使用命令行,执行该操作的示例如下:
freeze_graph –input_graph=/demo/mobilenet_v1_224.pd\
–input_checkpoint=/demo/checkpoints/mobilenet-1001.ckpt\
–input_binary=True\
–output_graph=/demo/frozen_mobilenet_v1_224.pd\
–output_node_names=/demo/MobileNetV1/Predictions/Reshape_1
input_binary: 读取的文件是否是二进制文件,如:pd 和 pdtxt 文件
android 端使用 Tensorflow Lite
可以使用 android studio 和源码编译两种方式,此处我们介绍第一种(由于你懂的原因,开 vpn 会比较顺利些)。

安装 android studio
SDK 大于 26,NDK 大于 14
导入工程项目,路径:tensorflow/lite/examples

默认使用 mobilenet 模型,如要使用 inception 模型,先下载模型文件并拷贝至 asset 文件夹,然后修改 Camera2BasicFragment 文件:classifier = new ImageClassifierQuantizedMobileNet(getActivity()) 改为:classifier = new ImageClassifierFloatInception(getActivity())
Tensorflow Lite 转换器

上图是 Tensorflow Lite 转换器的工作流程,清晰明了,就不做过多介绍了。此外,转换的方式有两种,python api 的方式和命令行方式。
从 Session 中导出 GraphDef
使用 tf.Session 将 Tensorflow 模型转为 Tensorflow Lite 模型
import tensorflow as tf

img = tf.placeholder(name=”img”, dtype=tf.float32, shape=(1, 64, 64, 3))
var = tf.get_variable(“weights”, dtype=tf.float32, shape=(1, 64, 64, 3))
val = img + var
out = tf.identity(val, name=”out”)

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
converter = tf.lite.TFLiteConverter.from_session(sess, [img], [out])
tflite_model = converter.convert()
open(“converted_model.tflite”, “wb”).write(tflite_model)
从 file 中导出 GraphDef
以下代码展示怎样将.pd 或.pdtxt 文件转为 Tensorflow Lite 模型支持的 FlateBuffer 格式文件。
import tensorflow as tf

graph_def_file = “/path/to/Downloads/mobilenet_v1_1.0_224/frozen_graph.pb”
input_arrays = [“input”]
output_arrays = [“MobilenetV1/Predictions/Softmax”]

converter = tf.lite.TFLiteConverter.from_frozen_graph(
graph_def_file, input_arrays, output_arrays)
tflite_model = converter.convert()
open(“converted_model.tflite”, “wb”).write(tflite_model)
将 SaveModle 导出
import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
tflite_model = converter.convert()
open(“converted_model.tflite”, “wb”).write(tflite_model)
tf.keras 文件导出
import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_keras_model_file(“keras_model.h5”)
tflite_model = converter.convert()
open(“converted_model.tflite”, “wb”).write(tflite_model)
量化模型
import tensorflow as tf

img = tf.placeholder(name=”img”, dtype=tf.float32, shape=(1, 64, 64, 3))
const = tf.constant([1., 2., 3.]) + tf.constant([1., 4., 4.])
val = img + const
out = tf.fake_quant_with_min_max_args(val, min=0., max=1., name=”output”)

with tf.Session() as sess:
converter = tf.lite.TFLiteConverter.from_session(sess, [img], [out])
converter.inference_type = tf.lite.constants.QUANTIZED_UINT8
input_arrays = converter.get_input_arrays()
converter.quantized_input_stats = {input_arrays[0] : (0., 1.)} # mean, std_dev
tflite_model = converter.convert()
open(“converted_model.tflite”, “wb”).write(tflite_model)
TensorFlow Lite Python 解释器
代码展示如何使用 Tensorflow Lite 解释器读取.tflite 文件。
import numpy as np
import tensorflow as tf

# 加载模型并分配张量
interpreter = tf.lite.Interpreter(model_path=”converted_model.tflite”)
interpreter.allocate_tensors()

# 获取输入输出张量
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# 随机生成测试数据,测试模型输出
input_shape = input_details[0][‘shape’]
input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32)
interpreter.set_tensor(input_details[0][‘index’], input_data)

interpreter.invoke()
output_data = interpreter.get_tensor(output_details[0][‘index’])
print(output_data)
Tensorflow2.0 转换器使用

如图所示,Tensorflow2.0 与之前相比,少了冻结 graph 模块,增加了 Concrete Fn。
生成 concrete Fn
为了将 Tensorflow2.0 模型转为 Tensorflow Lite,模型需要导出 concrete Fn。这是因为 Tensorflow2.0 中,eager execution 是默认设置,虽然调试更加便利,但是它没有保存图,因为不能直接应用到移动设备。不过,可以使用 tf.function 包装,这样保存的模型就包含图,可以转换为 Tensorflow Lite 所需要的 FlatBuffer 格式文件。
class BasicModel(tf.Module):

def __init__(self):
self.const = None

@tf.function
def pow(self, x):
if self.const is None:
self.const = tf.Variable(2.)
return x ** self.const
concrete Fn 声明的图可以被转换为 Tensorflow Lite 模型或者使用 SaveModel 导出。为了导出此方法,需要声明 signature,使用方法如下:

在 tf.function 中声明 input_signature
将 tf.TensorSpec 传值给 get_concrete_funtion
将 input 传值给 get_concrete_funtion

import tensorflow as tf

root = tf.Module()

# 初始化一次变量值
root.var = None

@tf.function
def exported_function(x):

if root.var is None:
root.var = tf.Variable(tf.random.uniform([2, 2]))
root.const = tf.constant([[37.0, -23.0], [1.0, 4.0]])
root.mult = tf.matmul(root.const, root.var)
return root.mult * x

root.func = exported_function

concrete_func = root.func.get_concrete_function(
tf.TensorSpec([1, 1], tf.float32))
Python api 执行 the TensorFlow Lite converter
Tensorflow2.0 中转换 Tensorflow Lite 模型使用 tf.lite.TFLiteConverter.from_concrete_function(),示例如下:
import tensorflow as tf

# 创建模型
root = tf.train.Checkpoint()
root.v1 = tf.Variable(3.)
root.v2 = tf.Variable(2.)
root.f = tf.function(lambda x: root.v1 * root.v2 * x)

# 保存模型
export_dir = “/tmp/test_saved_model”
input_data = tf.constant(1., shape=[1, 1])
to_save = root.f.get_concrete_function(input_data)
tf.saved_model.save(root, export_dir, to_save)

# 加载模型并获取 concrete fn.
model = tf.saved_model.load(export_dir)
concrete_func = model.signatures[
tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY]

# 设置 input shape
concrete_func.inputs[0].set_shape(input_data.shape)

# 转换模型
converter = tf.lite.TFLiteConverter.from_concrete_function(concrete_func)
tflite_model = converter.convert()
TensorFlow Lite 推断
TensorFlow Lite 推断一般执行以下步骤:

加载.tflite 模型
处理数据以适应模型 input
调用 API,创建解析器,运行模型
获取模型输出结果

如何选择模型

如图所示,大模型高精度,高延迟;小模型低精度,低延迟,模型的选择需要根据你的项目需求进行选择。

正文完
 0