深度学习移动端部署方案 --- MNN端侧推理引擎

  • MNN简介及应用场景

    • 一个轻量级的深度学习端侧推理引擎,核心解决深度神经网络模型在端侧推理运行问题,涵盖深度神经网络模型的优化、转换和推理。
    • MNN为提供面向不同业务算法场景,不同训练框架,不同部署环境的简单、高效、安全的端侧推理引擎 MNN 。能够抹平 Android 和 iOS 的差异,碎片设备之间的差异,不同训练框架的差异,实现快速的在端侧部署运行,并且能够根据业务模型进行 OP 灵活添加和 CPU/GPU 等异构设备深入性能优化。
  • 深度学习模型应用流程:

    • 模型训练---->模型导出----->模型转换------>在线部署----->在线推理预测
    • MNN主要用来解决模型转换, 在线部署和推理这几个阶段(虽然MNN也在逐步提供模型训练一站式方案)
  • Pytorch应用示例

    • 模型离线训练

    • 导出模型

      • MNN不直接支持Pytorch(直接支持的框架:TensorFlow,Caffe),但支持ONNX标准格式与MNN交流,Pytorch里使用torch.onnx.export接口导出ONNX格式的模型文件
      def save_model(m, loss, base_name, all_model=False):
          save_path = r'/home/hc/trainned_weight_params'
          model_name = str(type(m))
          name = '%s/%s_epoch%d_loss%.4f.pth' \
                 % (save_path, base_name, epoch_num, loss)
          name_onnx = name + '.onnx'
          print('>>>save model:', model_name, name)
          if all_model:
              torch.save(m, name)
          else:
              torch.save(m.state_dict(), name)
              # create the right input shape
              m_input_data = torch.randn(1, 4)
              # switch pytorch model to onnx model
              torch.onnx.export(m, m_input_data, name_onnx, verbose=True)
      
    • 模型转换

      • 使用MNN提供的onnx模型转换工具就可以转换成MNN可以解析的模型文件
      • 官方文档: https://github.com/alibaba/MNN/blob/master/tools/converter/README.md
      ./MNNConvert --framework ONNX --modelFile pfld-lite.onnx --MNNModel pfld-lite.mnn --bizCode MNN
      
    • 模型部署

      • 使用MNN API加载模型和相关配置,然后设置输入和输出

      • 示例代码(4输入3输出):

         // load model and set config (work thread num and platform
        auto ALSnet = MNN::Interpreter::createFromFile((const char*)model_path);
        MNN::ScheduleConfig netConfig;
        netConfig.type = MNN_FORWARD_CPU;
        netConfig.numThread = 4;
        
        // set model precison
        MNN::BackendConfig backendConfig;
        backendConfig.precision = MNN::BackendConfig::Precision_High;
        netConfig.backendConfig = &backendConfig;
        auto session = ALSnet->createSession(netConfig);
        auto inputTensor = ALSnet->getSessionInput(session, NULL);
        auto net_input_data = inputTensor->host<float>();
        
        // get input data
        net_input_data[0] = block_r[round] / (pixel_cnt / 4);
        net_input_data[1] = block_g[round] / (pixel_cnt / 4);
        net_input_data[2] = block_b[round] / (pixel_cnt / 4);
        // run session
        {
        	ALSnet->runSession(session);
        }
        // get output data
        auto outputTensor = ALSnet->getSessionOutput(session, NULL);
        predDiff[round].r = outputTensor->host<float>()[0];
        predDiff[round].g = outputTensor->host<float>()[1];
        predDiff[round].b = outputTensor->host<float>()[2];
        

猜你喜欢

转载自blog.csdn.net/hechao3225/article/details/114820905