TensorFlow Lite介绍
TensorFlow Lite是为了解决TensorFlow在移动平台和嵌入式端过于臃肿而定制开发的轻量级解决方案,是与TensorFlow完全独立的两个项目,与TensorFlow基本没有代码共享。 TensorFlow本身是为桌面和服务器端设计开发的,没有为ARM移动平台定制优化,因此如果直接用在移动平台或者嵌入式端会“水土不服”。TensorFlow Lite则实现了低能耗、低延迟的移动平台机器学习框架,并且使得编译之后的二进制发布版本更小。 TensorFlow Lite不仅支持传统的ARM加速,还为Android Neural Networks API提供了支持,在支持ANN的设备上能提供更好的性能表现。
TensorFlow Lite不仅使用了ARM Neon指令集加速,还预置了激活函数,提供了量化功能,加快了执行速度,减小了模型大小。
TensorFlow Lite特性
TensorFlow Lite有许多特性,这些特性使它在移动平台有非常良好的表现,先简单归纳一下TensorFlow Lite的特性如下:
- 支持一整套核心算子,所有算子都支持浮点输入和量化数据,这些核心算子是为移动平台单独优化定制的。这些算子还包括预置的激活函数,可以提高移动平台的计算性能,同时确保量化后计算的精确度。可以使用这些算子创建并执行我们自定义的模型,如果模型中需要一些特殊的算子,也可以编写我们自己定制的算子实现。
- 为移动平台定义了一种新的模型文件格式,这种格式是基于FlatBuffers的。FlatBuffers是一种高性能的开源跨平台序列化库,非常类似于Protobuf,但这两者之间的最大区别就是FlatBuffers不需要在访问数据前对数据进行任何解析或者接报(对应于Protobuf的压缩机制),因为FlatBuffers的数据格式一般是与内存对齐的。另外,FlatBuffers的代码也比Protobuf更小,更有利于移动平台集成使用。因此TensorFlow Lite和TensorFlow的模型文件格式是不同的。
- 提供了一种为移动平台优化的网络解释器,这使整个代码变得更加精简快速。这种解释器的优化思路是使用静态的图路径,加快运行时的决策速度,同时自定义内存分配器,减少动态内存分配,确保减少模型加载和初始化的时间及资源消耗,同时提高执行速度。
- 提供了硬件加速接口,一种是传统的ARM指令集加速,一种是Android Neural Networks API。如果目标设备是运行Android 8.1(API 27)及更高版本的系统,就可以使用Android自带加速API加快整体执行速度。
- 提供了模型转换工具,可以将TensorFlow生成的训练模型转换成TensorFlow Lite的模型。这样就解决了TensorFlow和TensorFlow Lite模型格式不同的问题。
- 编译后的二进制体积非常小,使用ARM Clang在优化设置为O3的条件下,整个库编译之后小于300KB,基本能满足目前大部分深度学习网络所需要的算子。
- 同时提供Java和C++ API,便于我们在Android App和嵌入式应用中集成TensorFlow Lite。
TensorFlow Lite架构
如果想要理解TensorFlow Lite是如何实现上述特性的,我们必须要先了解一下TensorFlow Lite的架构设计。TensorFlow Lite的架构设计图,如图所示。
我们可以用这样的方式理解TensorFlow Lite与TensorFlow的差异,首先需要训练一个TensorFlow的模型文件,然后使用TensorFlow Lite的模型转换器将TensorFlow模式转换为TensorFlow Lite的模型文件(.tflite格式)。接着可以在移动应用里使用转换好的文件。 我们可以在Android和iOS上使用TensorFlow Lite,通过TensorFlow Lite加载转换好的.tflite模型文件。TensorFlow Lite提供了下列调用方式。
- Java API:Android上基于C++ API封装的Java API,便于Android App的应用层直接调用。
- C++ API:可以用于装载TensorFlow Lite模型文件,构造调用解释器。Android和iOS平台都可以使用该API。
- 解释器(interpreter):负责执行模型并根据网络结构调用算子的核算法(kernel)。核算法的加载是可选择的。如果我们不使用加速的核算法,只需要100KB的空间;如果链接了所有的加速核算法,也只有300KB,整体体积是非常小的。在部分Android设备上,解释器会直接调用Android Neural Networks API实现硬件加速。 最后,我们可以通过C++ API实现自己的核算法,然后通过解释器加载,用在深度网络的执行中。
TensorFlow Lite代码结构
TensorFlow Lite和TensorFlow是两套基本独立的代码,完整的代码可以在TensorFlow的GitHub仓库插图中找到。这里着重介绍一下TensorFlow Lite的代码结构,这对我们后续的实战内容会有极大帮助。 在TensorFlow代码根目录下有一个lite目录,这就是完整的TensorFlow Lite代码。 为了便于读者阅读TensorFlow的完整代码,这里我们介绍一下TensorFlow Lite的代码结构和一些重要的文件,如下表所示。
目录/文件 | 解释 |
c | TensorFlow Lite的C API接口层实现,这部分接口也可以在C++中使用 |
core | TensorFlow Lite核心接口与实现,主要包括SubGraph结构,FlatBuffer转换和模型算子解析等功能 |
delegates | TensorFlow Lite的代理实现,这部分代码目前为实验性接口,主要用于支持TensorFlow Lite调用GPU或者NNAPI接口完成实际的计算任务。这样可以确保无论计算引起是什么都能向调用者提供一致的调用接口。 |
java | TensorFlow Lite Java接口实现,包括C++的JNI实现与Java的类定义,这部分会在移动平台实现中具体阐述。 |
kernels | TensorFlow的核心函数实现,包括所有的激活函数以及算子实现,可以满足大部分深度学习任务 |
kernels/internal | TensorFlow的核心内部实现,为算子实现提供必需的基础设置,包括基础类型定义、张量实现、量化实现甚至是MFCC算法。其中kernels/internal/optimized目录是针对不同移动平台的优化实现,包括基于Eigen或者Neon的加速实现。Neon实现中包含大量的汇编与C API优化实现。 |
nnapi | Android NNAPI实现,该部分仅支持在Android下使用。 |
profiling | TensorFlow Lite内部性能测量统计实现。 |
python | TensorFlow Lite的Python接口实现,包括Python的C层实现与Python层的类与函数定义,这部分会在移动平台实现中具体阐述。 |
schema | TensorFlow Lite数据结构的FlatBuffer模式定义,主要包括头文件的生成器与模型定义文件。模式定义文件包括fbs文件(原始定义)和FlatBuffer编译器生成的C代码中使用的头文件。 |
toco | 模型转换工具实现,实际包含了模型、模型量化和其他的模型优化实现。支持从命令行直接调用,也支持Python接口调用,便于我们集成在自己的构建工具链中 |
tools | 内部工具库实现,包括模型准确度测量库,解释器性能统计库,模型优化库,模型验证库等 |
allocation.h/cc | 内部分配器实现,主要目的是优化移动平台内存分配实现 |
builtin_ops.h | 内部算子定义,主要定义内部算子的枚举值 |
context.h | TensorFlow Lite执行上下文实现,由于TensorFlow Lite Context已经在C实现中定义,因此该文件直接饮引用了C层API的内部实现 |
graph_info.h/cc | TensorFlow Lite图信息实现,主要定义了图的数据结构,包括图的所有节点、输入、输出与存储变量 |
interpreter.h/cc | TensorFlow Lite的解释器实现。定义了Interpreter类,是C++层调用TensorFlow Lite的外层接口。该类主要支持:1、建立图和模型的内部结构;2、添加图的内部节点,设置节点参数;3、获取/设置图的输入;4、获取/设置图的输出;5、获取/设置图的变量;6、获取/修改图内部张量数据;7、其他参数设置;8、执行模型 |
model.h/cc | TensorFlow Lite模型实现,主要包括FlatBufferModel类与InterpretBuilder类。FlatBufferModel类负责从模型文件中读取数据并将其转换为TensorFlow Lite的内部模型数据结构。InterpretBuilder类负责根据用户指定的FlatBufferModel、OpResolver构建Interpreter对象。避免用户运行时手动构建图 |
nnapi_delegate.h/cc | NNAPI的代理实现,主要用于隔离接口与具体实现 |
string_util.h/cc | StringRef类型实现,定义封装了内部的字符串存储与相关工具函数实现 |
util.h/cc | 其他工具函数实现 |