解决由于历史原因解析tflite失败的问题

文章目录

  • 0. 背景
  • 1. tflite 历史遗留问题
  • 2. schema
  • 3. flatbuffers 编译器
    • 3.1 安装 FlatBuffers 编译器
    • 3.2. 编译 FlatBuffers schema 文件
    • 3.3 使用生成的 Python 文件
  • 4 问题未解决
  • 终极解决方案

写在最前面:解决方法是升级tensorflow版本,重新生成tflite

0. 背景

今天遇到了这么一个问题:

  File "***/scripts/tflite/schema.py", line 9366, in Tensorsx = self._tab.Indirect(x)File "***/anaconda3/lib/python3.8/site-packages/flatbuffers/table.py", line 46, in Indirectreturn off + encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)File "***/anaconda3/lib/python3.8/site-packages/flatbuffers/encode.py", line 26, in Getreturn packer_type.unpack_from(memoryview_type(buf), head)[0]
struct.error: unpack_from requires a buffer of at least 1574732 bytes for unpacking 4 bytes at offset 1574728 (actual buffer size is 853240)

我是在解析某个tflite模型的时候遇到这个问题的,而我在解析别的iflite文件的时候是正常的。
于是分析到是tensorflow的schema文件版本差异的问题,在此记录一下解决过程。

1. tflite 历史遗留问题

最开始的时候,tflite 认为 opcode 不会超过 256 个,所以使用了 u8 来存储。后来就超过了 256 个,改成 int 来存储。但是又不能直接改,所以搞了个巧妙的方式:如果 opcode 小于 256,那么还是用 u8 来存,但是大于 256 的就必须走新的 field 了。

不太好的一点就是,他们把老的那个 field 换了名字,而新的 field 直接用了原来的名字,导致直接调用原来的接口名字的函数在不适配他的逻辑的情况下生成的就是全 0 的东西。

这也就是为什么我解析这个 tflite 模型得到的算子全是 ADD 算子。

2. schema

schema.fbs 是一个 FlatBuffers schema 文件,它定义了数据结构。这个文件通常由你自己创建,以匹配你的特定需求。

对于TensorFlow,它们的 FlatBuffers schema 文件是公开的,可以从它们的源代码库中获取。

我在 https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/schema 找到了 schema.fbs 这个文件,将其下载下来。

在这里插入图片描述
同时在这里也可以看到schema之前是有很多版本的。

需要确保 schema.fbs 文件与正在使用的 TensorFlow Lite 版本匹配。如果 schema.fbs 文件与你的 TensorFlow Lite 版本不匹配,可能会遇到问题。

3. flatbuffers 编译器

要使用 FlatBuffers 在 Python 中生成 schema 文件,需要先安装 FlatBuffers 编译器。这个编译器可以将 FlatBuffers schema 文件编译成 Python 类或其他语言的类。

我是使用python,所以在这里记录python。

3.1 安装 FlatBuffers 编译器

在 FlatBuffers 的 GitHub 仓库下载预编译的二进制文件,或者从源代码编译。

使用以下命令从源代码编译 FlatBuffers:

git clone https://github.com/google/flatbuffers.git
cd flatbuffers
mkdir build
cd build
cmake ..
make flatc

编译完成后,FlatBuffers 编译器(flatc)将位于 flatbuffers 目录。

3.2. 编译 FlatBuffers schema 文件

假设你的 FlatBuffers schema 文件名为 schema.fbs,你可以使用以下命令编译它:

./flatc --python schema.fbs
这在当前目录生成一个名为 tflite 的文件夹。

或者,使用
./flatc -p --gen-onefile schema.fbs
得到文件schema_generated.py,这样子好管理版本,但是使代码变得难以管理和阅读,因为所有的代码都在一个文件中。schema.fbs 文件中定义了很多的表和结构,生成的 Python 代码会非常长。

我个人是喜欢用前者生成一个python文件,需要参考源码的时候去后者生成的文件夹里找源码看。

3.3 使用生成的 Python 文件

import schema# 读取 TFLite 模型文件。
with open('your_model.tflite', 'rb') as f:buf = f.read()# 使用 schema 模块解析模型。
model = schema.Model.GetRootAsModel(buf, 0)# 现在,你可以使用 model 对象来访问模型的各种属性。
# 例如,你可以获取模型中的操作符数量:
print(model.OperatorCodesLength())# 或者,你可以获取模型中的第一个操作符的类型:
op_code = model.OperatorCodes(0)
print(op_code.BuiltinCode())

