【雕爷学编程】MicroPython动手做(10)——零基础学MaixPy之神经网络KPU2

KPU的基础架构
让我们回顾下经典神经网络的基础运算操作:
卷积(Convolution):1x1卷积,3x3卷积,5x5及更高的卷积
批归一化(Batch Normalization)
激活(Activate)
池化(Pooling)
矩阵运算(Matrix Calculate):矩阵乘,加
对于基础的神经网络结构,仅具备1,2,3,4 四种操作;
对于新型网络结构,比如ResNet,在卷积结果后会加一个变量,就需要使用第五种操作,矩阵运算。
对于MAIX的主控芯片K210来说,它内置实现了 卷积,批归一化,激活,池化 这4钟基础操作的硬件加速,但是没有实现一般的矩阵运算,所以在实现的网络结构上有所限制。
对于需要额外操作的网络结构,用户必须在硬件完成基础操作后,手工插入CPU干预的处理层实现,会导致帧数降低,所以建议用户优化自己的网络结构到基础网络形式。
所幸的是,该芯片的第二代将支持通用矩阵计算,并固化更多类型的网络结构。
在KPU中,上述提到的4种基础操作并非是单独的加速模块,而是合成一体的加速模块,有效避免了CPU干预造成的损耗,但也丧失了一些操作上的灵活性。
从standalone sdk/demo 以及 Model Compiler 中分析出 KPU加速模块的原理框图如下,看图即懂。

在这里插入图片描述

#MicroPython动手做(10)——零基础学MaixPy之神经网络KPU
#实验程序之一:运行人脸识别demo(简单演示)
#模型下载地址:http://dl.sipeed.com/MAIX/MaixPy/model/face_model_at_0x300000.kfpkg
下载后模型文件夹内有二个文件

在这里插入图片描述
在这里插入图片描述

打开kflash_gui
使用kfpkg将 二个模型文件 与 maixpy 固件打包下载到 flash

在这里插入图片描述
打包kfpkg时出错,好像是文件地址范围不同…

在这里插入图片描述

尝试多次一直不行,两者不兼容。后来干脆不打包了,只烧录模型文件kfpkg(原来烧录过MaixPy固件V0.4.0),没想到可以了,这下明白了,固件和模型分开烧录也行。

在这里插入图片描述

#MicroPython动手做(10)——零基础学MaixPy之神经网络KPU
#实验程序之一:运行人脸识别demo(简单演示)
#模型下载地址:http://dl.sipeed.com/MAIX/MaixPy … l_at_0x300000.kfpkg

#MicroPython动手做(10)——零基础学MaixPy之神经网络KPU
#实验程序之一:运行人脸识别demo(简单演示)
#模型下载地址:http://dl.sipeed.com/MAIX/MaixPy ... l_at_0x300000.kfpkgimport sensor
import image
import lcd
import KPU as kpulcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.run(1)
task = kpu.load(0x300000) #使用kfpkg将 kmodel 与 maixpy 固件打包下载到 flash
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
while(True):img = sensor.snapshot()code = kpu.run_yolo2(task, img)if code:for i in code:print(i)a = img.draw_rectangle(i.rect())a = lcd.display(img)
a = kpu.deinit(task)

在这里插入图片描述
串口输出了大量数据

在这里插入图片描述

