Tensorflow Lite从入门到精通

TensorFlow Lite 是 TensorFlow 在移动和 IoT 等边缘设备端的解决方案,提供了 Java、Python 和 C++ API 库,可以运行在 Android、iOS 和 Raspberry Pi 等设备上。目前 TFLite 只提供了推理功能,在服务器端进行训练后,经过如下简单处理即可部署到边缘设备上。

个人使用总结:

  1. 如果我们只使用Tensorflow的高级API搭建模型,那么将TF转TF Lite再转TF lite micro的过程会相对顺利。但是如果我们的模型使用了自定义模块,那么转换过程会遇到很多麻烦,Tensorflow对自家高级API的转换提供了很好的支持,但对我们自己写的一些NN 算子支持不佳。
  2. Tensorflow LSTM的流式部署是有难度的,请使用最新的Tensorflow版本,将unrool打开,再尝试

转换模型

我们可以通过以下两种方式将Tensorflow模型 转换成 TF Lite:

  1. Python API(推荐,且本文主讲):它让您可以更轻松地在模型开发流水线中转换模型、应用优化、添加元数据,并且拥有更多功能。
  2. 命令行:它仅支持基本模型转换。

我们可以根据保存模型的方式来选择转换成TF lite的方式:

1、tf.lite.TFLiteConverter.from_saved_model()(推荐):转换 SavedModel

 View Code

2、tf.lite.TFLiteConverter.from_keras_model():转换 Keras 模型

 View Code

3、tf.lite.TFLiteConverter.from_concrete_functions():转换 具体函数

 View Code

转换RNN模型为TFLite

由于 TensorFlow 中 RNN API 的变体很多,我们的转换方式包括两个方面:

  1. 为标准 TensorFlow RNN API(如 Keras LSTM)提供原生支持。这是推荐的选项。
  2. 提供 进入转换基础架构的接口,用于 插入用户定义的 RNN 实现并转换为 TensorFlow Lite。我们提供了几个有关此类转换的开箱即用的示例,这些示例使用的是 lingvo 的 LSTMCellSimple 和 LayerNormalizedLSTMCellSimple RNN 接口。

Tensorflow官方提供了一个一个非常棒的案例:Keras LSTM fusion Codelab.ipynb

运行推理

TensorFlow Lite 推理通常遵循以下步骤:

  1. 加载模型
  2. 转换数据
  3. 运行推断
  4. 解释输出
import numpy as np
import tensorflow as tf

# 加载TFLite模型并分配张量
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']  # 获取输入的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()  # 运行
# 函数`get_tensor()`返回张量数据的副本
# 使用`tensor()`来获得一个指向这个张量的指针
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

定义了Signature的TFLite 推理

 View Code

优化模型

Tensorflow Lite 和 Tensorflow Model Optimization Toolkit (Tensorflow模型优化工具包)提供了最小优化推理复杂性的工具,可将优化推断的复杂性降至最低。深度神经网络的量化使用了一些技术,这些技术可以降低权重的精确表示,并且降低存储和计算。 TensorFlow Model Optimization Toolkit 目前支持通过量化、剪枝和聚类进行优化

剪枝:剪枝的工作原理是移除模型中对其预测影响很小的参数。剪枝后的模型在磁盘上的大小相同,并且具有相同的运行时延迟,但可以更高效地压缩。这使剪枝成为缩减模型下载大小的实用技术

未来,TensorFlow Lite 将降低剪枝后模型的延迟。

聚类:聚类的工作原理是将模型中每一层的权重归入预定数量的聚类中,然后共享属于每个单独聚类的权重的质心值。这就减少了模型中唯一权重值的数量,从而降低了其复杂性。这样一来,就可以更高效地压缩聚类后的模型,从而提供类似于剪枝的部署优势。

开发工作流程

  1. 首先,检查托管模型中的模型能否用于您的应用。如果不能,建议从训练后量化工具开始,因为它适用范围广,且无需训练数据。
  2. 对于无法达到准确率和延迟目标,或硬件加速器支持很重要的情况,**量化感知训练**是更好的选择。请参阅 TensorFlow Model Optimization Toolkit 下的其他优化技术。
  3. 如果要进一步缩减模型大小,可以在量化模型之前尝试剪枝和/或聚类。

