使用 NNOM ,我們可以先用 Python 訓練好模型,然後移植到C環境進行預測!
把這個 repository clone 下來: https://github.com/majianjia/nnom
若使用 VSCode 開發,安裝這個套件:
https://marketplace.visualstudio.com/items?itemName=danielpinto8zz6.c-cpp-project-generator
因為要進行動態連結,所以必須將所有檔案包裝於一個專案中,並用 makefile 編譯和執行。
移植 nnom 標頭檔和 source 檔:
cp -r path/to/nnom/inc/ path/to/workpath/include/
cp -r path/to/nnom/port/ path/to/workpath/include/
cp -r path/to/nnom/src/* path/to/workpath/src/
作業目錄建立 main.c 開始寫程式!
執行時可呼叫 ./output/main
,繞過 vscode 的除錯。
使用 nnom/examples/mnist-simple 來練習
用 mnist_simple.py 訓練模型 (直接執行即可,確認腳本路徑 ../../scripts
)
在程式碼裡面可以看到連接 NNOM 的 API,把模型轉換成 .h 檔
# select a few image and write them to image.h
image_to_cfile(x_test*127, y_test_num, 10, file='image.h')
# save weight
generate_model(model, np.vstack((x_train, x_test)), name="weights.h")
把生成的 weights.h, images.h 還有 mcu/main.c 丟到 C project 的作業目錄當中
此時,你的目錄應該會長這樣
或是,使用調整過的 main.c
/*
* Copyright (c) 2018-2020, Jianjia Ma
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-03-29 Jianjia Ma first implementation
*/
#include <stdio.h>
#include "nnom.h"
#include "image.h"
#include "weights.h"
nnom_model_t *model;
int main(void){
model = nnom_model_create();
model_run(model);
mnist(2, (char*[]){"mnist", "0"});
}
const char codeLib[] = "@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\\\|()1{}[]?-_+~<>i!lI;:,\\"^`'. ";
void print_img(int8_t * buf)
{
for(int y = 0; y < 28; y++)
{
for (int x = 0; x < 28; x++)
{
int index = 69 / 127.0 * (127 - buf[y*28+x]);
if(index > 69) index =69;
if(index < 0) index = 0;
printf("%c",codeLib[index]);
printf("%c",codeLib[index]);
}
printf("\\n");
}
}
// Do simple test using image in "image.h" with model created previously.
void mnist(int argc, char** argv){
uint32_t tick, time;
uint32_t predic_label;
float prob;
int32_t index = atoi(argv[1]);
if(index >= TOTAL_IMAGE || argc != 2)
{
printf("Please input image number within %d\\n", TOTAL_IMAGE-1);
return;
}
printf("\\nprediction start.. \\n");
// copy data and do prediction
memcpy(nnom_input_data, (int8_t*)&img[index][0], 784);
nnom_predict(model, &predic_label, &prob);
//print original image to console
print_img((int8_t*)&img[index][0]);
printf("Time: %d tick\\n", time);
printf("Truth label: %d\\n", label[index]);
printf("Predicted label: %d\\n", predic_label);
printf("Probability: %d%%\\n", (int)(prob*100));
}
void nn_stat(){
model_stat(model);
printf("Total Memory cost (Network and NNoM): %d\\n", nnom_mem_stat());
}