)
人工智能深度学习推理引擎本地部署嵌入式物联网【免费下载链接】tflite-microInfrastructure to enable deployment of ML models to low-power resource-constrained embedded targets (including microcontrollers and digital signal processors).项目地址https://gitcode.com/gh_mirrors/tf/tflite-micro点击查看免费下载导读本文围绕 third_party/xtensa/examples/pytorch_to_tflite/pytorch_to_tflite_converter/README.md 展开系统讲解如何把 PyTorch 生态中的 MobileNetV2 分类模型转换为 TFLite 格式的int8 全整数量化模型以便最终部署到 tflite-micro 支持的低功耗嵌入式目标如 Cadence Xtensa HiFi5 DSP上。文章提供两条可复现的转换路径TinyNN 一键直转约 3 分钟与PyTorch → ONNX → TFLite 标准链路约 5 分钟并完整覆盖环境搭建、量化校准、参数调优、推理验证以及转换产物在仓库内的 Xtensa 平台测试验证读完即可在 Google Colaboratory 上照做。背景为什么需要 PyTorch → TFLite(int8) 转换tflite-micro 的目标是让机器学习模型在微控制器与数字信号处理器等低功耗、资源受限的嵌入式目标上运行。这类设备通常没有文件系统与动态内存管理对模型体积、算子支持与数值格式都有严格约束。PyTorch 训练出的模型无法直接被 tflite-micro 加载必须经过转换格式转换PyTorch 模型 → TFLite FlatBuffer 格式本仓库 tensorflow/lite/schema 目录中的schema_generated.h即该格式的 C 绑定量化把 float32 权重与激活转换为 int8从而显著缩小模型体积并利用嵌入式 DSP 的整数指令加速这也是 MobileNetV2 这类图像模型能跑进嵌入式设备的前提。仓库在 third_party/xtensa/examples/pytorch_to_tflite 目录中给出了完整示例目录内已包含转换产物 mobilenet_v2_quantized_1x3x224x224.tflite、对应的 C 语言测试 pytorch_to_tflite_test.cc 以及两个转换 Notebook。其中 tinynn_pytorch_to_tflite_int8.ipynb 与 pytorch_to_onnx_to_tflite_int8.ipynb 分别对应 README 中介绍的两条转换路径。两条路径的差异对比如下对比项路径一TinyNN 直接转换路径二PyTorch → ONNX → TFLite转换链路PyTorch → (TinyNN QAT) → TFLitePyTorch → ONNX → TF SavedModel → TFLite依赖工具TinyNeuralNetwork、torch、tensorflowonnx、onnxruntime、onnx-tf、tensorflow量化方式PostQuantizer 后训练量化 QAT 校准代表数据集representative dataset驱动全整数量化预估耗时README 标注~3 分钟~5 分钟关键产物out/qat_model.tfliteint8mobilenet_v2_float32.tflitemobilenet_v2_1.0_224_quant.tfliteint8路径一TinyNN 一键直转 PyTorch → TFLiteint8该路径在 Google Colaboratory 中完成核心思路是先用 TinyNN 的PostQuantizer对预训练 MobileNetV2 做后训练量化并得到带QuantStub/DeQuantStub的 QAT 模型再借少量真实图片做校准前向最后调用torch.quantization.convert与 TinyNN 的TFLiteConverter直接产出 int8 的.tflite文件。1. 环境准备安装 TinyNeuralNetwork第一个 Notebook 通过pip从源码安装 TinyNeuralNetwork安装日志显示它会一并拉取ruamel.yaml、python-igraph、tflite2.3.0、PyYAML、flatbuffers、texttable等依赖!pip install githttps://github.com/alibaba/TinyNeuralNetwork.git随后导入转换所需的全部模块import random from glob import glob from PIL import Image import torch from torchvision import transforms import torchvision.models as models from tinynn.converter import TFLiteConverter from tinynn.graph.quantization.quantizer import PostQuantizer from tinynn.graph.tracer import model_tracer from tinynn.util.cifar10 import get_dataloader, train_one_epoch, validate from tinynn.util.train_util import DLContext, get_device, train2. 下载校准数据集量化需要真实数据来统计激活值的动态范围。Notebook 下载的是 TensorFlow 官方教学使用的猫狗二分类数据集cats_and_dogs_filtered.zip约 65 MB!wget --no-check-certificate \ https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip \ -O /content/cats_and_dogs_filtered.zipimport os import zipfile local_zip /content/cats_and_dogs_filtered.zip zip_ref zipfile.ZipFile(local_zip, r) zip_ref.extractall(/content) zip_ref.close()3. 模型追踪与 QAT 量化准备TinyNN 通过model_tracer()上下文追踪模型结构加载预训练的 MobileNetV2 并构造dummy_input形状(1, 3, 224, 224)与仓库内转换产物文件名mobilenet_v2_quantized_1x3x224x224一致random.seed(0) with model_tracer(): model models.mobilenet_v2(pretrainedTrue) model.eval() # Provide a viable input for the model dummy_input torch.rand((1, 3, 224, 224)) quantizer PostQuantizer(model, dummy_input, work_dirout, config{asymmetric: True, per_tensor: False}) qat_model quantizer.quantize() print(qat_model)PostQuantizer的关键配置说明配置项示例值含义work_dirout量化中间产物onnx/qat 模型的输出目录config[asymmetric]True使用非对称量化带 zero point更贴合常见 int8 部署格式config[per_tensor]False逐通道per-channel量化权重精度损失更小量化后的模型打印结果可以清楚看到 TinyNN 在每个卷积层后插入了HistogramObserver用于校准期间统计激活值分布并在输入/输出端插入了QuantStub/DeQuantStub这正是后面 QAT 微调与转换的基础。4. 校准前向用真实图片驱动量化范围估计将 QAT 模型搬到 GPU 上从猫狗训练集中随机取 100 张图片按 ImageNet 的标准预处理Resize(256)→CenterCrop(224)→ToTensor→Normalize后逐张前向让各层的HistogramObserver收集激活分布if torch.cuda.device_count() 1: qat_model nn.DataParallel(qat_model) device get_device() qat_model.to(devicedevice) dataset_list glob(/content/cats_and_dogs_filtered/train/**/*, recursiveTrue) random.shuffle(dataset_list) for i in range(100): filename dataset_list[i] input_image Image.open(filename) preprocess transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) input_tensor preprocess(input_image) input_tensor torch.unsqueeze(input_tensor, 0) qat_model(input_tensor.to(devicedevice))5. 转换为真正量化的 TFLite 模型校准完成后在torch.no_grad()下执行torch.quantization.convert把带伪量化节点的 QAT 模型固化为使用量化内核的真实量化模型再交给 TinyNN 的TFLiteConverter输出 int8 TFLitewith torch.no_grad(): qat_model.eval() qat_model.cpu() # The step below converts the model to an actual quantized model, which uses the quantized kernels. qat_model torch.quantization.convert(qat_model) # When converting quantized models, please ensure the quantization backend is set. torch.backends.quantized.engine quantizer.backend # The code section below is used to convert the model to the TFLite format converter TFLiteConverter(qat_model, dummy_input, tflite_pathout/qat_model.tflite, quantize_target_typeint8, input_transposeFalse, fuse_quant_dequantTrue) converter.convert()Notebook 注释中给出的TFLiteConverter参数说明quantize_target_typeint8指定输出量化目标类型如需其他数据类型可相应调整strict_symmetric_checkTrue可选当需要对预定义 zero point 做严格对称量化检查时启用input_transposeFalse控制输入张量是否需要转置PyTorch 的NCHW与 TFLite 布局的差异处理fuse_quant_dequantTrue融合相邻的 Quantize/Dequantize 节点减少图冗余。运行成功时控制台会打印INFO (tinynn.converter.base) Generated model saved to out/qat_model.tflite。6. 在 TensorFlow Lite 中验证转换结果最后一步用tf.lite.Interpreter加载生成的 int8 模型并跑真实图片。关键点在于读取输入张量的scale与zero_point用 PyTorch 的torch.quantize_per_tensor把预处理后的 float 图像量化成 qint8再经int_repr取整数表示喂给解释器import urllib url, filename (https://github.com/pytorch/hub/raw/master/images/dog.jpg, dog.jpg) try: urllib.URLopener().retrieve(url, filename) except: urllib.request.urlretrieve(url, filename) import tensorflow as tf import numpy as np tflite_model_path /content/out/qat_model.tflite interpreter tf.lite.Interpreter(model_pathtflite_model_path) interpreter.allocate_tensors() input_details interpreter.get_input_details() output_details interpreter.get_output_details() test_details interpreter.get_input_details()[0] scale, zero_point test_details[quantization] print(scale) print(zero_point) from PIL import Image from torchvision import transforms input_image Image.open(filename) preprocess transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) input_tensor preprocess(input_image) input_tensor torch.unsqueeze(input_tensor, 0) input_tensor torch.quantize_per_tensor(input_tensor, torch.tensor(scale), torch.tensor(zero_point), torch.qint8) input_tensor torch.int_repr(input_tensor).numpy() interpreter.set_tensor(input_details[0][index], input_tensor) interpreter.invoke() output_data interpreter.get_tensor(output_details[0][index]) print(Predicted value . Label index: {}, confidence: {:2.0f}% .format(np.argmax(output_data), 100 * output_data[0][np.argmax(output_data)]))Notebook 记录的实测输出中该模型的输入量化参数为scale0.01871182955801487、zero_point-15推理得到Label index: 258对应 ImageNet 中的金毛寻回犬类别与路径二的量化模型结果一致。路径二PyTorch → ONNX → TFLiteint8当希望走业界通用的 ONNX 中间格式便于后续对接 ONNX Runtime 等工具链时使用第二个 Notebook 的五步链路导出 ONNX → 校验 → onnx-tf 转 SavedModel → 转 float32 TFLite → 代表数据集全整数量化。1. 安装 ONNX 与 ONNX Runtime!pip install onnx !pip install onnxruntime import numpy as np import torch import torch.onnx import torchvision.models as models import onnx import onnxruntime2. 从 torchvision 加载 MobileNetV2 并导出 ONNX加载预训练模型并进入推理模式日志显示权重文件mobilenet_v2-b0353104.pth约 13.6 MB首次运行会自动下载model models.mobilenet_v2(pretrainedTrue) model.eval()导出 ONNX 时torch.onnx.export的参数直接决定了产物形态IMAGE_SIZE 224 BATCH_SIZE 1 x torch.randn(BATCH_SIZE, 3, 224, 224, requires_gradTrue) torch_out model(x) torch.onnx.export(model, # model being run x, # model input (or a tuple for multiple inputs) mobilenet_v2.onnx, # where to save the model export_paramsTrue, # store the trained parameter weights inside the model file opset_version10, # the ONNX version to export the model to do_constant_foldingTrue, # whether to execute constant folding for optimization input_names [input], # the models input names output_names [output], # the models output names dynamic_axes{input : {0 : BATCH_SIZE}, output : {0 : BATCH_SIZE}})各参数作用参数示例值说明export_paramsTrue把训练好的权重内嵌进 ONNX 文件opset_version10目标 ONNX 算子集版本需与下游转换工具兼容do_constant_foldingTrue开启常量折叠优化导出图input_names/output_names[input]/[output]指定输入/输出张量名便于下游引用dynamic_axes{0: BATCH_SIZE}声明 batch 维为动态轴3. 校验 ONNX 并与 PyTorch 结果对齐先用 ONNX 自带 checker 校验图结构合法性再用 ONNX Runtime 跑一遍同样的输入与 PyTorch 输出做数值对齐rtol1e-03, atol1e-05onnx_model onnx.load(mobilenet_v2.onnx) onnx.checker.check_model(onnx_model)ort_session onnxruntime.InferenceSession(mobilenet_v2.onnx) def to_numpy(tensor): return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy() ort_inputs {ort_session.get_inputs()[0].name: to_numpy(x)} ort_outs ort_session.run(None, ort_inputs) np.testing.assert_allclose(to_numpy(torch_out), ort_outs[0], rtol1e-03, atol1e-05) print(Exported model has been tested with ONNXRuntime, and the result looks good!)实测输出为Exported model has been tested with ONNXRuntime, and the result looks good!确认导出无误。4. ONNX → TF SavedModel → float32 TFLite安装onnx-tf用其prepare后端把 ONNX 图导出为 TensorFlow SavedModel 目录model_tf!pip install onnx-tf from onnx_tf.backend import prepare import onnx onnx_model_path mobilenet_v2.onnx tf_model_path model_tf onnx_model onnx.load(onnx_model_path) tf_rep prepare(onnx_model) tf_rep.export_graph(tf_model_path)随后用 TensorFlow 原生转换器得到 float32 版本的 TFLiteimport tensorflow as tf saved_model_dir model_tf tflite_model_path mobilenet_v2_float32.tflite converter tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) tflite_model converter.convert() with open(tflite_model_path, wb) as f: f.write(tflite_model)5. float32 模型的推理验证先用随机数据快速验证输入输出形状与基本推理通路Notebook 输出显示输入形状为[1 3 224 224]import numpy as np import tensorflow as tf tflite_model_path /content/mobilenet_v2_float32.tflite interpreter tf.lite.Interpreter(model_pathtflite_model_path) 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), dtypenp.float32) interpreter.set_tensor(input_details[0][index], input_data) interpreter.invoke() output_data interpreter.get_tensor(output_details[0][index])再用真实猫图验证TensorFlow 侧读图、解码、resize 到 224 并 reshape 为[1, 3, 224, 224]DUMP INPUT/DUMP OUTPUT表明输入名serving_default_input:0、输出名PartitionedCall:0均为float32且quantization: (0.0, 0)未量化image tf.io.read_file(/content/cats_and_dogs_filtered/validation/cats/cat.2000.jpg) image tf.io.decode_jpeg(image, channels3) image tf.image.resize(image, [IMAGE_SIZE, IMAGE_SIZE]) image tf.reshape(image,[3,IMAGE_SIZE,IMAGE_SIZE]) image tf.expand_dims(image, 0) interpreter.set_tensor(input_details[0][index], image) interpreter.invoke() output_data interpreter.get_tensor(output_details[0][index])6. 代表数据集驱动 int8 全整数量化float32 模型无法直接用于嵌入式部署需要再走一次代表数据集量化。核心是提供representative_data_gen_1生成器从猫狗训练集取 100 张图做带数据增强的预处理RandomCrop(224, padding4)、Resize(224)、RandomHorizontalFlip、ToTensor、Normalize后逐张yieldconverter tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) # This enables quantization converter.optimizations [tf.lite.Optimize.DEFAULT] # This sets the representative dataset for quantization converter.representative_dataset representative_data_gen_1 # This ensures that if any ops cant be quantized, the converter throws an error converter.target_spec.supported_ops [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] # For full integer quantization, though supported types defaults to int8 only, we explicitly declare it for clarity. converter.target_spec.supported_types [tf.int8] # These set the input and output tensors to uint8 (added in r2.3) converter.inference_input_type tf.int8 converter.inference_output_type tf.int8 tflite_model converter.convert() with open(mobilenet_v2_1.0_224_quant.tflite, wb) as f: f.write(tflite_model)这段代码的每个配置项都是 int8 全整数量化的关键配置项值作用optimizations[tf.lite.Optimize.DEFAULT]开启默认量化优化representative_dataset生成器函数提供校准数据统计激活动态范围target_spec.supported_ops[TFLITE_BUILTINS_INT8]只允许 int8 内建算子遇到无法量化的算子直接报错target_spec.supported_types[tf.int8]显式声明仅支持 int8 类型inference_input_type/inference_output_typetf.int8输入输出张量也强制 int8实现全整数量化7. int8 量化模型的推理验证对量化模型跑 dog.jpg 时读取到的输入量化参数为scale0.020324693992733955、zero_point-8喂入的 int8 输入张量取值区间约在[-109, -27]推理输出同样为Label index: 258说明量化前后预测类别保持一致import tensorflow as tf import numpy as np tflite_model_path /content/mobilenet_v2_1.0_224_quant.tflite interpreter tf.lite.Interpreter(model_pathtflite_model_path) interpreter.allocate_tensors() input_details interpreter.get_input_details() output_details interpreter.get_output_details() test_details interpreter.get_input_details()[0] scale, zero_point test_details[quantization] print(scale) print(zero_point) # ... 与路径一相同的图像预处理与量化quantize_per_tensor → int_repr... interpreter.set_tensor(input_details[0][index], input_tensor) interpreter.invoke() output_data interpreter.get_tensor(output_details[0][index])MobileNetV2int8 量化模型架构README 指出示例模型即 MobileNetV2并给出了量化模型的架构图。从 TinyNN 路径打印的量化模型结构可以看到int8 量化后的 MobileNetV2 不再是一个普通的浮点骨干网而是由 18 个带HistogramObserver的量化倒残差块features_0~features_17串成的主干、末尾Conv2d(320, 1280)ReLU6、DropoutLinear(1280, 1000)分类头以及输入QuantStub、输出DeQuantStub和 10 个FloatFunctional加法节点对应倒残差块的残差连接共同组成的量化算子链架构图位于 third_party/xtensa/examples/pytorch_to_tflite/images/qat_model.png其中每个卷积层都插入了用于统计激活分布的HistogramObserver。在 tflite-micro 上验证转换产物XTensa HiFi5转换只是第一步最终要验证的是 TFLite 模型能被 tflite-micro 正确加载并推理。仓库已经把路径一/路径二产出的 int8 模型固化在 third_party/xtensa/examples/pytorch_to_tflite/mobilenet_v2_quantized_1x3x224x224.tflite并由构建系统自动转换为 C 数组mobilenet_v2_quantized_1x3x224x224_model_data.h配套的 pytorch_to_tflite_test.cc 演示了标准 TFLM 推理流程用tflite::GetModel解析模型HIFI5宏下编译即仅针对 Xtensa HiFi5使用 pytorch_op_resolver.h 中定义的PytorchOpsResolver即tflite::MicroMutableOpResolver128最多注册 128 个算子按需注册算子分配 3 MB 的tensor_arena构建MicroInterpreter并AllocateTensors()校验输入张量为kTfLiteInt8、形状[1, 3, 224, 224]将内置的 pytorch_images_dog_jpg.h 中的 int8 狗图数据memcpy到输入缓冲Invoke()后扫描 1000 维 int8 输出打印Label index与Confidence。构建接入由 Makefile.inc 完成仅当OPTIMIZED_KERNEL_DIRxtensa时启用该示例TARGET_ARCH非 hifi5 时注册pytorch_to_tflite_test测试目标。同级 README.md 给出了完整的 Xtensa 工具链环境与构建命令# Setup Xtensa Tools $ set path ( ~/xtensa/XtDevTools/install/tools/RI-2020.5-linux/XtensaTools/bin $path ) $ set path ( ~/xtensa/XtDevTools/install/tools/RI-2020.5-linux/XtensaTools/Tools/bin $path ) $ setenv XTENSA_SYSTEM ~xtensa/XtDevTools/install/tools/RI-2020.5-linux/XtensaTools/config $ setenv XTENSA_CORE AE_HiFi5_LE5_AO_FP_XC $ setenv XTENSA_TOOLS_VERSION RI-2020.5-linux $ setenv XTENSA_BASE ~/xtensa/XtDevTools/install/ # Clean and build mobilenet_v2 model on TFLM $ make -f tensorflow/lite/micro/tools/make/Makefile clean $ make -f tensorflow/lite/micro/tools/make/Makefile TARGETxtensa OPTIMIZED_KERNEL_DIRxtensa TARGETxtensa TARGET_ARCHhifi5 test_pytorch_to_tflite_test -j其中XTENSA_CORE、XTENSA_TOOLS_VERSION等环境变量需要与本地安装的 Xtensa 工具链版本对应该命令同时会使用 tensorflow/lite/micro/kernels/xtensa 下的 HiFi5 优化内核。从测试结构看pytorch_to_tflite_test专用于验证PyTorch 训练 → TFLite 量化转换 → TFLM 端到端推理这条完整链路标签258的输出也与两个转换 Notebook 的验证结果相互印证。总结与注意事项本文完整复现了 README 中介绍的两条 PyTorch → TFLite(int8) 转换路径TinyNN 路径~3 分钟model_tracer追踪 →PostQuantizer后训练量化 → 100 张图片校准 →torch.quantization.convert→ TinyNNTFLiteConverter直接产出 int8 模型链路最短、依赖最少ONNX 路径~5 分钟torch.onnx.export导出并校验 →onnx-tf转 SavedModel → float32 TFLite 验证 → 代表数据集 TFLITE_BUILTINS_INT8全整数量化链路标准、便于对接更多中间工具。实操中需要注意以下几点量化必须配套校准数据两条路径都依赖真实图片统计激活动态范围校准集应与部署场景分布接近预处理与输入格式要对齐ImageNet 风格预处理Resize(256)CenterCrop(224)Normalize与输入量化scale/zero_point→quantize_per_tensor→int_repr必须与转换时一致否则推理结果会明显退化输出类型选择嵌入式端TFLM通常偏好输入输出均为int8的全整数量化模型路径二通过inference_input_type/inference_output_type显式指定算子兼容性量化转换要求模型中所有算子都能被 TFLite int8 内建算子覆盖TFLITE_BUILTINS_INT8会在遇到不支持的算子时直接报错部署验证闭环转换完成后应像仓库 pytorch_to_tflite_test.cc 一样在目标平台如 Xtensa HiFi5上跑真实输入并比对预测标签确认端到端精度无损。赞分享人工智能深度学习推理引擎本地部署嵌入式物联网【免费下载链接】tflite-microInfrastructure to enable deployment of ML models to low-power resource-constrained embedded targets (including microcontrollers and digital signal processors).项目地址https://gitcode.com/gh_mirrors/tf/tflite-micro点击查看免费下载相关推荐tflite-micro Xtensa 平台部署实战PyTorch MobileNetV2 转 int8 TFLite 并在 HiFi5 DSP 上运行tflite micro Xtensa 平台部署实战PyTorch MobileNetV2 转 int8 TFLite 并在 HiFi5 DSP 上运行 本指人工智能深度学习推理引擎本地部署嵌入式物联网OpenChatKit移动端部署ONNX转换与TensorFlow Lite模型优化指南OpenChatKit移动端部署ONNX转换与TensorFlow Lite模型优化指南 引言移动端大模型部署的挑战与解决方案 你是否还在为OpenChat人工智能大模型NLP模型训练模型推理服务Qwen3-30B-A3B移动端部署ONNX转换与TFLite模型优化指南Qwen3 30B A3B移动端部署ONNX转换与TFLite模型优化指南 引言移动端大模型部署的痛点与解决方案 你是否还在为将300亿参数的Qwen3 3大模型基础模型人工智能上一篇Qwopus3.5-9B-Coder-GGUF代码调试技巧快速发现和修复复杂Bug的7个方法下一篇Mac Mouse Fix 完整上手指南3 步配置让低价鼠标拥有平滑滚动、侧键自定义与触控板手势创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考