{“x”:0, “y”:31, “w”:107, “h”:145, “value”:0.611305, “classid”:0, “index”:0, “objnum”:1}
{“x”:0, “y”:31, “w”:107, “h”:145, “value”:0.500000, “classid”:0, “index”:0, “objnum”:1}
{“x”:1, “y”:31, “w”:107, “h”:144, “value”:0.500000, “classid”:0, “index”:0, “objnum”:1}
{“x”:0, “y”:31, “w”:107, “h”:145, “value”:0.556360, “classid”:0, “index”:0, “objnum”:1}
{“x”:13, “y”:34, “w”:83, “h”:139, “value”:0.556360, “classid”:0, “index”:0, “objnum”:1}
{“x”:0, “y”:31, “w”:107, “h”:145, “value”:0.500000, “classid”:0, “index”:0, “objnum”:1}
{“x”:0, “y”:31, “w”:107, “h”:145, “value”:0.500000, “classid”:0, “index”:0, “objnum”:1}
{“x”:0, “y”:31, “w”:107, “h”:145, “value”:0.556360, “classid”:0, “index”:0, “objnum”:1}
{“x”:0, “y”:31, “w”:107, “h”:145, “value”:0.500000, “classid”:0, “index”:0, “objnum”:1}
{“x”:15, “y”:36, “w”:83, “h”:111, “value”:0.556360, “classid”:0, “index”:0, “objnum”:1}
{“x”:13, “y”:33, “w”:83, “h”:139, “value”:0.556360, “classid”:0, “index”:0, “objnum”:1}
{“x”:14, “y”:47, “w”:83, “h”:111, “value”:0.500000, “classid”:0, “index”:0, “objnum”:1}
{“x”:0, “y”:31, “w”:107, “h”:144, “value”:0.556360, “classid”:0, “index”:0, “objnum”:1}
{“x”:13, “y”:32, “w”:83, “h”:139, “value”:0.500000, “classid”:0, “index”:0, “objnum”:1}
{“x”:14, “y”:32, “w”:83, “h”:139, “value”:0.611305, “classid”:0, “index”:0, “objnum”:1}
{“x”:0, “y”:31, “w”:107, “h”:144, “value”:0.556360, “classid”:0, “index”:0, “objnum”:1}

KPU是通用的神经网络处理器,它可以在低功耗的情况下实现卷积神经网络计算,时时获取被检测目标的大小、坐标和种类,对人脸或者物体进行检测和分类。KPU模块方法:

  1. 加载模型
    从flash或者文件系统中加载模型
    import KPU as kpu
    task = kpu.load(offset or file_path)

参数
offtset: 模型在 flash 中的偏移大小,如 0xd00000 表示模型烧录在13M起始的地方
file_path: 模型在文件系统中为文件名, 如 “/sd/xxx.kmodel”

返回
kpu_net: kpu 网络对象

  1. 初始化yolo2网络
    为yolo2网络模型传入初始化参数
    import KPU as kpu
    task = kpu.load(offset or file_path)
    anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
    kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)

参数
kpu_net: kpu 网络对象
threshold: 概率阈值
nms_value: box_iou 门限
anchor_num: 锚点数
anchor: 锚点参数与模型参数一致

  1. 反初始化
    import KPU as kpu
    task = kpu.load(offset or file_path)
    kpu.deinit(task)

参数
kpu_net: kpu_load 返回的 kpu_net 对象

  1. 运行yolo2网络
    import KPU as kpu
    import image
    task = kpu.load(offset or file_path)
    anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
    kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
    img = image.Image()
    kpu.run_yolo2(task, img)

参数
kpu_net: kpu_load 返回的 kpu_net 对象
image_t:从 sensor 采集到的图像

返回
list: kpu_yolo2_find 的列表

  1. 网络前向运算(forward)
    计算已加载的网络模型到指定层数,输出目标层的特征图
    import KPU as kpu
    task = kpu.load(offset or file_path)
    ……
    fmap=kpu.forward(task,img,3)

参数
kpu_net: kpu_net 对象
image_t: 从 sensor 采集到的图像
int: 指定计算到网络的第几层

返回
fmap: 特征图对象,内含当前层所有通道的特征图

  1. fmap 特征图
    取特征图的指定通道数据到image对象
    img=kpu.fmap(fmap,1)

参数
fmap: 特征图 对象
int: 指定特征图的通道号】

返回
img_t: 特征图对应通道生成的灰度图

  1. fmap_free 释放特征图
    释放特征图对象
    kpu.fmap_free(fmap)

参数
fmap: 特征图 对象

返回

  1. netinfo
    获取模型的网络结构信息
    info=kpu.netinfo(task)
    layer0=info[0]

参数
kpu_net: kpu_net 对象

返回
netinfo list:所有层的信息list, 包含信息为:
index:当前层在网络中的层数
wi:输入宽度
hi:输入高度
wo:输出宽度
ho:输出高度
chi:输入通道数
cho:输出通道数
dw:是否为depth wise layer
kernel_type:卷积核类型,0为1x1, 1为3x3
pool_type:池化类型,0不池化; 1:2x2 max pooling; 2:…
para_size:当前层的卷积参数字节数

