使用S32DS部署Tensorflow lite到S32K3

一、概述

1、本文主要介绍如何用S32DS在NXP S32K344 中部署Tensorflow;

2、示例使用了Tensorflow入门代码,主要功能是识别28 * 28 的手写图片的数字;

3、在MCU上开启DSP功能后,最终运行时间在 7ms(64神经元),准确率在 90%左右;

4、Tensorflow Lite Micro为嵌入式环境运行的设计,参考以下链接:

开始使用 TensorFlow Lite

二、资源需求

1、库文件

库文件资源地址说明
CMSIS 6Release CMSIS 6.1.0 · ARM-software/CMSIS_6 · GitHubARM提供,会使用部分头文件
CMSIS-NNhttps://codeload.github.com/ARM-software/CMSIS-NN/zip/refs/heads/mainARM提供ARM Cortex-M 系列微控制器设计的神经网络库
CMSIS-DSPRTE_Components.h在micro_time.cpp中调用,可手动修改
https://github.com/ARM-software/CMSIS-DSP/tree/main
ARM提供,DSP运算库
tensorflow-lite-microhttps://codeload.github.com/tensorflow/tflite-micro/zip/refs/heads/mainGoogle tensorflowlite基础版,同宗永好,可以借点东西
tensorflow-lite-microhttps://www.keil.arm.com/packs/tensorflow-lite-micro-tensorflow/versions/

ARM提供的tensorflowlite ARM版,我们用这个,直接解压缩使用

Flatbuffershttps://github.com/google/flatbuffers/tree/master
Gemmlowp头文件低精度计算
https://github.com/google/gemmlowp/tree/master
Ruyinstrumentation.h 需要Ruy中提供,矩阵计算
https://github.com/google/ruy

2、软件工具

工具描述
S32DS3.4版本,GCC 10.2编译
Python3.7版本
VS Code + copilot可选,测试程序由AI帮忙生成,再手动修改
豆包遇到不会的问问他吧,比自己查资料快多了
Tensorflow2.x 机器学习模型构建
Netron可选,打开tflite文件
Trace32和 Lauterbach.rc可选,Python操作trace32,更新输入数据(原始数据28*28很大)

三、模型制作

1、机器学习模型

参考 关于TensorFlow | TensorFlow中文官网

import tensorflow as tf
import oscurr_path = os.path.dirname(__file__)
model_path = os.path.join(curr_path, 'model.tflite')mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
first_index_data = x_train[0]# 128 = 12ms
# 64 = 7ms
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(input_shape=(28, 28)),tf.keras.layers.Dense(64, activation='relu'),tf.keras.layers.Dropout(0.2),tf.keras.layers.Dense(10, activation='softmax')
])model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)# 计算需要的缓存大小,main.cc 会设置
total_memory = 0
for layer in model.layers:for tensor in layer.weights:shape = tensor.shapeelement_size = tensor.dtype.sizetensor_memory = 1for dim in shape:if dim is not None:tensor_memory *= dimtensor_memory *= element_sizetotal_memory += tensor_memory
print(f"Estimated memory usage: {total_memory} bytes")# 转换模型
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()# 保存转换后的模型
with open(model_path, 'wb') as f:f.write(tflite_model)

2、转换模型

缓存区大小和转换成TFlite 模型由AI生成。

converter = tf.lite.TFLiteConverter.from_keras_model(model)

tflite_model = converter.convert()

3、量化

生成模型数组,在嵌入式软件中调用。下列脚本保存到model.cc中。

第一种方法

Convert.py 实现,该脚本由豆包生成

import numpy as np
import tensorflow as tf
import oscurr_path = os.path.dirname(__file__)
model_path = os.path.join(curr_path, 'model.tflite')
output_path = os.path.join(curr_path, 'model.cc')def convert_tflite_to_c_array(tflite_model_path, output_c_file_path):# Load the TFLite modelwith open(tflite_model_path, 'rb') as f:tflite_model = f.read()# Convert the model to a numpy arraymodel_array = np.frombuffer(tflite_model, dtype=np.uint8)# Create the C array as a stringc_array_str = "const unsigned char model_data[] = {\n"c_array_str += ',\n'.join('    ' + ', '.join(f'0x{byte:02x}' for byte in model_array[i:i+12]) for i in range(0, len(model_array), 12))c_array_str += "\n};\n"c_array_str += f"const unsigned int model_len = {len(model_array)};\n"# Write the C array to the output filewith open(output_c_file_path, 'w') as f:f.write(c_array_str)# Example usage
convert_tflite_to_c_array(model_path, output_path)
print(f"Model converted to C array and saved to {output_path}")

第二种方法

许多微控制器平台没有本地文件系统的支持。从程序中使用一个模型最简单的方式是将其以一个 C 数组的形式包含并编译进你的程序。

