张小白带你体验MindSpore 1.1的新特性:MindSpore Lite端侧推理的另类实现
本文是 https://bbs.huaweicloud.cn/forum/thread-105498-1-1.html 论坛文字的去粗求精版,论坛文字强调折腾的过程,而本文则可以让读者一目了然知道MindSpore在如何利用runtime执行端侧推理的。
一切都要从【1.23-1.24 | MindSpore第五期两日集训营】的作业4说起。。。
作业内容:解压runtime tar包,将转换得到的mobilenetv2.ms模型,编写程序调用runtime include对外头文件,在X86跑通推理,假定输入初始化为1,打印模型推理输出,并将输出截图
参考页面:
(1)使用Runtime执行推理(C++) https://www.mindspore.cn/tutorial/lite/zh-CN/master/use/runtime_cpp.html
(2)使用Runtime执行推理(Java) https://www.mindspore.cn/tutorial/lite/zh-CN/master/use/runtime_java.html
(3)MindSpore Java API https://www.mindspore.cn/doc/api_java/zh-CN/master/index.html
张小白对题目的解析过程:
一开始,这道题张小白是完全不会做的。首先就没读懂题目的意思。后来仔细看了看C++的教程(上面第一个链接)中的流程图。多少知道了其中的意思,目前我们已经有了一个名为 mobilenetv2.ms 的移动端模型文件,这是在 由源码编译好的 MindSpore lite converter 将网上下载的 mobilenetv2.mindir 文件转换而来的。而现在,就是拿这个模型,读入 格式化后的Tensor,通过ms模型的编译和推理,生成一个目标的tensor。
当然,看懂了大概的意思,张小白也不会写这段 C++的代码,就把精力放在了如何用Java来实现上面。但是,即便是Java的实现,张小白也走了不小的弯路。具体的弯路过程在论坛帖子中都有描述,此处不再赘述。
我们直接说一下解题的过程:
使用Android Studio惯例打开image_segmentation这个项目( https://gitee.com/mindspore/mindspore/tree/master/model_zoo/official/lite/image_segmentation ),
在编译后run,将apk安装到华为手机上后,发现可以利用其中的 RECOVERY按钮搞事情:
因为这个按钮会触发 MainActivity.java的 onClickRecovery代码,而这个代码完全可以引入Java的推理内容。
如果你刚打开这个app,如果点击recovery,就会弹出 Please select an original picture first 这个字样,走进这个分支。
在app/src/main/asserts下,记得将 作业3的mobilenetv2.ms文件拷贝过来。大家可以看到这个目录下有2个ms文件,一个是图像分割自己用的ms,一个是张小白这次测试MobileNetV2网络所需要的ms模型。
打开链接 https://www.mindspore.cn/tutorial/lite/zh-CN/master/use/runtime_java.html 拖到最下面,可以看到“Android项目使用MindSpore Lite推理框架示例 ”这段代码,将这段代码贴进 MainActivity的class中:
Model model;
LiteSession session;
private String InitInference(Context context) {
// Load the .ms model.
model = new Model();
if (!model.loadModel(context, "mobilenetv2.ms")) {
Log.e("MS_LITE", "Load Model failed");
return "Load Model failed";
}
// Create and init config.
MSConfig msConfig = new MSConfig();
if (!msConfig.init(DeviceType.DT_CPU, 2, CpuBindMode.MID_CPU)) {
Log.e("MS_LITE", "Init context failed");
return "Init context failed";
}
// Create the MindSpore lite session.
session = new LiteSession();
if (!session.init(msConfig)) {
Log.e("MS_LITE", "Create session failed");
msConfig.free();
return "Create session failed";
}
msConfig.free();
// Compile graph.
if (!session.compileGraph(model)) {
Log.e("MS_LITE", "Compile graph failed");
model.freeBuffer();
return "Compile graph failed";
}
// Note: when use model.freeBuffer(), the model can not be compiled.
model.freeBuffer();
return "InitInference Success";
}
然后修改 前面提到的 onClickRecovery方法:
public void onClickRecovery(View view) {
if (originBitmap != null) {
Glide.with(this).load(originBitmap).into(imgPreview);
} else {
String result = InitInference(this.getApplicationContext());
result = result.substring(0,21);
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
//Toast.makeText(this, "Please select an original picture first", Toast.LENGTH_SHORT).show();
}
}
重新编译并安装到手机上。
点击recovery按钮:
居然可以在下面显示InitInference方法的结果了。
再按照教程的内容加入 DoInference和FreeInference(教程中的free,由于跟 MainActivity方法冲突,特意换了个名字)
private String DoInference(Context context) throws IOException {
// Set input tensor values.
List<MSTensor> inputs = session.getInputs();
MSTensor inTensor = inputs.get(0);
byte[] inData = readFileFromAssets(context, "model_inputs.bin");
inTensor.setData(inData);
Log.d("MS_LITE","readFileFromAssets OK!!!!!!!!!"+ inTensor.size());
// return "readFileFromAssets OK!!!!!!!!!";
// Run graph to infer results.
if (!session.runGraph()) {
Log.e("MS_LITE", "Run graph failed");
return "Run graph failed";
}
Log.d("MS_LITE","runGraph OK!!!!!!!!!");
// return "Run graph()OK";
String buffer="\n";
// Get output tensor values.
List<String> tensorNames = session.getOutputTensorNames();
Map<String, MSTensor> outputs = session.getOutputMapByTensor();
Set<Map.Entry<String, MSTensor>> entries = outputs.entrySet();
for (String tensorName : tensorNames) {
MSTensor output = outputs.get(tensorName);
if (output == null) {
Log.e("MS_LITE", "Can not find output " + tensorName);
return "Can not find output " + tensorName;
}
float[] results = output.getFloatData();
// Apply infer results.
// Log.d("MS_LITE","results... "+ results.toString());
for(int i=0;i< results.length;i++){
buffer = buffer + results + " ";
if( (i+1) % 8 == 0) buffer = buffer + "\n";
// Log.d("MS_LITE","%.f"+ results);
}
// buffer = buffer + results.toString();
}
Log.d("MS_LITE","buffer "+ buffer);
return buffer;
}
// Note: we must release the memory at the end, otherwise it will cause the memory leak.
private void FreeInference() {
session.free();
model.free();
}
并且继续在onClickRecovery增加推理调用的代码:
public void onClickRecovery(View view) {
if (originBitmap != null) {
Glide.with(this).load(originBitmap).into(imgPreview);
} else {
String result = InitInference(this.getApplicationContext());
try {
result = DoInference(this.getApplicationContext());
} catch (IOException e) {
e.printStackTrace();
}
// result = "Zhanghui Test";
result = result.substring(0,13);
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
FreeInference();
//Toast.makeText(this, "Please select an original picture first", Toast.LENGTH_SHORT).show();
}
}
而 教程中的 readFileFromAssets 方法张小白自行找了一个:
public byte[] readFileFromAssets(Context context, String fileName) throws IOException {
if (null == context || null == fileName) return null;
AssetManager am = context.getAssets();
InputStream input = am.open(fileName);
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[602112];
int len = 0;
while ((len = input.read(buffer)) != -1) {
output.write(buffer, 0, len);
}
output.close();
input.close();
return output.toByteArray();
}
下面开始测试:
可以使用Log.d在Android控制台输出日志。即便是在手机运行的情况下,Android Studio也会显示Logcat的效果:
张小白就可以轻易地将各种日志输出到AS的日志界面。当然也包括推理的结果。那么下面问题来了,Tensor的输入到底是什么呢?
张小白自己输入了若干“11111”
apk直接被crash了。。。看来如果没有好的tensor输入是不行的。。
好在有大侠提供了一个可以被正常转换的Tensor,就是588K的全1的Tensor
张小白根据自己处理的文件名,将其拷贝到 app/src/main/asserts下:
然后重新build和run安装到手机上,再点击recovery执行:
点击Recovery之后,手机屏幕上出现了一个神奇的结果。
而在Android Studio的Logcat上,也出现了令人激动的效果:
具体内容如下:
2021-02-03 14:42:39.497 7804-7804/com.mindspore.imagesegmentation D/MS_LITE: |7804|Java_com_mindspore_lite_Model_loadModel[32]|: Start Loading model
2021-02-03 14:42:39.513 7804-7804/com.mindspore.imagesegmentation W/MS_LITE: [mindspore/lite/src/model_common.cc:123] ImportFromBuffer] model version is MindSpore Lite 1.1.0, inference version is MindSpore Lite 1.0.0 not equal
2021-02-03 14:42:39.536 7804-7804/com.mindspore.imagesegmentation D/MS_LITE: readFileFromAssets OK!!!!!!!!!602112
2021-02-03 14:42:39.610 7804-7804/com.mindspore.imagesegmentation D/MS_LITE: runGraph OK!!!!!!!!!
2021-02-03 14:42:39.646 7804-7829/com.mindspore.imagesegmentation W/agesegmentatio: Reducing the number of considered missed Gc histogram windows from 173 to 100
2021-02-03 14:42:39.649 7804-7804/com.mindspore.imagesegmentation D/MS_LITE: buffer
5.316959E-4 8.1157126E-4 3.1442843E-5 1.0879105E-4 4.1746796E-4 9.381819E-5 0.016447714 0.017205147
0.08879496 0.044375964 0.0058201198 7.290559E-5 0.0013815778 7.801154E-4 0.0064813513 0.0019044834
2.2252767E-5 7.817705E-5 0.0022028144 1.8775946E-4 0.0011087313 0.0022129589 3.5608486E-5 0.0013678656
0.0024700523 0.0587411 0.0030367132 0.0030314415 8.2758494E-4 4.8635344E-4 0.0016071507 1.6779236E-4
0.0018248813 2.3086317E-5 2.2861302E-4 6.769039E-4 5.060664E-4 0.004388241 0.0010077908 6.488332E-4
3.7596258E-4 1.5979777E-4 0.0015471611 0.001477473 9.818526E-4 0.0046368716 0.033048213 0.0012080359
3.3923596E-4 0.07926178 0.0061298395 3.480988E-4 3.5623342E-4 1.9476764E-4 4.199E-4 3.5644807E-5
6.8171433E-4 0.0010183341 0.010756234 0.0019057873 5.944465E-4 0.008226985 2.4316515E-4 8.899783E-5
3.34869E-4 4.7348364E-4 7.782811E-4 5.598126E-4 1.472876E-4 0.0011236448 0.036010593 4.6915334E-4
4.2699954E-5 0.0016519583 5.5146924E-5 0.00371875 6.1608077E-4 0.024927843 5.4034506E-5 0.013328659
1.8784702E-4 0.0024711993 7.7366465E-5 4.0495805E-5 0.008612551 6.680687E-5 9.390067E-4 5.301291E-4
1.41999E-4 7.873553E-4 0.034176987 0.0023775604 8.9402765E-4 4.7897387E-4 4.3489927E-4 3.4963954E-4
8.954066E-4 6.139793E-5 9.9249606E-5 7.6620333E-4 4.381692E-4 0.0039188233 1.9596523E-4 5.9166324E-4
0.0037733659 0.001237865 5.2257534E-4 8.277095E-4 5.604754E-4 5.794706E-4 8.360341E-5 1.5439487E-4
6.2260247E-4 6.33027E-5 1.3777742E-4 0.0054231305 0.011073659 2.0620137E-4 0.0020142952 5.106029E-4
3.843124E-4 0.007338049 4.6307655E-4 2.755714E-4 0.0012273518 1.982152E-4 0.0011227187 1.447257E-4
0.0019584275 0.0034081356 9.418116E-5 0.0014891075 3.212613E-4 1.708055E-4 2.932361E-4 1.4513863E-4
3.0789158E-4 0.0032074908 0.0010307737 1.3364972E-4 4.1503555E-4 0.00356471 1.0122663E-4 6.899241E-4
1.372626E-4 0.0019129844 0.0047789537 2.5083162E-4 1.4074224E-4 8.969859E-5 1.0735894E-4 2.1454891E-4
0.0015054045 4.4526E-4 6.432085E-4 0.0018724166 0.001319308 8.4503967E-4 2.0784682E-4 3.2927605E-4
8.995776E-4 2.0187155E-4 1.3232205E-4 0.0013284828 0.0016080828 4.5678788E-4 0.09004243 0.0010020579
1.0804866E-4 0.002544322 0.0037601406 0.022555472 0.005845844 0.0027240186 0.0013476298 2.0063326E-5
9.3436195E-4 0.0012605451 0.001358962 3.1199314E-5 1.3090117E-4 4.5408113E-5 2.2712607E-4 0.027440293
3.4165696E-5 4.4441552E-4 1.3737638E-4 0.0014951156 0.0015622453 2.074641E-4 0.039215304 5.069609E-5
4.638459E-5 0.0012528414 0.0019625765 2.0016801E-4 5.6138524E-5 0.0059100124 4.071122E-4 1.2258928E-4
0.0026759428 0.0029619865 0.0010003357 0.0028447055 0.004864395 4.5173222E-4 3.4111808E-4 3.3163666E-4
2.7847162E-4 3.6637468E-4 9.249679E-4 0.0026881911 0.008341547 3.9941486E-4 7.288862E-4 1.8655046E-4
5.008062E-5 3.106339E-4 4.7387014E-4 0.001073295 3.001135E-4 0.0079701 0.0035962586 0.0027228415
0.0058531673 6.6452616E-5 7.095781E-4 0.07049619 0.0010629745 7.131929E-4 5.74112E-5 0.0334088
6.658264E-4 4.3070577E-5 0.0029400927 1.063143E-4 0.0044201887 0.0027942797 2.0022603E-4 0.0029905005
0.0011479132 0.0125309825 0.002139744 0.0035204028 1.7135984E-5 4.2074965E-4 4.1353665E-5 2.0887631E-4
0.0010897731 1.9209905E-5 4.0530926E-5 0.017882733 1.3532837E-4 4.549183E-4 1.9505217E-4 4.4926368E-5
0.0017371915 0.0061534443 0.002568177 3.645758E-4 9.437906E-5 0.0035608201 0.025376016 5.6205594E-5
5.0778565E-4 0.0014993779 3.4701053E-4 8.283897E-5 0.0018122749 0.0036839498 0.04868968 3.3331563E-4
0.0011317385 5.144476E-4 1.9313637E-4 6.159763E-4 0.009005169 0.024169147 3.215655E-5 0.0034997747
0.001337005 0.0033419633 0.0019013309 2.1257883E-4 0.0064205634 1.2273305E-4 9.755312E-4 1.5110848E-4
0.0059430124 0.0098516885 0.0017060108 5.2177416E-5 0.03256633 0.0014326915 6.5529835E-4 9.713253E-5
0.07187746 0.0026068748 2.801971E-4 0.001444967 0.007947793 1.1214088E-4 0.0010782399 5.058007E-4
1.2592367E-4 1.9942161E-4 0.0010283916 0.0014432727 6.830869E-5 0.0017316928 1.971183E-4 0.0032599866
1.3834442E-4 0.005232496 0.0015611196 0.0040574544 4.5845067E-5 2.6593092E-4 0.0071222885 0.005524
2021-02-03 14:42:39.687 7804-7889/com.mindspore.imagesegmentation D/OpenGLRenderer: disableOutlineDraw is true
2021-02-03 14:42:39.702 7804-7889/com.mindspore.imagesegmentation D/mali_winsys: EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
2021-02-03 14:42:41.248 7804-7804/com.mindspore.imagesegmentation V/AudioManager: querySoundEffectsEnabled...
2021-02-03 14:42:41.694 7804-7889/com.mindspore.imagesegmentation D/OpenGLRenderer: disableOutlineDraw is true
从上述的结果可以看出,输入的Tensor,已经经过推理过程,获得了输出的Tensor。
这就应该是变相的完成了推理的作业,虽然也不像完全是在X86上完成的推理过程,但是至少输出是显示在X86上了(当然,如果张小白Android课程再学得好一点的话,把输出显示在安卓的屏幕应该也是没问题的。。。)
(全文完,谢谢阅读)
- 点赞
- 收藏
- 关注作者
评论(0)