KPU寄存器配置说明
芯片厂家没有给出寄存器手册,我们从kpu.c, kpu.h, Model Compiler中分析各寄存器定义。KPU的寄存器配置写在 kpu_layer_argument_t 结构体中,我们取standalone demo中的kpu demo中的gencode.c来分析.(https://github.com/kendryte/kend … pu/gencode_output.c)

//层参数列表,共16层kpu_layer_argument_t la[] __attribute__((aligned(128))) = {
//0{
.kernel_offset.data = {.coef_row_offset = 0,                //固定为0.coef_column_offset = 0        //固定为0
},
.image_addr.data = {                //图像输入输出地址,一个在前,一个在后,下一层运算的时候翻过来,可以避免拷贝工作。.image_dst_addr = (uint64_t)0x6980,        //图像输出地址,int((0 if idx & 1 else (img_ram_size - img_output_size)) / 64).image_src_addr = (uint64_t)0x0                //图像加载地址
},
.kernel_calc_type_cfg.data = {.load_act = 1,                        //使能激活函数,必须使能(硬件设计如此),不使能则输出全为0.active_addr = 0,                        //激活参数加载首地址,在kpu_task_init里初始化为激活折线表.row_switch_addr = 0x5,        //图像宽占用的单元数,一个单元64Byte.  ceil(width/64)=ceil(320/64)=5.channel_switch_addr = 0x4b0,                        //单通道占用的单元数.  row_switch_addr*height=5*240=1200=0x4b0.coef_size = 0,                        //固定为0.coef_group = 1                        //一次可以计算的组数,因为一个单元64字节,//所以宽度>32,设置为1;宽度17~32,设置为2;宽度<=16,设置为4
},
.interrupt_enabe.data = {.depth_wise_layer = 0,        //常规卷积层,设置为0.ram_flag = 0,                        //固定为0.int_en = 0,                                //失能中断.full_add = 0                                //固定为0
},
.dma_parameter.data = {        //DMA传输参数.dma_total_byte = 307199,                //该层输出16通道,即 19200*16=308200.send_data_out = 0,                        //使能输出数据.channel_byte_num = 19199                //输出单通道的字节数,因为后面是2x2 pooling, 所以大小为160*120=19200
},
.conv_value.data = {                //卷积参数,y = (x*arg_x)>>shr_x.arg_x = 0x809179,                //24bit        乘法参数.arg_w = 0x0,.shr_x = 8,                                //4bit        移位参数.shr_w = 0
},
.conv_value2.data = {                //arg_add = kernel_size * kernel_size * bw_div_sw * bx_div_sx =3x3x?x?.arg_add = 0
},
.write_back_cfg.data = {        //写回配置.wb_row_switch_addr = 0x3,                //ceil(160/64)=3.wb_channel_switch_addr = 0x168,        //120*3=360=0x168.wb_group = 1                                                //输入行宽>32,设置为1
},
.image_size.data = {        //输入320*240,输出160*120.o_col_high = 0x77,.i_col_high = 0xef,.i_row_wid = 0x13f,.o_row_wid = 0x9f
},
.kernel_pool_type_cfg.data = {.bypass_conv = 0,                //硬件不能跳过卷积,固定为0.pad_value = 0x0,                //边界填充0.load_para = 1,                //硬件不能跳过归一化,固定为1.pad_type = 0,                //使用填充值.kernel_type = 1,                //3x3设置为1, 1x1设置为0.pool_type = 1,                //池化类型,步长为2的2x2 max pooling.dma_burst_size = 15,        //dma突发传送大小,16字节;脚本中固定为16.bwsx_base_addr = 0,        //批归一化首地址,在kpu_task_init中初始化.first_stride = 0                //图像高度不超过255;图像高度最大为512},
.image_channel_num.data = {.o_ch_num_coef = 0xf,        //一次性参数加载可计算的通道数,16通道。4K/单通道卷积核数//o_ch_num_coef = math.floor(weight_buffer_size / o_ch_weights_size_pad)       .i_ch_num = 0x2,                //输入通道,3通道 RGB.o_ch_num = 0xf                //输出通道,16通道
},
.kernel_load_cfg.data = {.load_time = 0,                //卷积加载次数,不超过72KB,只加载一次.para_size = 864,                //卷积参数大小864字节,864=3(RGB)*9(3x3)*2*16.para_start_addr = 0,        //起始地址.load_coor = 1                //允许加载卷积参数
}
},//0层参数结束……
};上表中还有些结构体内容没有填充,是在KPU初始化函数中填充:```kpu_task_t* kpu_task_init(kpu_task_t* task){
la[0].kernel_pool_type_cfg.data.bwsx_base_addr = (uint64_t)&bwsx_base_addr_0;        //初始化批归一化表
la[0].kernel_calc_type_cfg.data.active_addr = (uint64_t)&active_addr_0;                //初始化激活表
la[0].kernel_load_cfg.data.para_start_addr = (uint64_t)¶_start_addr_0;         //初始化参数加载
……        //16层参数,逐层计算
task->layers = la;
task->layers_length = sizeof(la)/sizeof(la[0]);        //16层
task->eight_bit_mode = 0;                                        //16bit模式
task->output_scale = 0.12349300010531557;        //输出的缩放,偏置
task->output_bias = -13.528212547302246;
return task;
}```

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

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