xxd是个工具(linux/Cygwin/git等中包含)

四、嵌入式软件

1、库创建

使用tensorflow-lite-micro为基础,创建库工程(C++)。可直接使用编译号的库

已编译的库地址下载(使用以下内容,可跳过“库创建”)

【免费】S32DS编译的S32K3tensorflowlite库,o3优化,DSP开启资源-CSDN文库

A、需要的头都放进去,安装Tensorflow引用的头路径方式

使用DSP编译选项的设置,设置方式参考下一章;S32K3支持该协处理器。

B、可能的问题

库路径配置,记得是 C++

ethosu是平台的, AI推理,可以删除

schema_generated.h 屏蔽版本检查

///static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&

///              FLATBUFFERS_VERSION_MINOR == 5 &&

///              FLATBUFFERS_VERSION_REVISION == 26,

///             "Non-compatible flatbuffers version included");

blocking_counter.h error: 'condition_variable' in namespace 'std' does not name a type,直接屏蔽代码(这个是多线程系统时才有操作实体)

array.h 从tflite-micro-main拷到ARM下载的中,而不是#include "flatbuffers/array.h",

arm_nnfunctions.h  在CMSIS-NN中

instrumentation.h 需要Ruy中提供,矩阵计算

FixPonit 头文件 Gemmlowp 低精度计算

C、重定义问题解决

右击工程“Build configurations Explorer”,这几个文件在其他文件已经“include”了

D、库引用设置(在测试程序中配置)

路径设置:

2、测试程序

创建工程(C++)

Main.c 代码

/** main implementation: use this 'C++' sample to create your own application**/
#include "S32K344.h"
#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/micro/tflite_bridge/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"// 包含模型数据
#include "model.cc"
#include "input_data.cc"volatile int predicted_class_index = 0;
float input_data[28 * 28];
volatile bool test_run = false;
const int tensor_arena_size = 40 * 1024;
uint8_t tensor_arena[tensor_arena_size];int main() 
{// 定义错误报告器tflite::MicroErrorReporter micro_error_reporter;tflite::ErrorReporter* error_reporter = &micro_error_reporter;// 定义操作解析器tflite::MicroMutableOpResolver<10> resolver;resolver.AddAdd();resolver.AddMul();resolver.AddSub();resolver.AddDiv();resolver.AddReshape();resolver.AddFullyConnected();resolver.AddSoftmax();resolver.AddRelu();// 定义模型const tflite::Model* tfmodel = tflite::GetModel(model_data);if (tfmodel == nullptr) {TF_LITE_REPORT_ERROR(error_reporter, "Failed to build tfmodel from buffer");while (1);}// 定义解释器tflite::MicroInterpreter interpreter = tflite::MicroInterpreter(tfmodel, resolver, tensor_arena, tensor_arena_size);// 分配张量TfLiteStatus allocate_status = interpreter.AllocateTensors();if (allocate_status != kTfLiteOk) {TF_LITE_REPORT_ERROR(error_reporter, "Tensor allocation failed");while (1);}// 初始化第一个输入张量for (int i = 0; i < 28 * 28; ++i) {input_data[i] = x_train[i];}// 准备输入数据TfLiteTensor* input_tensor = interpreter.input(0);for (;;) {// 填充输入数据for (int i = 0; i < 28 * 28; ++i) {input_tensor->data.f[i] = input_data[i];}// 运行推理TfLiteStatus invoke_status = interpreter.Invoke();if (invoke_status != kTfLiteOk) {TF_LITE_REPORT_ERROR(error_reporter, "Invoke failed");while (1);}// 获取输出结果TfLiteTensor* output_tensor = interpreter.output(0);// 处理输出数据:找到概率最大的类别索引int num_classes = output_tensor->bytes / sizeof(float);float max_prob = output_tensor->data.f[0];for (int i = 1; i < num_classes; ++i) {if (output_tensor->data.f[i] > max_prob) {max_prob = output_tensor->data.f[i];predicted_class_index = i;}}test_run = false;while(!test_run);}return 0;
}

解释器

MicroInterpreter为该示例的解释器,另外一个不使用

增加操作

resolver.AddRelu();根据Netron图中的操作或HelloAi中模型层确定

设置缓存区

uint8_t tensor_arena[tensor_arena_size];

tensor_arena_size根据Hellow.py  中的 total_memory

3、性能测试

输入 28 * 28 个数据,输出 10 个数据;该结果通过TRACE32读取。

隐藏层神经元个数48MHz

48MHz

O3优化

DSP使用

160MHz

O3优化

DSP使用

128560ms32ms12ms
64//7ms

使用DSP编译选项的设置

五、模型预测的正确率测试

1、测试脚本(先加载训练数据,再传给TRACE32)

