查看: 806|回复: 0

[分享] 一种基于MCU的神经网络模型在线更新方案之数据处理篇

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3298

    主题

    6545

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32003
    最后登录
    2024-4-9
    发表于 2022-7-29 14:50:50 | 显示全部楼层 |阅读模式
    一种基于MCU的神经网络模型在线更新方案之数据处理篇
    书接上文(点此查看前文),我们横向比较了在应用TFLm引擎进行模型文件导入时候,所使用的三种常用方式:
    ·SD卡存储结合文件系统,
    ·xxd小工具进行文件的十六进制转换
    ·以及使用汇编指令.incbin直接进行模型导入。

    可以说各有所长,但是,当我们需要频繁地进行模型的替换、更新时,麻烦就出现了。xxd和.incbin的形式都需要重新编译目标工程,并下载到板子中。
    当我们的程序体量较大时,即便不需要对全部工程进行编译(做到改啥编啥),但是,下载这一步,是无论如何不能跳过的,随着最终镜像大小的不同,所消耗的时间也会不同。而使用文件系统的方式,无形中增加了移植文件系统的工作量。

    设计思路

    为了克服这一问题,小编在上一篇的结尾提出了一个新的方案,直接把flash看作一大块空白存储区,并开辟一个固定区域存放模型文件。这样一来,我们只需要在程序中将模型的读取位置固定,无论模型是否更新,都能够读取最新的模型数据,进行后续处理。
    而且小编也特意强调建议大家直接使用Nor Flash来实现这一操作。
    以i.MX RT系列MCU为例说明这样做的优势。i.MX RT系列由于没有片上Flash芯片,都通过外扩Flash芯片存储代码。当我们将启动方式调整为XIP,即从flash启动时,芯片内部的BootROM会帮我们配置初始化好这个片上的Flash芯片,而由于Nor Flash的特性,支持随机的内存访问,也就是说,我们在程序内部,可以直接通过指针的形式进行访问,甚至可以直接调用memcpy函数进行数据的拷贝。
    比起集成文件系统的方式,可以说方便至极。不过,也不是说Nand Flash就不适合,只是处理起来会稍稍麻烦一点,由于不支持随机的读操作,就要先拷贝到RAM区域再进行操作。

    设计实现

    言归正传,为了方便进行数据的管理,我们需要设计一套简单的管理逻辑,说的专业一点就是为我们的数据添加一个帧头,当然,既然大道至简,数据打包格式大致就是如下格式(可能有些简陋啊,大家见谅):
    11.png
    当然为了能够在程序中使用,我们再定义一个对应的C语言形式来表达,这里要用到C语言中0长度数组的概念:
    1. struct {
    2.         uint32_t n, w, h , c;
    3.         uint8_t data[0];
    4. }
    复制代码
    这样一来,我们就具象化了我们所设计的那个简单的数据打包协议。

    下一步是如何将数据打包成我们要的样子,这里要借助于Python来编写一个简单的脚本处理,并假设最终会生成一个二进制文件,假设输入一个多维数组results,首先构建其帧头,默认维度不足4的数据,用1补齐,保证最终的帧头包含4个维度信息:
    1. def save_to_bin(bin_name, results):
    2.     shape = list(results[0].shape)
    3.     element_size = [1] * (3 - len(shape)) + shape
    4.     element_len = len(results)
    5.     # shape is [N, H, W, C]
    6.     bin_values = np.asarray([element_len] + element_size, dtype=np.uint32).tobytes()
    7.     bin_values += results.tobytes()
    8.     with open(bin_name, "wb") as f:
    9.         f.write(bin_values)
    10.         f.close()
    复制代码
    聊到这儿,可能有同学会问了,针对于tflite模型,我们往往只需要知道其首地址就好了,TFLm会处理那些长度信息,我还有必要构造帧头吗?这下给小编问的有点哑口无言。马上着手设计了第二种数据结构:
    12.png
    是的,针对于模型数据这一特殊的存在,可以设计出更加精简的表达格式,而且,我们知道tflite模型本身实际上已经是二进制文件的形式了,也就是说,可以直接拿过来使用,无需再做任何操作,直接烧写到固定地址即可。

    那我们上面所设计的数据结构就毫无用武之地了吗?当然不是!小编做这些当然都是有理由的啊。

    大家想一想,运行神经网络模型的时候,光有模型就可以了吗?当然不,我们还缺少输入啊!如果你是摄像头输入,请跳过这节。而如果是离线测试呢?需要大量加载静态图到内存中,是不是和之前我们的分析就类似了。

    每次更换测试数据,依旧需要重新下载链接,那么按照本文提供的方案,也为数据设置一块固定的区域,然后借助于上述save_to_bin代码,将数据打包成固定格式,是不是就可以在程序中利用那个结构体访问了呢?没错!小编早就设计好了。

    下期预告

    那么至此,小编就给大家介绍了数据的组织结果,以及如何编写PC端工具对数据进行打包处理,以变成“应用程序可以访问的样子”。

    当然,考虑到模型文件在使用上的特殊性,也为其设计了特殊的存储格式,即直接删去了帧头,只保留了数据部分。而对于图像输入等,需要明确知道其输入维度的数据,就需要保留帧头信息了。

    在这里再次做个广告:下一篇我们以i.MX RT1060系列芯片为例,进行MCU实战部分,包括如何进行C代码的的编写获取数据,Keil的散列加载文件的编写以实现数据的运行时加载,完成将数据拷从Flash拷贝到sdram等,敬请期待!





    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-20 00:48 , Processed in 0.117148 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表