相关文章

单例模式(Singleton)

单例模式保证一个类仅有一个实例&#xff0c;并提供一个全局访问点来访问它&#xff0c;这个类称为单例类。可见&#xff0c;在实现单例模式时&#xff0c;除了保证一个类只能创建一个实例外&#xff0c;还需提供一个全局访问点。 Singleton is a creational design pattern t…

JavaScript场景应用:Canvas实战开发一个二维折线图插件

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f3c6;本文已…

VB6中FSO具体应用详解

文前申明:原文为通用版实例代码,本菜鸟在每例之后加入一个简单的实例(均验证通过),供有需要的朋友参考. 您正在看的VB教程是:VB入门基础认识VB的文件系统对象FSO。 在 VB 编程中经常需要和文件系统打交道&#xff0c;比如获取硬盘的剩余空间、判断文件夹或文件是否存在等。在…

认识主被动无人机遥感数据、预处理无人机遥感数据、定量估算农林植被关键性状、期刊论文插图精细制作与Appdesigner应用开发

目录 第一章、认识主被动无人机遥感数据 第二章、预处理无人机遥感数据 第三章、定量估算农林植被关键性状 第四章、期刊论文插图精细制作与Appdesigner应用开发 更多推荐 遥感技术作为一种空间大数据手段&#xff0c;能够从多时、多维、多地等角度&#xff0c;获取大量的…

PHP语言基础知识(超详细)

文章目录 前言第一章 PHP语言学习介绍 1.1 PHP部署安装环境1.2 PHP代码工具选择 第二章 PHP代码基本语法 2.1 PHP函数知识介绍2.2 PHP常量变量介绍 2.2.1 PHP变量知识&#xff1a;2.2.2 PHP常量知识&#xff1a; 2.3 PHP注释信息介绍2.4 PHP数据类型介绍 2.4.1 整形数据类型2.4…

基于量子同态的安全多方量子求和加密

摘要安全多方计算在经典密码学中一直扮演着重要的角色。量子同态加密(QHE)可以在不解密的情况下对加密数据进行计算。目前&#xff0c;大多数协议使用半诚实的第三方(TP)来保护参与者的秘密。我们使用量子同态加密方案代替TP来保护各方的隐私。在量子同态加密的基础上&#xff…

2023年自动化测试已成为标配?一篇彻底打通自动化测试...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 首先我们从招聘岗…

《面试1v1》ElasticSearch 和 Lucene

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

智慧~经典开源项目数字孪生智慧商场——开源工程及源码

深圳南山某商场的工程和源码免费赠送&#xff0c;助您打造智慧商场。立即获取&#xff0c;提升商场管理效能&#xff01; 项目介绍 凤凰商场作为南山地区的繁华商业中心&#xff0c;提供多样化的购物和娱乐体验。通过此项目&#xff0c;凤凰商场将迈向更智能的商业模式。 本项目…

