MNIST-SIMPLE
MNIST 是一個手寫數字庫,由250個人的手寫數字組成。每個數字被裁剪成 28 * 28 的灰度圖片。
MNIST 經常被用來做為分類任務的入門數據庫使用。在這個簡單的例子里面,我們也用它來試試數據歸類。
1. 下載并啟用NNoM
在 RT-Thread 的包管理中
RT-Thread online packages --->
miscellaneous packages --->
[*] NNoM: A Higher-level Nerual Network ... --->
*選擇 latest 版本
*需要打開 msh 支持
源碼請到GitHub
2. 復制例子文件
把 packages/nnom-latest/examples/mnist-simple/mcu
目錄下的三個文件 image.h
, weights.h
和 main.c
復制到工程目錄的 application/
。替換掉默認的 main.c
。先不用管這三個文件的內容。
(如果你是好奇寶寶:)
-
image.h
里面放置了 10 張從 MNIST 數據集里面隨機挑選的圖片。 -
weights.h
是 NNoM 的工具腳本自動生成的模型參數。 -
main.c
包含了最簡單的模型初始化和 msh 交互命令。
3. 跑起來
用你喜歡的方式,編譯,下載,運行
3.1 模型編譯
RT-Thread 啟動后,接著會在 main()
函數里面調用 model = nnom_model_create();
。
這條語句將會載入我們藏在 weights.h
里面的模型,將它編譯并把信息打印出來。
\ | /
- RT - Thread Operating System
/ | \ 4.0.0 build Mar 29 2019
2006 - 2018 Copyright by rt-thread team
RTT Control Block Detection Address is 0x20000a8c
msh >
INFO: Start compile...
Layer Activation output shape ops memory mem life-time
----------------------------------------------------------------------------------------------
Input - - ( 28, 28, 1) 0 ( 784, 784, 0) 1 - - - - - - -
Conv2D - ReLU - ( 28, 28, 12) 84672 ( 784, 9408, 432) 1 1 - - - - - -
MaxPool - - ( 14, 14, 12) 0 ( 9408, 2352, 0) 1 - 1 - - - - -
Conv2D - ReLU - ( 14, 14, 24) 508032 ( 2352, 4704, 864) 1 1 - - - - - -
MaxPool - - ( 7, 7, 24) 0 ( 4704, 1176, 0) 1 - 1 - - - - -
Conv2D - ReLU - ( 7, 7, 48) 508032 ( 1176, 2352, 1728) 1 1 - - - - - -
MaxPool - - ( 4, 4, 48) 0 ( 2352, 768, 0) 1 - 1 - - - - -
Dense - ReLU - ( 96, 1, 1) 73728 ( 768, 96, 768) 1 1 - - - - - -
Dense - - ( 10, 1, 1) 960 ( 96, 10, 96) 1 - 1 - - - - -
Softmax - - ( 10, 1, 1) 0 ( 10, 10, 0) - 1 - - - - - -
Output - - ( 10, 1, 1) 0 ( 10, 10, 0) 1 - - - - - - -
----------------------------------------------------------------------------------------------
INFO: memory analysis result
Block0: 1728 Block1: 2352 Block2: 9408 Block3: 0 Block4: 0 Block5: 0 Block6: 0 Block7: 0
Total memory cost by network buffers: 13488 bytes
這里面的信息有:
- 模型有三個卷積層組成,每個卷積層都使用 ReLU 進行激活 (ReLU: 大于0的數值不變,小于0的數值重新賦值為0)。
- 三個卷積后面跟著兩個 Dense 層 (Densely-connected,或者也叫 fully-connected 全連接層)。
- 最后模型通過 Softmax 層來輸出 (將數值轉換成概率值)
- 各層的內存信息,輸出的數據,計算量 (定點乘加操作:MAC-OPS)
- 總網絡內存占用 13488 bytes
3.2 跑個模型
之前我們介紹過 image.h
里面藏有十張圖片。我們現在可以通過 mnist
這個自定義的 MSH 命令來預測一下這十張圖。
命令使用方法如下, num 是 0~9 里面的任意數字。代表十張圖片里面的第幾個圖片(注意:輸入的數字并非指圖片的數字,圖片是隨機拉取的)。
mnist num
我輸入了 msh >mnist 6
,我要測試第六張圖片。
msh >mnist 6
prediction start..
..]] ((ZZOO))^^
``//qq&&)) kkBB@@@@ff
"">>\\pp%%ZZ,, [[%%@@BB11
^^}}MM@@@@oo{{ rr@@@@OO<<
nn@@@@aajj.. ++dd@@88nn''
\\%%@@hh!! ++88@@oo::
!!%%@@kk>> ;;88@@oo::
))@@@@<< ^^pp@@oo::
::oo@@WWzzll!!bb@@bb''
ttBB@@@@%%WW@@**,,
ll}}LL%%@@@@@@bbtt''
``&&@@MMCC&&%%hh[[
((@@@@(( II**@@nn''
??@@##`` QQ@@>>
((@@@@^^ [[@@pp
[[@@@@^^ nn@@jj
..aa@@[[ ZZ%%++
__@@**,, xx@@OO
{{&&**jj00@@aa::
^^YYpppp||,,
Time: 62 tick
Truth label: 8
Predicted label: 8
額,如果惡心到你了,那我道歉...
不要懷疑,上面那一坨是 ASCII 碼表示的 28 * 28 的手寫圖片...
輸出的信息里面記錄了
- 此次預測的時間,這里用了
62 tick
,我這是相當于 62ms - 這張圖片的真實數字是
8
- 網絡計算的這張照片的數字
8
趕快去試試,其他的 9 張圖片吧。
簡單的體驗就到這。
4 建立自己的模型
對于沒有機器學習基礎的同學,想要在 MCU 上跑自己的模型,需要先學會在 Keras 里面建立一個模型。
在這里可以參照網絡上 Keras 的教程來修改這個例子里面的模型。
這個例子的模型在 nnom/example/mnist-simple/model
里面的 mnist_simple.py
,請自行實踐。
*需要把 nnom/scripts
下的幾個 python 腳本文件復制到以上目錄。
環境是 Python3 + Keras + Tensorflow。推薦使用 Anaconda 來安裝 python 環境而不是 pip。
模型訓練完成后,會生成 weights.h
還會生成隨機圖片文件 image.h
。 接下來按照上面的操作從頭來一遍就好。
5 結語
使用 NNoM 來部署神經網絡真的很簡單?;A的代碼不過兩三行,NNoM 能輕松讓你的 MCU 也神經一把~ 變成真正的 Edge AI 設備。
這個例子僅使用了最簡單的 API 搭建了最基礎的卷積模型。