MNIST是一个入门级的计算机视觉数据集,它包含各种手写数字图片,分辨率为28*28,色深为8bit灰度图
我们常用该数据集测试一些入门级的图像识别算法的准确率。
本文就将带你在30分钟内训练,转换,运行MNIST识别算法于MAIX开发板
本文要求的PC环境:Ubuntu 1804 64bit 以上, python 3.6
本文要求的硬件环境:Sipeed MAIX系列开发板
10min:神经网络训练
安装tensorflow环境
pip3 install tensorflow
如果安装失败,可以到https://pypi.org/搜索tensorflow下载安装
运行mnist训练脚本
我们上传了mnist训练脚本,可到此处下载:
https://github.com/sipeed/Maix-TF-workspace.git
运行mnist训练脚本:python3 mnist.py
训练脚本会自动下载,训练神经网络,最后在目录下得到了mnist.pb, 即模型文件。
(代码第121行为训练次数,可以酌情增减来调整精度或者训练时间)
python3 mnist.py
……
step 0, train_accuracy 0.04
step 100, train_accuracy 0.26
……
step 4900, train_accuracy 0.94
test accuracy 0.9428
小贴士
- 目前KPU驱动支持的算子在kpu.h中有描述,如果在构建模型中请避免使用在支持算子之外的算子
- 特征图宽度为64倍数时,能够让KPU完全发挥算力(KPU是以64像素宽为单位计算)
- 3×3卷积最能发挥KPU算力,1×1卷积或者depth wise 卷积效率只有3×3卷积的1/8~1/9
- 详细KPU图示见:http://dl.sipeed.com/MAIX/SDK/Document/KPU%20diagram.pdf
typedef enum
{
KL_INVALID = 0,
KL_ADD,
KL_QUANTIZED_ADD,
KL_GLOBAL_MAX_POOL2D,
KL_QUANTIZED_GLOBAL_MAX_POOL2D,
KL_GLOBAL_AVERAGE_POOL2D,
KL_QUANTIZED_GLOBAL_AVERAGE_POOL2D,
KL_MAX_POOL2D,
KL_QUANTIZED_MAX_POOL2D,
KL_AVERAGE_POOL2D,
KL_QUANTIZED_AVERAGE_POOL2D,
KL_QUANTIZE,
KL_DEQUANTIZE,
KL_REQUANTIZE,
KL_L2_NORMALIZATION,
KL_SOFTMAX,
KL_CONCAT,
KL_QUANTIZED_CONCAT,
KL_FULLY_CONNECTED,
KL_QUANTIZED_FULLY_CONNECTED,
KL_TENSORFLOW_FLATTEN,
KL_QUANTIZED_TENSORFLOW_FLATTEN,
KL_K210_CONV = 10240,
KL_K210_ADD_PADDING,
KL_K210_REMOVE_PADDING,
KL_K210_UPLOAD
} kpu_model_layer_type_t;
10min: pb模型转换为kmodel
下载MAIX_Toolbox
MAIX_Toolbox内收集了常用格式转换的脚本程序,大家可以方便地使用他们进行模型格式转换。
https://github.com/sipeed/Maix_Toolbox.git
查看计算图
我们使用MAIX Toolbox内的gen_pb_graph.py工具来查看计算图,在这之前先把mnist.pb放入workspace目录下
python3 gen_pb_graph.py workspace/mnist.pb
WARNING:tensorflow:From gen_pb_graph.py:9: FastGFile.__init__ (from tensorflow.python.platform.gfile) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.gfile.GFile.
TensorBoard 1.12.2 at http://sipeed_ai:6006 (Press CTRL+C to quit)
我们就可以打开浏览器,输入它提示的网址进行查看计算图:
可以看到输入节点名为“inputs”,输出节点名为“output”
转换模型
首先从pb转换为tflite:
./pb2tflite.sh workspace/mnist.pb
This script help you generate cmd to convert *.pb to *.tflite
Please put your pb into workspace dir
1. pb file name: (don't include workspace)
mnist.pb
2. input_arrays name:
inputs
3. output_arrays name:
output
4. input width:
28
5. input height:
28
6. input channel:
1
-----------------------------------
The command you need is:
-----------------------------------
toco --graph_def_file=workspace/mnist.pb --input_format=TENSORFLOW_GRAPHDEF --output_format=TFLITE --output_file=workspace/mnist.tflite --inference_type=FLOAT --input_type=FLOAT --input_arrays=inputs --output_arrays=output --input_shapes=1,28,28,1
2019-03-18 09:35:35.452504: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
现在在workspace里生成了mnist.tflite
然后我们再生成kmodel:
在执行以下命令之前,请放入一些训练集或者测试集的图片到images目录下,辅助nncase进行动态范围估计,进而进行量化操作。
./tflite2kmodel.sh workspace/mnist.tflite
uasge: ./tflite2kmodel.sh xxx.tflite
2019-03-18 09:38:06.654782: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
0: InputLayer -> 1x1x28x28
1: K210Conv2d 1x1x28x28 -> 1x16x14x14
2: K210Conv2d 1x16x14x14 -> 1x32x7x7
3: Dequantize 1x32x7x7 -> 1x32x7x7
4: TensorflowFlatten 1x32x7x7 -> 1x1568
5: FullyConnected 1x1568 -> 1x32
6: Quantize 1x32 -> 1x32
7: K210AddPadding 1x32 -> 1x32x4x4
8: K210Conv2d 1x32x4x4 -> 1x10x4x4
9: K210RemovePadding 1x10x4x4 -> 1x10
10: Dequantize 1x10 -> 1x10
11: Softmax 1x10 -> 1x10
12: OutputLayer 1x10
KPU memory usage: 8960 B
Main memory usage: 14112 B
这时在workspace下生成了mnist.kmodel
ls workspace/ -l
-rw-rw-r-- 1 sipeed sipeed 208072 Mar 18 09:38 mnist.kmodel
可以看到模型大小为200KB大小左右。
这里模型尺寸偏大,是因为全连接层通道数超过了1024,使用了软件进行浮点全连接运算,增大了模型大小。
如果想优化尺寸大小,可以减小全连接层的大小,或者使用GLOBAL_AVERAGE_POOL来代替全连接层。
10min: 在MAIX上运行MNIST算法
下载工程
在这里下载MNIST验证工程,将目录拷贝到standalone工程的src目录下即可。
https://github.com/sipeed/LicheeDan_K210_examples/tree/master/src/mnist
我们把生成的mnist.kmodel重命名为m.kmodel,放入代码目录
在main.c中,有个宏开关:LOAD_FROM_FLASH
如果关闭,会直接将模型数据编译进固件;
如果打开,则会从flash指定偏移读取kmodel。
在模型大小较小时,可以直接编译进固件,如果模型上M大小的话,则预先烧录进flash比较方便,避免调试程序时反复烧录固件。
模型烧录进flash的方法:使用pack_model.sh打包出kfpkg文件,使用kflash烧录。
工程浏览及编译下载
简要解读下工程:
首先初始化了 时钟,IO,屏幕,摄像头,如果模型存在flash的话,则从flash读取模型到内存。
主循环中,等待摄像头获取到一帧图像,原始分辨率为224x224xRGB的彩色图像。
我们进行灰度化并降采样,反色,然后根据灰度直方图进行灰度拉伸,如果使用M12镜头的话,还需要进行去暗角操作。
此时我们就获取到了接近MNIST数据集的图像了,就可以把图像送入KPU处理。
使用kpu_run_kmodel运行模型,计算结束后,我们使用kpu_get_output获取最后一层的输出结果。
在我们的模型中,最后一层就是10个数字的置信概率。
我们在show_result函数中同时展示了原始图像,预处理后的28×28图像,以及最高概率的数字及概率。
在build目录下编译我们的工程,生成mnist.bin, 然后下载固件:
./kflash.py -p /dev/ttyUSB1 -b 2000000 mnist.bin
运行效果展示
视频见:
Youtube:
Bilibili:
下一篇文章我们体验使用MaixPy 3分钟运行kmodel!
能不能出个tensorflow workspace的教程?