量化

有两种形式的量化:训练后量化和量化感知训练。请从训练后量化开始,因为它更易于使用,尽管量化感知训练在模型准确率方面的表现通常更好。

量化感知训练

等我将代码进行了训练后量化后,再来整这个量化感知训练

训练后量化

量化的工作原理是降低模型参数的精度(默认情况为 32 位浮点数)。这样可以获得较小的模型大小和较快的计算速度。TensorFlow Lite 提供以下量化类型:

技术数据要求大小缩减准确率
训练后 Float16 量化无数据高达 50%轻微的准确率损失
训练后 动态范围量化无数据高达 75%,速度加快 2-3倍极小的准确率损失
训练后 int8 量化无标签的代表性样本高达 75%,速度加快3+倍极小的准确率损失
量化感知训练带标签的训练数据高达 75%极小的准确率损失

以下决策树可帮助您仅根据预期的模型大小和准确率来选择要用于模型的量化方案。

动态范围量化

权重(float32) 会在训练后量化为 整型(int8),激活会在推断时动态量化,模型大小缩减至原来的四分之一:

TFLite 支持对激活进行动态量化(激活始终以浮点进行存储。对于支持量化内核的算子,激活会在处理前动态量化为 8 位精度,并在处理后反量化为浮点精度。根据被转换的模型,这可以提供比纯浮点计算更快的速度)以实现以下效果:

  1. 在可用时使用量化内核加快实现速度。
  2. 将计算图不同部分的浮点内核与量化内核混合。
import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
# 启动默认的 optimizations 来量化所有固定参数(权重)
converter.optimizations = [tf.lite.Optimize.DEFAULT] 
tflite_quant_model = converter.convert()

此优化提供的延迟接近全定点推断。但是,输出仍使用浮点进行存储因此使用动态范围算子的加速小于全定点计算

我们来吃一个完整的栗子,构建一个MNIST模型,并且对它使用动态范围量化,对比量化前后的精度变化:

 View Code

更多细节请参考:Tensorflow官方文档 训练后动态范围量化

全整型量化

整型量化是将32位浮点数 转换为8位定点数。这样可以缩减模型大小并加快推理速度,这对低功耗设备(如微控制器)很有价值。仅支持整数的加速器(如 Edge TPU)也需要使用此数据格式。

对于全整数量化,需要校准或估算模型中所有浮点张量的范围,即 (min, max)。与权重和偏差等常量张量不同,模型输入、激活(中间层的输出)和模型输出等变量张量不能校准,除非我们运行几个推断周期。因此,转换器需要一个有代表性的数据集来校准它们。这个数据集可以是训练数据或验证数据的一个小子集(大约 100-500 个样本)。请参阅下面的  representative_dataset() 函数。

从 TensorFlow 2.7 版本开始,您可以通过签名指定代表数据集,示例如下:

 View Code

如果给定的 TensorFlow 模型中有多个签名,则可以通过指定签名密钥来指定多个数据集:

 View Code

您可以通过提供输入张量列表来生成代表性数据集:

 View Code

从 TensorFlow 2.7 版本开始,我们推荐使用基于签名的方法,而不是基于输入张量列表的方法,因为输入张量排序可以很容易地翻转。

出于测试目的,您可以使用如下所示的虚拟数据集:

 View Code

1、模型整型量化,输入输出还是浮点

启动默认的 optimizations 只能量化固定参数(如:权重),但是模型输入/输出 和层之间的状态值 依然是浮点型的,要量化可变中间值,您需要提供 RepresentativeDataset。这是一个生成器函数,它提供一组足够大的输入数据来代表典型值。converter 可以通过该函数估算所有可变数据的动态范围(相比训练或评估数据集,此数据集不必唯一)为了支持多个输入,每个代表性数据点都是一个列表,并且列表中的元素会根据其索引被馈送到模型。

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_keras_model(model)
# 启动默认的 optimizations 来量化所有固定参数(权重)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
# 要量化可变数据(模型输入/输出 和层之间的中间体),提供 RepresentativeDataset,来估算所有可变数据的动态范围
converter.representative_dataset = representative_data_gen
tflite_model_quant = converter.convert()

