前言

本文没有使用文件系统,以最小RTOS为例来调用Tensor Flow TFLite模型

Tensor FLow TFLite的工作流程就是先训练好模型,然后转换为TFLite模型文件,最后在通过Tensor Flow Tflite加载调用

相关知识

​​​​​​什么是Tensor Flow和lite以及数据流图_17岁boy的博客-CSDN博客

神经网络全连接层详解_17岁boy的博客-CSDN博客

Tensor Flow V2:基于Tensor Flow Keras的摄氏度到华氏度温度转换的训练模型_17岁boy的博客-CSDN博客
​​​​​​Tensor Flow V2:将Tensor Flow H5模型文件转换为tflite_17岁boy的博客-CSDN博客

​​​​​​Tensor Flow Lite C++ API 介绍_17岁boy的博客-CSDN博客

TinyML与Tensor Flow Lite的关系_17岁boy的博客-CSDN博客

TFLite模型文件转C语言文件_17岁boy的博客-CSDN博客

Zephry对Tensor Flow Lite的支持

Zephry2.6已经内置了Tensor Flow Lite与TinyML源代码,我们不需要去进行移植,并且提供了两个基于示例代码:hello_world以及magic_wand

示例路径存在于:samples/modules/tensorflow

开始实战

开启Tensor Flow Lite/TinyML支持、以及使用C++编译器,Tensor Flow Lite提供的是C++接口必须使用C++编译器

CONFIG_TENSORFLOW_LITE_MICRO=y    //TinyML
CONFIG_NEWLIB_LIBC=y    //cLib
CONFIG_CPLUSPLUS=y //c++
CONFIG_LIB_CPLUSPLUS=y    //c++lib

包含基本头文件

需要注意你的源文件必须是.cc结尾,如果是.c结尾的Zephry构建工具会调用GCC编译那么不会包含c++的库文件会导致缺失头文件,其次记得在你的model文件中加上#pragma pack(1),让内存以1字节对齐,防止出现偏移对齐的问题导致数值不对

//一个允许解释器加载模型使用的操作的类
#include <tensorflow/lite/micro/all_ops_resolver.h>
//可以记录错误并输出以帮助调试的类
#include <tensorflow/lite/micro/micro_error_reporter.h>
//TensorFlow Lite for Microcontrollers 解释器,模型将在解释器中运行
#include <tensorflow/lite/micro/micro_interpreter.h>
//定义 TensorFlow Lite FlatBuffer 数据结构的模型,用于理解 sine_model_data.h 中的模型数据
#include <tensorflow/lite/schema/schema_generated.h>
//用于获取当前tensor flow版本与模型版本
#include <tensorflow/lite/version.h>
//我们生成的model文件
#include "model.h"
//zephyr 核心文件
#include <zephyr.h>
#include <sys/printk.h>

创建log工具

//set up logging
tflite::MicroErrorReporter micro_error_reporter;
tflite::ErrorReporter* error_reporter = &micro_error_reporter;

这一段代码详细讲解一下,可以跳过,这一条关于C++中多态的运用

大家看到首先定义了MicroErrorReporter类,然后又定义了ErrorReporter指针指向MicroErrorReporter类型的变量,这是为何?

ErrorReporter是Tensor Flow Lite下的Log调试模块,而MicroErrorReporter是基于ErrorReporter的派生类,它内部重载实现了父类里的调试输出日志的虚函数,使用的代码比ErrorReporter更低功耗,这里用父类指针指向子类的用意在于限制逻辑业务以及增加灵活性,因为派生类里可能有一些与业务不相关的代码与成员变量,当子类派生父类时每次构造都有一个父类的副本,如果这个父类有虚函数的情况下还会有虚函数表指针指向当前全局唯一需虚函数表,当父类指针调用方法时会如果不是虚函数则调用父类副本里的代码,如果是虚函数则从虚函数指针找到属于自己的虚表,然后在虚函数表中找到对应的函数地址然后去调用

这样做还有一个灵活性的好处,就是一些旧代码里类型可能是ErrorReporter,如果你传递MicroErrorReporter进去会报类型不一致的错误,如果进行类型转换还会出现内存丢失可能出现段错误的问题,如果使用这个方法的话即不影响类型又能调用派生类的方法,还能兼容旧函数

获取模型并检查模型版本是否被当前Tensor支持

//getModel
const tflite::Model* model = tflite::GetModel(model_tflite);
//check version
if(model->version() != TFLITE_SCHEMA_VERSION){TF_LITE_REPORT_ERROR(error_reporter,"Version Mismatch %d != ",model->version(),TFLITE_SCHEMA_VERSION);return -1;
}