4 问题未解决

我更换了其他版本的 schema.fbs 之后,问题还是没有解决。。。
看来不是schema的问题

需要在解析的时候做以下修改:

tfliteOpSet[tfliteOp->opcode_index]->builtin_code

改成

static_cast<tflite::BuiltinOperator>(tfliteOpSet[tfliteOp->opcode_index]->deprecated_builtin_code)

  • tfliteOpSet[tfliteOp->opcode_index]->builtin_code:这里使用的是builtin_code,这是TensorFlow Lite中内建操作的枚举值。这种方式是推荐的,因为builtin_code是最新的,包含了所有的TensorFlow Lite内建操作。

  • static_cast<tflite::BuiltinOperator>(tfliteOpSet[tfliteOp->opcode_index]->deprecated_builtin_code):这里使用的是 deprecated_builtin_code,这是在旧版本的TensorFlow Lite中使用的,现在已经被标记为弃用(deprecated)。static_cast<tflite::BuiltinOperator>是将 deprecated_builtin_code 转换为 BuiltinOperator 枚举类型。这种方式不推荐使用,因为 deprecated_builtin_code 可能不包含所有的TensorFlow Lite内建操作。

终极解决方案

升级tensorflow版本,重新生成tflite。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

web前端笔记+表单练习题+五彩导航栏练习题

web前端笔记 1-骨架快捷方式!enter<!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>骨架部分</titl…

基于单片机的指纹打卡机设计

摘要 在科学技术飞速发展的今天&#xff0c;社会对身份识别的要求越来越高&#xff0c;尤其是在企业管理的人员签到、工作考勤等活动中对身份识别的高效性和可靠性的需求更为迫切。而传统的个人身份识别手段&#xff0c;如钥匙、密码、IC卡等&#xff0c;由于具有可盗用、可伪…

vue3 reactive丢失响应式

问题 使用 reactive 构造响应式对象时&#xff0c;当对其进行重新赋值后&#xff0c;会导致原有变量失去响应式&#xff0c;页面不会发生联动更新 例如&#xff1a; 1、使用 reactive 定义一个响应式的对象变量 let data1 reactive({name: 小李,date: 2024-03-18,address: xx…

Spring炼气之路(炼气二层)

目录 一、bean的配置 1.1 bean的基础配置 1.2 bean的别名配置 1.3 bean的作用范围配置 二、bean的实例化 2.1 bean是如何创建创建的&#xff1f; 2.2 使用静态工厂实例化bean 2.3 使用实例工厂实例化bean 三、bean的生命周期 3.1 什么是bean的生命周期 3.2 bean的生…

工控机在机器人领域的应用丨工业一体机的应用

随着机器人技术的不断发展&#xff0c;机器人在制造、物流等领域得到了广泛应用。而工业控制计算机&#xff08;工控机&#xff09;作为机器人控制系统的核心设备&#xff0c;也在机器人领域发挥着越来越重要的作用。 机器人控制系统是机器人的核心部分&#xff0c;控制系统的…

C++的内存管理

目录 1. C/C内存分布 2. C语言中动态内存管理方式 3. C内存管理方式 3.1 new/delete操作内置类型 4. operator new与operator delete函数 4.1 连续开辟空间(尽力了解) 5. new和delete的实现原理 5.1 内置类型 5.2 自定义类型 6. 深入理解 6.1malloc/free和new/delete的区…

SAP CAP篇十五:写个ERP的会计系统吧,Part II

本文目录 本系列文章目标开发步骤数据库表设计初始数据初始数据&#xff1a;AccountCategories初始数据&#xff1a;AccountUsages初始数据&#xff1a;ChartOfAccounts初始数据&#xff1a;AccountSubjects Service 定义生成Fiori AppApp运行 本系列文章 SAP CAP篇一: 快速创…

适用于智能语音小家电的语音ic类型有哪些?

适用于智能语音小家电的语音ic类型有哪些&#xff1f; 1. 语音播放芯片&#xff1a;这种芯片主要用于实现语音提示和报警功能。例如&#xff0c;当按下某个按钮时&#xff0c;它可以发出语音提醒&#xff0c;或者在出现故障时发出报警声音。这种芯片的应用非常广泛&#xff0…

操作系统笔记之进程调用API中的getpid、fork、wait、exec补充

