找回密码
 立即注册
Qt开源社区 门户 查看内容

愚蠢项目|在嵌入式MCU上玩机器学习(一)

2019-8-11 07:03| 发布者: admin| 查看: 612| 评论: 0

摘要: 本文原作者Dimitris Tassopoulos(Dimtass);电工哔哔翻译本文较长,建议合理使用微信悬停功能“这就是我们最终关心的,对吗?这是我创建这个项目的主要动力。要了解这些MCU在执行简单或更复杂的NN时表现如何?是否 ...
本文原作者Dimitris Tassopoulos(Dimtass);电工哔哔翻译本文较长,建议合理使用微信悬停功能
“这就是我们最终关心的,对吗?这是我创建这个项目的主要动力。要了解这些MCU在执行简单或更复杂的NN时表现如何?是否可以实时运行NN?甚至说在MCU上运行NN有意义吗?你应该期待什么?值得吗?那些mcu能有好的性能吗?极限是什么?为了在微控制器上运行,把神经网络问题转换成算法可能更好吗?嵌套ifs、查找表、卡诺图还是更好的选择吗?还有很多其他问题。


从2015年开始我就密切关注着机器学习(Machine Learning;ML)的炒作,四年后的今天我终于可以说这已经足够成熟到可以让我参与并尝试在中低端的嵌入式领域中进行游戏和实验。尽管立即参与新技术是令人兴奋的,但我相信工程师应该关注那些在未来似乎很有价值的、或者有可能成长为可以在他们的领域中有使用价值的东西。但同时工程师应该保持温和的心态等待“炒作”消逝,然后才能获取到真正有价值的信息。对我来说,机器学习就是这样。现在我终于觉得已经到了可以深耕这一领域的合适时机,而且现在机器学习的工具和框架都已经成熟且易于使用。
事实使我们认识到,“实现”和“开发工具”是不同的,使用它们解决问题是另一回事。到目前为止,许多工程师都在努力开发这些工具,现在我们更容易使用它们来解决问题。例如,Keras,就是这样。Keras是一个成熟、漂亮并且非常稳定的框架。另一方面,当你等待这种情况发生时,你面前的学习曲线会更加陡峭,所以不时更新你感兴趣的领域的内容是件好事。无论如何,这一次我决定做这样一个完全愚蠢的项目来寻找嵌入式世界中机器学习的极限和用例。好吧,不要误解我,“愚蠢项目”并不是一项严肃的研究,它只是评估工具的当前状态以及它们在当前较低端的嵌入式技术下的表现。如今,当大多数工程师听到嵌入式时,他们会想到在SBC上运行Linux的ARM应用型MCU。是的没错,它们也都是嵌入式,而且目前许多SBC已经变得非常便宜。但是嵌入式同时也包括这些非常便宜的8位、16位、32位的RISC的MCU,同样的还有Cortex-M系列。让我们先做一些假设:在本项目中,我们假设低端嵌入式为所有Cortex-M或者更低端的一些计算芯片,也就是微控制器(MCU)。高端处理器我们指的是其它的一些可以运行Linux的CPU,也就是应用处理器。我知道还有一些更小的无内存管理的微处理器可以运行Linux,但是现在让我们忘掉它。也从现在开始,在本文中为了方便起见,我将把机器和深度学习统称为ML。尽管这个领域的术语越来越标准化,但我会尽量保持简单,即使在某些情况下我没有使用适当的惯例。否则这篇文章会变得像那些我刚开始读的一些文章一样,很难理解。最后,我将神经网络简称为NN。本文将分为4或5个不同的帖子。第一个(本文)将包括一些关于ML和NN的非常通用的信息;但并不会深入讲解,因为这不是本系列文章的目的。在这篇文章中,我们还将实现一个非常简单的神经网络,它只有一个节点,有3个输入和1个输出,然后在不同的微处理器中运行一些基准测试并分析结果。在第二部分中,我将使用相同的MCU,但是使用具有相同输入的更复杂的NN,但是具有32个节点和1个输出的隐藏层。与简单的NN相比,这个NN在预测中会更准确(正如我们所看到的);但与此同时,需要更多的处理时间来运行前向预测。请不要期望在这里学习ML的术语和细节,但如果您已经了解NN的一些基本知识,那么它将更容易理解。兴奋了吗?没有?好吧,不要忘记这是一个愚蠢的项目!做一些没用的东西总是令人兴奋。那么,让我们继续前进。

运行NN测试的所有开发板