创建对模型操作的接口类

//create AllopsResolver
tflite::AllOpsResolver resolver;

为模型创建张量空间,主要用于存放在模型运行期间产生的输入输出以及中间变量

//create tensor space
const int tensor_arena_size = 2* 1024;
uint8_t tensor_arena[tensor_arena_size];

创建空间绑定类

//create build
tflite::MicroInterpreter interpreter(model,resolver,tensor_arena,tensor_arena_size,error_reporter);

为模型分配内存

//allocate memory for model
TfLiteStatus allocate_status = interpreter.AllocateTensors();
if(allocate_status != kTfLiteOk){TF_LITE_REPORT_ERROR(error_reporter,"allocate momory error");return -2;
}

获取输入输出源,这里的源索引跟你的模型有关,之前一篇文章训练keras模型时调用了:tf.keras.layers.Dense(units=1,input_shape=[1])这个API,其中units就是输出维度,意味着有多少个神经网络,我们给的是1所以只有一个神经网络,需要注意输入与输出要选择对应的下标,因为是C++语言所以下标从0开始计算。

//get input and output index 0
TfLiteTensor* input  = interpreter.input(0);
TfLiteTensor* output = interpreter.output(0);

输入值

//input
input->data.f[0] = static_cast < float >(50);

运行解释器

//run
TfLiteStatus invoke_status = interpreter.Invoke();
if(invoke_status != kTfLiteOk){TF_LITE_REPORT_ERROR(error_reporter,"run error");return -3;
}

获取输出并打印

//output
float f_output = output->data.f[0];
printk("output:%d\n",static_cast < int >(f_output));

需要注意我这里使用了static_cast做转换,因为我的处理器没有浮点数运算的FPU,Zephyr没有支持,所以用C++的类型转换可以对浮点数与整数进行转换,C++自己实现了针对浮点数操作的API函数

输出结果:

output:121

输出的是华氏度,摄氏度是50,华氏度是122,相差不大,说明我们训练的还可以,这个模型只训练了1000次

完整代码

//一个允许解释器加载模型使用的操作的类
#include <tensorflow/lite/micro/all_ops_resolver.h>
//可以记录错误并输出以帮助调试的类
#include <tensorflow/lite/micro/micro_error_reporter.h>
//TensorFlow Lite for Microcontrollers 解释器,模型将在解释器中运行
#include <tensorflow/lite/micro/micro_interpreter.h>
//定义 TensorFlow Lite FlatBuffer 数据结构的模型,用于理解 sine_model_data.h 中的模型数据
#include <tensorflow/lite/schema/schema_generated.h>
//用于获取当前tensor flow版本与模型版本
#include <tensorflow/lite/version.h>
//我们生成的model文件
#include "model.h"
//zephyr 核心文件
#include <zephyr.h>
#include <sys/printk.h>int main(){printk("********** Tensor Flow Lite Test **********\n");//set up loggingtflite::MicroErrorReporter micro_error_reporter;tflite::ErrorReporter* error_reporter = &micro_error_reporter;//getModelconst tflite::Model* model = tflite::GetModel(model_tflite);//check versionif(model->version() != TFLITE_SCHEMA_VERSION){TF_LITE_REPORT_ERROR(error_reporter,"Version Mismatch %d != ",model->version(),TFLITE_SCHEMA_VERSION);return -1;}//create AllopsResolvertflite::AllOpsResolver resolver;//create tensor spaceconst int tensor_arena_size = 2* 1024;uint8_t tensor_arena[tensor_arena_size];//create buildtflite::MicroInterpreter interpreter(model,resolver,tensor_arena,tensor_arena_size,error_reporter);//allocate memory for modelTfLiteStatus allocate_status = interpreter.AllocateTensors();if(allocate_status != kTfLiteOk){TF_LITE_REPORT_ERROR(error_reporter,"allocate momory error");return -2;}//get input and output index 0TfLiteTensor* input  = interpreter.input(0);TfLiteTensor* output = interpreter.output(0);//inputinput->data.f[0] = static_cast < float >(50);//runTfLiteStatus invoke_status = interpreter.Invoke();if(invoke_status != kTfLiteOk){TF_LITE_REPORT_ERROR(error_reporter,"run error");return -3;}//outputfloat f_output = output->data.f[0];printk("output:%d\n",static_cast < int >(f_output));return 0;}