基于SaaS模式的Java基层卫生健康云HIS系统源码【运维管理+运营管理+综合监管】

云HIS综合管理平台 一、模板管理 模板分为两种&#xff1a;病历模板和报表模板。模板管理是运营管理的核心组成部分&#xff0c;是基层卫生健康云中各医疗机构定制电子病历和报表的地方&#xff0c;各医疗机构可根据自身特点特色定制电子病历和报表&#xff0c;制作的电子病历…

Python-Python基础综合案例:数据可视化 - 折线图可视化

版本说明 当前版本号[20230729]。 版本修改说明20230729初版 目录 文章目录 版本说明目录知识总览图Python基础综合案例&#xff1a;数据可视化 - 折线图可视化json数据格式什么是jsonjson有什么用json格式数据转化Python数据和Json数据的相互转化 pyecharts模块介绍概况如何…

Golang 函数参数的传递方式 值传递,引用传递

基本介绍 我们在讲解函数注意事项和使用细节时&#xff0c;已经讲过值类型和引用类型了&#xff0c;这里我们再系统总结一下&#xff0c;因为这是重难点&#xff0c;值类型参数默认就是值传递&#xff0c;而引用类型参数默认就是引用传递。 两种传递方式&#xff08;函数默认都…

BUG分析以及BUG定位

一般来说bug大多数存在于3个模块&#xff1a; 1、前台界面&#xff0c;包括界面的显示&#xff0c;兼容性&#xff0c;数据提交的判断&#xff0c;页面的跳转等等&#xff0c;这些bug基本都是一眼可见的&#xff0c;不太需要定位&#xff0c;当然也不排除一些特殊情况&#xf…

《cuda c编程权威指南》04 - 使用块和线程索引映射矩阵索引

目录 1. 解决的问题 2. 分析 3. 方法 4. 代码示例 1. 解决的问题 利用块和线程索引&#xff0c;从全局内存中访问指定的数据。 2. 分析 通常情况下&#xff0c;矩阵是用行优先的方法在全局内存中线性存储的。如下。 8列6行矩阵&#xff08;nx,ny&#xff09;&#xff08;…

Kafka-消费者组消费流程

消费者向kafka集群发送消费请求&#xff0c;消费者客户端默认每次从kafka集群拉取50M数据&#xff0c;放到缓冲队列中&#xff0c;消费者从缓冲队列中每次拉取500条数据进行消费。

时序预测 | Python实现NARX-DNN空气质量预测

时序预测 | Python实现NARX-DNN空气质量预测 目录 时序预测 | Python实现NARX-DNN空气质量预测效果一览基本介绍研究内容程序设计参考资料效果一览 基本介绍 时序预测 | Python实现NARX-DNN空气质量预测 研究内容 Python实现NARX-DNN空气质量预测,使用深度神经网络对比利时空气…

PDF文件忘记密码,怎么办?

PDF文件设置密码分为打开密码和限制密码&#xff0c;忘记了密码分别如何解密PDF密码&#xff1f; 如果是限制编辑密码忘记了&#xff0c;我们可以试着将PDF文件转换成其他格式来避开限制编辑&#xff0c;然后重新将文件转换回PDF格式就可以了。 如果因为转换之后导致文件格式…

如何打造属于自己的个人IP?

在当今信息爆炸的时代&#xff0c;个人 IP 已经成为人们在网络世界中的独特标签。无论是在职场上、创业中&#xff0c;还是在社交生活中&#xff0c;拥有个人 IP 的人都能脱颖而出&#xff0c;吸引更多的关注和机会。那么&#xff0c;如何打造属于自己的个人 IP 呢&#xff1f;…

go 如何知道一个对象是分配在栈上还是堆上?

如何判断变量是分配在栈&#xff08;stack&#xff09;上还是堆&#xff08;heap&#xff09;上&#xff1f; Go和C不同&#xff0c;Go局部变量会进行逃逸分析。如果变量离开作用域后没有被引用&#xff0c;则优先分配到栈上&#xff0c;否则分配到堆上。判断语句&#xff1a;…

在外远程NAS群晖Drive - 群晖Drive挂载电脑磁盘同步备份【无需公网IP】

文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…