现在,所有权重和可变数据都已量化,并且与原始 TensorFlow Lite 模型相比,该模型要小得多。

但是,为了与传统上使用浮点模型输入和输出张量的应用保持兼容,TensorFlow Lite 转换器将模型的输入和输出张量保留为浮点,这通常对兼容性有利,但它无法兼容执行全整形运算的设备(如 Edge TPU)。

interpreter = tf.lite.Interpreter(model_content=tflite_model_quant)
input_type = interpreter.get_input_details()[0]['dtype']
print('input: ', input_type)    # <class 'numpy.float32'>
output_type = interpreter.get_output_details()[0]['dtype']
print('output: ', output_type)  # <class 'numpy.float32'>

2、全整型量化

为了量化输入和输出张量,我们需要使用一些附加参数再次转换模型:

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]    # 先启动默认的optimizations将模型权重进行量化
converter.representative_dataset = representative_data_gen  # 使用代表数据集量化模型中间值
# 如果有任何的 ops不能量化,converter 将抛出错误
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] 
# 将输入和输出tensors设置为int8 类型
converter.inference_input_type = tf.int8   # or tf.uint8
converter.inference_output_type = tf.int8  # or tf.uint8

tflite_model_quant = converter.convert()

现在我们可以看到输入和输出张量现在是整数格式:

interpreter = tf.lite.Interpreter(model_content=tflite_model_quant)
input_type = interpreter.get_input_details()[0]['dtype']
print('input: ', input_type)    # <class 'numpy.int8'>
output_type = interpreter.get_output_details()[0]['dtype']
print('output: ', output_type)  # <class 'numpy.int8'>

我们来整一个栗子,您将从头开始训练一个 MNIST 模型、将其转换为 TensorFlow Lite 文件,并使用训练后整型量化。最后,将检查转换后模型的准确率并将其与原始浮点模型进行比较。

 View Code

更多细节请参考:Tensorflow官方文档训练后整型量化

float16量化

现在,TensorFlow Lite 支持在模型从 TensorFlow 转换到 TensorFlow Lite FlatBuffer 格式期间将权重转换为 16 位浮点值。这样可以将模型的大小缩减至原来的二分之一。某些硬件(如 GPU)可以在这种精度降低的算术中以原生方式计算,从而实现比传统浮点执行更快的速度。可以将 Tensorflow Lite GPU 委托配置为以这种方式运行。但是,转换为 float16 权重的模型仍可在 CPU 上运行而无需其他修改:float16 权重会在首次推理前上采样为 float32。这样可以在对延迟和准确率造成最小影响的情况下显著缩减模型大小。

float16 量化的优点如下:

  • 将模型的大小缩减一半(因为所有权重都变成其原始大小的一半)。
  • 实现最小的准确率损失。
  • 支持可直接对 float16 数据进行运算的部分委托(例如 GPU 委托),从而使执行速度比 float32 计算更快。

float16 量化的缺点如下:

  • 它不像对定点数学进行量化那样减少那么多延迟。
  • 默认情况下,float16 量化模型在 CPU 上运行时会将权重值“反量化”为 float32。(请注意,GPU 委托不会执行此反量化,因为它可以对 float16 数据进行运算)
import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()

在本教程中,您将从头开始训练一个 MNIST 模型,并在 TensorFlow 中检查其准确率,然后使用 float16 量化将此模型转换为 Tensorflow Lite FlatBuffer 格式。最后,检查转换后模型的准确率,并将其与原始 float32 模型进行比较。

 View Code

仅整数:具有 8 位权重的 16 位激活(实验性)

这是一个实验性量化方案。它与“仅整数”方案类似,但会根据激活的范围将其量化为 16 位,权重会被量化为 8 位整数,偏差会被量化为 64 位整数。这被进一步称为 16x8 量化。

这种量化的主要优点是可以显著提高准确率,但只会稍微增加模型大小。

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
tflite_quant_model = converter.convert()

