NNoM 系列 - 在單片機和RT-Thread上擼個簡單的 MNIST 數據集吧

MNIST-SIMPLE

MNIST 是一個手寫數字庫,由250個人的手寫數字組成。每個數字被裁剪成 28 * 28 的灰度圖片。

image

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.hmain.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 搭建了最基礎的卷積模型。

高級用法和更多例子請查看API 文檔其他例子

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容