基于Stm32F746g_disg平台下移植zephry使用TinyML预测模型相关推荐

  1. 1013.windows平台下移植qtmqtt三方库

    windows平台下移植Qt版本qtmqtt 1 下载qtmqtt源码 git clone https://github.com/qt/qtmqtt 2 安装perl软件 http://strawbe ...

  2. linux网卡握手速率模式,一种基于Linux平台下的网卡速率和双工模式测试的方法与流程...

    本发明涉及计算机技术领域,更具体的说是涉及一种基于Linux平台下的网卡速率和双工模式测试的方法. 背景技术: 随着社会经济的发展和互联网技术的进步,如今把计算机网络使得我们的生活变得更加方便,快捷. ...

  3. 不同平台下移植x264

    一.   编译环境 mips移植x264相关记录,mips交叉编译工具采用buildroot-gcc342版本,x264 版本x264-snapshot-20140831-2245. android ...

  4. 基于.net平台下大型分布式HIS系统之药房药库系统-石曼迪-专题视频课程

    基于.net平台下大型分布式HIS系统之药房药库系统-159人已学习 课程介绍         本次课程重点讲解药房药库系统中典型的几个环节,如:入库.入库审核.盘点.盘点审核.药房划价.门诊发药.住 ...

  5. 基于MacOSX平台下的二维码扫码功能

    基于MacOSX平台下的二维码扫码功能 最近项目接受了一个需求,要在macOS的系统上实现一个二维码扫码的功能.通过多方面的学习,最终实现了要求,具体的实现步骤将会在下面展示. 核心功能模块 实现途径 ...

  6. linux 2440网卡驱动,Linux-2.6.30平台下移植DM9000网卡驱动到TQ2440

    平台:虚拟机Ubuntu 12.04  内核:linux-2.6.30 开发板:TQ2440 包括编译内核.制作文件系统,到目前可以在虚拟机上可以通过交叉网线可以和开发板互通,用了弄了差不多快两天时间 ...

  7. linux-2.6.30平台下移植DM9000网卡驱动到TQ2440

    平台:虚拟机ubuntu12.04  内核:linux-2.6.30 开发板:TQ2440 包括编译内核.制作文件系统,到目前可以在虚拟机上可以通过交叉网线可以和开发板互通,用了弄了差不多快两天时间吧 ...

  8. 基于Android平台下的科学计算器

    作者:hinsxu,时间:2011-8-12 大概在半年前应公司的需要学习了android的相关方面的内容,以便后续在做GPL33000(A8内核架构)技术Support/Project打下基础.在w ...

  9. 基于C#平台下利用POP3和SMTP协议的邮件归档系统

    今天对电脑进行整理,发现电脑上有一个帮同学做的毕设代码,挺简单的,但是当成做的时候吃了不少苦头,现在都毕业了,就放上来给新手分享一下.好了话不多说. 首先了解一下POP3和SMTP协议,他们是两个网络 ...

最新文章

  1. Keras入门(一)搭建深度神经网络(DNN)解决多分类问题
  2. python编程语言基础
  3. seaborn常用的10种数据分析图表
  4. 数据库开发——MySQL——简单介绍和安装
  5. 1066. [SCOI2007]蜥蜴【最大流】
  6. QT事件过滤器eventFilter函数
  7. 解析内、外职业发展规划秘诀
  8. 【BZOJ4554】游戏(二分图匹配,网络流)
  9. [转]Windows Shell 编程 第五章 【来源:http://blog.csdn.net/wangqiulin123456/article/details/7987939】...
  10. 转:高级PHP应用程序漏洞审核技术
  11. “最强大脑”蒋昌建站台,原来是为这群白帽黑客和少年极客
  12. 屏蔽电脑上所有的广告推送(亲测可用)
  13. MMS流媒体下载原理
  14. 数据库:一对一,一对多,多对多
  15. IdentityServer Checking for expected scope openid failed
  16. Laravel 数据库去重计数
  17. 学生信息管理系统目标和范围说明书
  18. Behavior Designer 干货总结
  19. 关于Unity中更新到HDRP会导致材质变粉色的问题
  20. 基于海康SDK开发文档分析+云台控制实现+经典案例

热门文章

  1. html if语句多条件,nginx if多条件判断的实现
  2. Tcl Tutorial 笔记10 · list
  3. cesium +vue项目怎么运行
  4. linux不同机器之间的拷贝,Linux下不同机器之间的文件拷贝
  5. python基础入门笔记_Python基础入门笔记:函数
  6. micro framework php,index.php
  7. idea中ssm集成freemark_基于SSM框架的迷你天猫商城
  8. Linux下 mysql5.7的彻底卸载
  9. mysql的部分数据主从复制_MySQL主从复制数据不一致的办法部分原因
  10. python 中定义的函数 如何在main中调用_在python中,在定义类时自动运行函数的方法?_class_酷徒编程知识库...