如果模型中的部分算子不支持 16x8 量化,模型仍然可以量化,但不受支持的算子会保留为浮点。要允许此操作,应将以下选项添加到 target_spec 中。

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
                                       tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_quant_model = converter.convert()

这种量化的缺点是:

  • 由于缺少优化的内核实现,目前的推断速度明显比 8 位全整数慢。
  • 目前它不兼容现有的硬件加速 TFLite 委托。

注:这是一项实验性功能。

可以在此处找到该量化模型的教程。

模型准确率

由于权重是在训练后量化的,因此可能会造成准确率损失,对于较小的网络尤其如此。TensorFlow Hub 为特定网络提供了预训练的完全量化模型。请务必检查量化模型的准确率,以验证准确率的任何下降都在可接受的范围内。有一些工具可以评估 TensorFlow Lite 模型准确率。

另外,如果准确率下降过多,请考虑使用量化感知训练。但是,这样做需要在模型训练期间进行修改以添加伪量化节点,而此页面上的训练后量化技术使用的是现有的预训练模型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/310184.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++11_lambda表达式

文章目录 一、lambda表达式1.lambda的组成2.[capture-list] 的其他使用方法2.1混合捕捉 二、lambda表达式的使用场景1.替代仿函数 总结 一、lambda表达式 lambda表达式是C11新引入的功能&#xff0c;它的用法与我们之前学过的C语法有些不同。 1.lambda的组成 [capture-list] …

消息开始事件message start event

一&#xff1a;bpmn 二&#xff1a;java repositoryService.createDeployment().name("消息事件流程").addClasspathResource("bpmn/msg_event_process.bpmn").deploy(); identityService.setAuthenticatedUserId("huihui"); ProcessInstance p…

vue3中ref和reactive联系与区别以及如何选择

vue3中ref和reactive区别与联系 区别 1、ref既可定义基本数据类型&#xff0c;也可以定义引用数据类型&#xff0c;reactive只能定义应用数据类型 2、ref在js中取响应值需要使用 .value&#xff0c;而reactive则直接取用既可 3、ref定义的对象通过.value重新分配新对象时依旧…

放电深度对电池寿命的影响

一、SOC和DOD概念 SOC&#xff1a;State Of Charge. 电池SOC是指荷电状态&#xff0c;是用来反映电池的剩余容量的&#xff0c;其数值上定义为剩余容量占电池容量的比值&#xff0c;常用百分数表示&#xff1b;其取值范围为0~1&#xff0c;当“SOC0”时表示电池放电完全&#…

python爬虫实战(6)--获取某度热榜

1. 项目描述 需要用到的类库 pip install requests pip install beautifulsoup4 pip install pandas pip install openpyxl然后&#xff0c;我们来编写python脚本&#xff0c;并引入需要的库&#xff1a; import requests from bs4 import BeautifulSoup import pandas as p…

SpringBoot 自动装配原理

一、什么是自动装配 自动装配是指应用程序启动时由容器自动扫描和装配相关的组件和模块&#xff0c;无须像传统的spring那样在xml文件中手动配置Bean&#xff0c;从而简化了应用程序的配置过程&#xff0c;提高开发效率。 二、SpringBootApplication解析 进入到这个 SpringB…

概率中的 50 个具有挑战性的问题 [9/50]:掷骰子

一、说明 我最近对与概率有关的问题产生了兴趣。我偶然读到了弗雷德里克莫斯特勒&#xff08;Frederick Mosteller&#xff09;的《概率论中的五十个具有挑战性的问题与解决方案》&#xff09;一书。我认为创建一个系列来讨论这些可能作为面试问题出现的迷人问题会很有趣。每篇…

你需要尽早知道的15个开源网络安全工具

在本文中&#xff0c;你将找到一个开放源码网络安全工具列表&#xff0c;你一定要查看这些工具。 开源工具代表了技术版图中的一股有活力的力量&#xff0c;体现了创新、协作和可访问性&#xff0c;这些工具是根据透明度和社区驱动的原则开发的&#xff0c;使用户能够根据其独特…