import lauterbach.trace32.rcl as t32rc
import tensorflow as tf
import timeif __name__ == "__main__":mnist = tf.keras.datasets.mnist(x_train, y_train),(x_test, y_test) = mnist.load_data()x_train = x_train / 255.0t32debug = t32rc.connect(node = "localhost",port = 20000,packlen = 1024)right_cnt = 0calcu_cnt = 0# input data updatei = 0for x in x_train:calcu_cnt += 1input_datas = x.flatten()varDict = {}j = 0input_checksum = 0readback_checksum = 0for input_data in input_datas:signalName = 'input_data[' + str(j) + ']' # 构建信号名input_data = float(input_data)input_checksum += input_dataj += 1t32debug.variable.write(signalName, input_data)#time.sleep(0.001)readback_checksum += t32debug.variable.read(signalName).value#t32debug.go()# model predict in mircrocontroller, wait finsht32debug.variable.write('test_run', 1)while t32debug.variable.read('test_run').value != 0:time.sleep(0.1)#0.1s#t32debug.trace32_break()# read output dataout_signalname = 'predicted_class_index'predicted_class = t32debug.variable.read(out_signalname).valueif  predicted_class == y_train[i]:right_cnt += 1else:print("predict error!", 'input checksum: ', input_checksum, 'readback checksum', readback_checksum)print(right_cnt, '/', calcu_cnt, ' [predicted class]:', predicted_class, '[real class]:', y_train[i])i += 1print('Accuracy: ', right_cnt / calcu_cnt)print('Total number of test data: ', calcu_cnt)

2、加载训练数据

获取结果与实际进行对比。

3、TRACE32需要使能Port

4、TRACE32增加交互的数据

5、执行测试

运行可能不是太快

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

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

相关文章

【OMCI实践】ONT上线过程的omci消息(五)

引言 在前四篇文章中&#xff0c;主要介绍了ONT上线过程的OMCI交互的第一、二、三个阶段omci消息&#xff0c;本篇介绍第四个阶段&#xff0c;OLT下发配置到ONT。前三个阶段&#xff0c;每个厂商OLT和ONT都遵循相同标准&#xff0c;OMCI的交换过程大同小异。但第四个阶段&…

vue3: directive自定义指令防止重复点击

第一章 前言 相信很多小伙伴会在各个渠道上搜如何防止重复点击&#xff0c;之后会推荐什么防抖、节流来避免这一操作&#xff0c;该方法小编就不继续往下说了。接下来说说小编的场景&#xff0c;项目已经完成的差不多了&#xff0c;但是由于之前大家都是直接点击事件调用方法的…

危化品经营单位安全管理人员的职责及注意事项

危化品经营单位安全管理人员肩负着保障经营活动安全的重要责任&#xff0c;以下是其主要职责及注意事项&#xff1a; 职责 1. 安全制度建设与执行&#xff1a;负责组织制定本单位安全生产规章制度、操作规程和生产安全事故应急救援预案&#xff0c;确保这些制度符合国家相关法…

解决VMware 安装 Ubuntu 后无法全屏的问题

根据以往的经验&#xff0c;一直想安装 VMware-tools&#xff0c;但是看了官方介绍才突然发现早就已经有更好的替代品了。 官方介绍连接在此&#xff1a;Install VMware Tools in VMware products 如上图所述&#xff0c;早期的 Linux 系统推荐安装 VMware-tools&#xff0c;但…

C++ 继承,多态

看前须知&#xff1a; 本篇博客是作者听课时的笔记&#xff0c;不喜勿喷&#xff0c;若有疑问可以评论区一起讨论。 继承 定义&#xff1a; 继承机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段&#xff0c;它允许我们在保持原有 类特性的基础上进⾏扩展&#xff0c;增…

【C++】list 链表的使用+模拟实现

目录 文章目录 前言 一、list的简介 二、list的使用方法 三、list的模拟实现 1.基本框架&#xff1a; 2.迭代器实现 3.常用接口实现 四、完整代码 总结 前言 本文主要介绍C【STL】容器中的 list&#xff0c;包括接口说明和模拟实现。其中讲解了迭代器功能上的分类&am…

2. EXCEL中函数和公式《AI赋能Excel》

欢迎来到滔滔讲AI。今天我们来学习和讨论下函数和公式是什么&#xff0c;以及它们之间的区别。 点击图片查看视频 2、AI赋能EXCEL-函数和公式 一、什么是函数 首先&#xff0c;我们来了解一下函数。函数是Excel中预定义的计算工具&#xff0c;能够帮助我们快速进行各种计算。 …

基于AT89C51单片机的教室智能照明控制系统

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/90419908?spm1001.2014.3001.5501 C16 部分参考设计如下&#xff1a; 摘 要 本项目的智能教室灯光控制系统通过合理的软硬件设计&#xff0c;有效地提升了教室…

