张小白带你体验MindSpore 1.1的新特性:MindSpore Lite端侧推理的另类实现

举报
张辉 发表于 2021/02/08 01:14:10 2021/02/08
【摘要】 本文介绍了MindSpore的新特性——Lite端实现端侧推理。

本文是 https://bbs.huaweicloud.com/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。

image.png

当然,看懂了大概的意思,张小白也不会写这段 C++的代码,就把精力放在了如何用Java来实现上面。但是,即便是Java的实现,张小白也走了不小的弯路。具体的弯路过程在论坛帖子中都有描述,此处不再赘述。

我们直接说一下解题的过程:

使用Android Studio惯例打开image_segmentation这个项目( https://gitee.com/mindspore/mindspore/tree/master/model_zoo/official/lite/image_segmentation ),

在编译后run,将apk安装到华为手机上后,发现可以利用其中的 RECOVERY按钮搞事情:

image.png

因为这个按钮会触发 MainActivity.java的 onClickRecovery代码,而这个代码完全可以引入Java的推理内容。

image.png

如果你刚打开这个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按钮:

image.png

居然可以在下面显示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的效果:

image.png

张小白就可以轻易地将各种日志输出到AS的日志界面。当然也包括推理的结果。那么下面问题来了,Tensor的输入到底是什么呢?

张小白自己输入了若干“11111”

image.png

apk直接被crash了。。。看来如果没有好的tensor输入是不行的。。

好在有大侠提供了一个可以被正常转换的Tensor,就是588K的全1的Tensor

image.png

张小白根据自己处理的文件名,将其拷贝到 app/src/main/asserts下:

image.png

然后重新build和run安装到手机上,再点击recovery执行:

image.png

点击Recovery之后,手机屏幕上出现了一个神奇的结果。

而在Android Studio的Logcat上,也出现了令人激动的效果:

image.png

具体内容如下:

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课程再学得好一点的话,把输出显示在安卓的屏幕应该也是没问题的。。。)

(全文完,谢谢阅读)

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。