Vue-13、Vue深度监视

1、监视多级结构中某个属性的变化 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>watch深度监视</title><script type"text/javascript" src"https://cdn.jsdelivr.net/npm…

Vue基础-搭建Vue运行环境

这篇文章介绍了在Vue.js项目中进行开发环境搭建的关键步骤。包括node.js安装和配置、安装Vue及Vue CLI工具、安装webpack模板、安装vue-router、创建Vue项目等步骤。这篇文章为读者提供了清晰的指南&#xff0c;帮助他们快速搭建Vue.js开发环境&#xff0c;为后续的项目开发奠定…

端到端自动驾驶

自动驾驶主要流程&#xff1a;感知->预测->规划 预测是预测周围目标&#xff08;车、行人、动物等&#xff09;的轨迹&#xff0c;规划是规划自车的运动轨迹。 UniAD[CVPR 2023]: 使用transformer架构&#xff0c;统一自动驾驶流程&#xff0c;完成所有检测&#xff0c…

如何上传苹果ipa安装包?

目录 引言 摘要 第二步&#xff1a;打开appuploader工具 第二步&#xff1a;打开appuploader工具&#xff0c;第二步&#xff1a;打开appuploader工具 第五步&#xff1a;交付应用程序&#xff0c;在iTunes Connect中查看应用程序 总结 引言 在将应用程序上架到苹果应用…

Navicat 技术干货 | 为 MySQL 表选择合适的存储引擎

MySQL 是最受欢迎的关系型数据库管理系统之一&#xff0c;提供了不同的存储引擎&#xff0c;每种存储引擎都旨在满足特定的需求和用例。在优化数据库和确保数据完整性方面&#xff0c;选择合适的存储引擎是至关重要的。今天&#xff0c;我们将探讨为 MySQL 表选择合适的存储引擎…

【开源项目】轻量元数据管理解决方案——Marquez

大家好&#xff0c;我是独孤风。 又到了本周的开源项目推荐。最近推荐的元数据管理项目很多&#xff0c;但是很多元数据管理平台的功能复杂难用。 那么有没有轻量一点的元数据管理项目呢&#xff1f; 今天为大家推荐的开源项目&#xff0c;就是一个轻量级的元数据管理工具。虽然…

《SPSS统计学基础与实证研究应用精解》视频讲解:SPSS的功能特色

《SPSS统计学基础与实证研究应用精解》1.2 SPSS的功能特色 视频为《SPSS统计学基础与实证研究应用精解》张甜 杨维忠著 清华大学出版社 一书的随书赠送视频讲解1.2节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。本书旨在手把手…

NSSCTF Interesting_include

开启环境: 通过审计,我们可知: flag在flag.php中,可以利用php中伪协议 payload:?filterphp://filter/readconvert.base64-encode/resourceflag.php 将其base64解码就是flag. NSSCTF{3dc54721-be9e-444c-8228-7133fba76ad4}

回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.CPO-BP回归基于冠豪猪优化算法[24年新…

关于Vue前端接口对接的思考

关于Vue前端接口对接的思考 目录概述需求&#xff1a; 设计思路实现思路分析1.vue 组件分类和获取数值的方式2.http 通信方式 分类 如何对接3.vue 组件分类和赋值方式&#xff0c; 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your p…

力扣最热一百题——只出现一次的数字

这个合集已经很久没有更新了&#xff0c;今天来更新更新~~~ 目录 力扣题号 题目 题目描述 示例 提示 题解 Java解法一&#xff1a;Map集合 Java解法二&#xff1a;位运算 C位运算代码 力扣题号 136. 只出现一次的数字 - 力扣&#xff08;LeetCode&#xff09; 下述题…

腾讯云对象存储COS计算文件的大小

properties配置类 TencentCos.APPIDxxxxx TencentCos.SecretIdxxxxxxx TencentCos.SecretKeyxxxxxx TencentCos.testBucketxxxxxx TencentCos.CosPathhttps://xxxxxxxx.cos.ap-chengdu.myqcloud.com TencentCos.regionap-chengdu读取properties中的配置 import lombok.AllArg…