商业化运作的“日记”

晴&#xff0c;2025年2月24日 看到这张图&#xff1a; 将其放大&#xff1a; 建立表格&#xff1a; 原话翻译一些点市场中的万物现出本相&#xff0c;无非世人的需求有需求才有市场商品交换需求交换⇆孕育平台产品价值功能价值情绪价值资产价值解决实际问题 情感经济价值/增…

Matlab R2024B软件安装教程

一、新版本特点 MATLAB R2024B版本带来了众多新特性和改进&#xff0c;旨在提升用户的内容创作体验和工程效率。以下是该版本的一些主要特点&#xff1a; 1. 性能提升和优化&#xff1a;R2024B版本在性能上进行了显著优化&#xff0c;无论是在提问、回答问题、发布新技巧还是…

本地部署AI模型 --- DeepSeek(二)---更新中

目录 FAQ 1.Failed to load the model Exit code: 18446744072635812000 FAQ 1.Failed to load the model Exit code: 18446744072635812000 问题描述&#xff1a; &#x1f972; Failed to load the model Error loading model. (Exit code: 18446744072635812000). Unkn…

项目一 - 任务3:搭建Java集成开发环境IntelliJ IDEA

本次实战任务通过搭建 Java 集成开发环境 IntelliJ IDEA&#xff0c;深入体验了 Java 开发的全流程。从安装 IntelliJ IDEA 到配置开发环境&#xff0c;再到创建 Java 项目、包和类&#xff0c;每一步都为后续开发奠定了基础。通过编写简单的 Java 程序&#xff0c;如 Welcome …

【uni-app】对齐胶囊容器组件

代码碎片 <template><div><view :style"{ height: ${statusBarHeight}px }"></view><viewclass"":style"{height: ${menuButtonHeight menuButtonPadding * 2}px,width: ${menuButtonInfo.left}px,}"><slot …

OpenCV(8):图像直方图

在图像处理中&#xff0c;直方图是一种非常重要的工具&#xff0c;它可以帮助我们了解图像的像素分布情况。通过分析图像的直方图&#xff0c;我们可以进行图像增强、对比度调整、图像分割等操作。 1 什么是图像直方图&#xff1f; 图像直方图是图像像素强度分布的图形表示&am…

攻防世界 Reversing-x64Elf-100

进入题目&#xff0c;先下载附件 将下载好的RE文件拖入ExeinfoPE查看&#xff0c;有无壳 “Diagnose” 一栏的信息 “NOT WIN EXE -o - ELF executable [64bit obj. Exe file - CPU: AMD x86” 可知&#xff0c;这是一个 ELF 格式的可执行文件&#xff08;通常用于 Linux 系统…

【C】堆的应用1 -- 堆排序

之前学习了堆&#xff0c;堆的一棵以顺序结构存储的完全二叉树&#xff0c;堆本身又氛围大根堆和小根堆&#xff0c;假设以大根堆为例&#xff0c;由于堆顶部元素是一棵二叉树里面最大的元素&#xff0c;所以如果每次都取堆顶的元素&#xff0c;那么取出的元素就是一个降序排列…

CentOS 7配置YOLOv8环境指南:无显卡版教程 - 幽络源

看本篇教程前请确保Centos7系统已安装配置Python3环境&#xff0c;参考幽络源上一篇文章>CentOS 7安装Python3环境详细指南&#xff1a;从源码编译到PIP配置 步骤1&#xff1a;建立python虚拟环境项目 在home目录下执行如下命令新建虚拟环境python项目 python3 -m venv y…

Confluence知识库管理系统安装步骤(Windows版本)

我们介绍的是安装7.15.1以下版本的安装方式,8.0以上的安装方式暂不支持。 如果你要安装8.0以上的版本,请参考本文末尾的附录中提供的相关网址。 首先我们安装之前需要准备安装所需文件以上文件可以在这里下载:【https://download.csdn.net/download/Elegant_Kevin/90412040】…

Uniapp 开发中遇到的坑与注意事项:全面指南

文章目录 1. 引言Uniapp 简介开发中的常见问题本文的目标与结构 2. 环境配置与项目初始化环境配置问题解决方案 项目初始化注意事项解决方案 常见错误与解决方案 3. 页面与组件开发页面生命周期注意事项示例代码 组件通信与复用注意事项示例代码 样式与布局问题注意事项示例代码…

学习笔记--电磁兼容性EMC

一、基本概念 电磁兼容性&#xff08;Electromagnetic Compatibility&#xff0c;EMC&#xff09;是电子电气设备在特定电磁环境中正常工作的能力&#xff0c;同时不会对其他设备产生不可接受的电磁干扰。其核心目标是确保设备在共享的电磁环境中既能抵抗干扰&#xff0c;又能避…