操作系统笔记之进程调用API中的getpid、fork、wait、exec补充 code review! —— 杭州 2024-03-17 夜 文章目录 操作系统笔记之进程调用API中的getpid、fork、wait、exec补充1.getpid()2.fork()3.wait()4.exec()5.通常&#xff0c;exec() 调用与 fork() 调用一起使用&#xff…

002_avoid_for_loop_in_Matlab避免使用for循环

避免使用for循环 在程序设计思想中&#xff0c;循环是一个很有力的工具。在循环中&#xff0c;计算机很轻松地重复执行相同的操作。循环是汇编之上的编程中最重要的概念之一。Matlab的循环有两个语言构造&#xff0c;一个是for循环&#xff0c;另一个是while循环。在Matlab中&…

JetBrains全家桶激活,分享 GoLand 2024 激活的方案

大家好&#xff0c;欢迎来到金榜探云手&#xff01; GoLand 公司简介 JetBrains 是一家专注于开发工具的软件公司&#xff0c;总部位于捷克。他们以提供强大的集成开发环境&#xff08;IDE&#xff09;而闻名&#xff0c;如 IntelliJ IDEA、PyCharm、和 GoLand等。这些工具被…

总结mac下解决matplotlib中文显示问题的几种方法

一、前言&#xff1a; 使⽤matplotlib画图时&#xff0c;由于matplotlib默认没有中⽂&#xff0c;显⽰中文时会出现空⽩⼩⽅块。 二、方法&#xff1a; 2.1 matplotlib中使用SimHei字体 1&#xff09;进入终端后查看matplotlib的字体路径&#xff1a; $ python >>&g…

Linux学习-进程

目录 进程基本概念 进程相关命令 进程的创建 进程的调度 进程相关函数接口 进程的消亡 实例&#xff1a;创建九个子进程 目录 进程基本概念 进程相关命令 进程的创建 进程的调度 进程相关函数接口 进程的消亡 实例&#xff1a;创建九个子进程 exec函数…

Python脚本:用py处理PDF的五大功能

一、代码 【第三方库】3个 【Py版本】3.9 【使用前提】关闭所有的word文档 import os from datetime import datetime from docx2pdf import convert from pdf2docx import parse from PyPDF2 import PdfMerger from PyPDF2 import PdfReader,PdfWriter#将文件夹中的所有Wo…

C++语言学习(二)—— C++语言的基本知识

目录 一、面向对象的三个核心概念 二、C语言中的I/O口 三、C语言中的数据类型​​​​​​​ 3.1 逻辑类型 3.2 引用类型 3.2.1 引用作为函数参数 3.2.2 引用作为函数返回值 3.2.3 引用作为类成员 3.3 类类型 四、 C语言中的内联函数 五、 函数重载 六、 带默认形参…

四、分布式锁之自定义分布式锁

1、基本原理和实现方式对比 分布式锁&#xff1a;满足分布式系统或集群模式下多个进程可见并且互斥的锁。分布式锁的核心思想就是多线程都使用同一把锁&#xff0c;实现程序串行执行。 分布式锁需要具备的条件&#xff1a; 特性含义可见性多个线程都能感知到变化互斥性分布…

数据库系统概论-第16章 数据仓库与联机分析处理技术

概念性的介绍&#xff0c;一略而过&#xff0c;不重要。 16.1 数据仓库技术 16.2 联机分析处理技术 16.3 数据挖掘技术 16.4 大数据时代的新型数据仓库 16.5 小结

G - Find a way

题目分析 1.双重bfs,遍历两个起点求最短路再计算总和即可 2.唯一的坑点在于对于一个KFC&#xff0c;两人中可能有一个到不了&#xff0c;所以还要对到不了的点距离做处理 #include <bits/stdc.h> using namespace std; using ll long long; const int N 220;struct pos…

Linux/Ubuntu/Debian从控制台启动程序隐藏终端窗口

如果你想从终端运行应用程序但隐藏终端窗口. 你可以这样做&#xff1a; 在后台运行&#xff1a; 你只需在命令末尾添加一个与号 (&) 即可在后台运行它。 例如&#xff1a; your_command &将 your_command 替换为你要运行的命令。 这将在后台启动该命令&#xff0c…

Three.js基础入门介绍——【毕业季】Three.js动态相册

前言 岁月匆匆&#xff0c;又是一年毕业季&#xff0c;这次做个动态相册展示图片&#xff0c;放些有意思的内容&#xff0c;一起回忆下校园生活吧。 预期效果 相册展示和点选切换&#xff0c;利用相机旋转和移动来实现一个点击切图平滑过渡的效果。 实现流程 基本流程 1、搭…