对我来说,这个愚蠢项目中最有趣的事情之一是我使用了很多种不同的MCU开发板来运行NN基准测试。我认为我最喜欢的就是我能够使用相同的代码测试所有这些不同的板。当然,stm32f103(blue-pill)更加优化,因为我使用了自制的名为“cmake”的板子,但是我很享受我的大多数电路板运行相同的神经网络代码。好吧,我没有使用任何PSoC 4&5,STM8,LPC1110,LPC1768系列以及我所拥有的其他一些开发板,此次我没有更多时间花在这上面。也许以后我会为这些开发板也添加基准测试。

STM32F103C8T6 (AKA BLUE-PILL)
这是我最喜欢的板子和我的参考,所以它不能错过派对。我已经运行了@ 72MHz的基准测试,然后我将MCU超频到了 @ 128MHz。
STM32F746G-DISCO
这实际上是STM32 F7发现板,这是一个可爱的开发板,上面有很多外设和很酷的东西,但在这种情况下我只使用串口和GPIO引脚。
ARDUINO UNO
我想我不需要写更多关于此的内容。大家都知道。它的主控是ATmega328p上,是这次比较中最慢的MCU。
ARDUINO LEONARDO
这是另一款带有ATmega32 cpu的Arduino变体,它比ATmega328p快一点。
ARDUINO DUE
这是一款运行在Atmel SAM3X8E MCU上的arduino板,实际上是一台运行频率为84MHz的ARM Cortex-M3。在它发布的当年其实是相当快的一款MCU。
TEENSY 3.2
TEENSY是一个非常有趣的板。当然,有点贵。但是它几乎与Arduino集成开发环境库完全兼容,这使得它非常适合快速原型开发和测试。它是基于一个Cortex-M4中央处理器的,在测试中,我将其超频到了@120MHz。
TEENSY 3.5
这款TEENSY主板也使用了Cortex-M4 CPU;但它运行在更快的时钟上。我也用它超频@ 168MHz。两款Teensy主板的超频选项在Arduino IDE的Teensy插件中都很容易免费实现。
ESP8266-12E
是的,我们现在都是这个板子。一个L106 32位RISC CPU,运行频率高达160MHz。

一个简单的神经网络(NN)

好的,现在让我们跳到有趣的东西。与此项目和所有帖子相关的所有内容都在这个bitbucket仓库中:https://bitbucket.org/dimtass/machine-learning-for-embedded/src/master/虽然在一个仓库中放下所有这些不同的东西并不是最好的事情,但它更有意义,因为它使维护和更新更容易。在这个系列文章中,我将使用此bitbucket仓库中的不同部分,因此您在那里看到的很多的内容并不仅仅是第一篇文章中用到的。在我们开始之前,如果您想了解NN的一些基础知识,那么您可以自行去了解,在这里就不赘述了。首先让我们从一个简单的NN开始。对于这篇文章,我们将使用具有3个输入和1个输出的单个神经元。您可以在下图中看到。

在上图中,我们看到了简单NN的拓扑结构。它有3x输入和1x输出。我不会深入了解数学的细节。在这种情况下,输出很容易计算,它是:y = a0*w0  +  a1*w1 + a2*w2这是a(n)和w(n)的点积,其中n = 1,2,3。请注意,a(n)不是函数,它只表示a0,a1,a2。w(n)也是如此。因此,a(n)是输入,w(n)是所谓的权重。您可以认为权重只是一些数字,数字的大小控制着每个a(n)在输出结果中产生的影响。w(n)越高,a(n)对y的影响越大(多)。假设输出不是y。输出是y的sigmoid,因此:output = sigmoid(y)sigmoid的作用是将输出限制在0和1之间。因此y越接近0则越负,越接近1越正。在ML世界中,此功能称为激活功能。对于这个项目,我们假设a(n)是一个二进制数字(0或1)。因此,由于我们有3个输入,因此所有可能的组合都在下表中:
a0
a1
a2
000
001
010
011
100
101
110
111
为简单起见,您可以将这些输入视为连接到MCU上3个gpio引脚的3个按钮,它们的状态是按下或未按下。然后根据它们的状态,输出也是二进制值(0或1)。

训练模型

训练模型意味着获得一组已经可以确定的输出的和输入,然后根据这些输入训练NN。然后我们希望/期望NN能够预测未经过训练的未知输入的输出。培训不是针对目标板子上进行的,而是在具有更强处理能力的工作站(或云)上单独完成;最后只在MCU上执行预测功能。虽然这个模型非常简单,但有人可能认为2个输入 - 1个输出更简单

鲜花

握手

雷人

路过

鸡蛋

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了