如何将pytorch模型部署到安卓

如何将pytorch模型部署到安卓上

这篇文章演示如何将训练好的pytorch模型部署到安卓设备上。我也是刚开始学安卓,代码写的简单。

环境:

pytorch版本:1.10.0

模型转化

pytorch_android支持的模型是.pt模型,我们训练出来的模型是.pth。所以需要转化才可以用。先看官网上给的转化方式:

import torch
import torchvision
from torch.utils.mobile_optimizer import optimize_for_mobile

model = torchvision.models.mobilenet_v3_small(pretrained=True)
model.eval()
example = torch.rand(1, 3, 224, 224)
traced_script_module = torch.jit.trace(model, example)
optimized_traced_model = optimize_for_mobile(traced_script_module)
optimized_traced_model._save_for_lite_interpreter("app/src/main/assets/model.ptl")

这个模型在安卓对应的包:

repositories {
    jcenter()
}

dependencies {
    implementation 'org.pytorch:pytorch_android_lite:1.9.0'
    implementation 'org.pytorch:pytorch_android_torchvision:1.9.0'
}

注:pytorch_android_lite版本和转化模型用的版本要一致,不一致就会报各种错误。

目前用这种方法有点问题,我采用的另一种方法。

转化代码如下:

import torch
import torch.utils.data.distributed

# pytorch环境中
model_pth = 'model_31_0.96.pth' #模型的参数文件
mobile_pt ='model.pt' # 将模型保存为Android可以调用的文件

model = torch.load(model_pth)
model.eval() # 模型设为评估模式
device = torch.device('cpu')
model.to(device)
# 1张3通道224*224的图片
input_tensor = torch.rand(1, 3, 224, 224) # 设定输入数据格式

mobile = torch.jit.trace(model, input_tensor) # 模型转化
mobile.save(mobile_pt) # 保存文件

对应的包:

//pytorch
implementation 'org.pytorch:pytorch_android:1.10.0'
implementation 'org.pytorch:pytorch_android_torchvision:1.10.0'

定义模型文件和转化后的文件路径。

load模型。这里要注意,如果保存模型

torch.save(model,'models.pth')

加载模型则是

model=torch.load('models.pth')

如果保存模型是

torch.save(model.state_dict(),"models.pth")

加载模型则是

model.load_state_dict(torch.load('models.pth'))

定义输入数据格式。

模型转化,然后再保存模型。

安卓部署

新建项目

新建安卓项目,选择Empy Activity,然后选择Next

image-20220210142047786

然后,填写项目信息,选择安卓版本,我用的4.4,点击完成

image-20220210142213719

导入包

导入pytorch_android的包

//pytorch
implementation 'org.pytorch:pytorch_android:1.10.0'
implementation 'org.pytorch:pytorch_android_torchvision:1.10.0'

image-20220210142327206

如果有参数报错请参照我的完整的配置,代码如下:

plugins {
    id 'com.android.application'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    //pytorch
    implementation 'org.pytorch:pytorch_android:1.10.0'
    implementation 'org.pytorch:pytorch_android_torchvision:1.10.0'

}

页面文件

页面的配置如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter" />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:textSize="24sp"
        android:background="#80000000"
        android:textColor="@android:color/holo_red_light" />

</FrameLayout>

这个页面只有两个空间,一个展示图片,一个显示文字。

image-20220210142827091

模型推理

新增assets文件夹,然后将转化的模型和待测试的图片放进去。

image-20220210143351535

新增ImageNetClasses类,这个类存放类别名字。

image-20220210143105326

代码如下:

package com.example.myapplication;

public class ImageNetClasses {
    public static String[] IMAGENET_CLASSES = new String[]{
            "Black-grass",
            "Charlock",
            "Cleavers",
            "Common Chickweed",
            "Common wheat",
            "Fat Hen",
            "Loose Silky-bent",
            "Maize",
            "Scentless Mayweed",
            "Shepherds Purse",
            "Small-flowered Cranesbill",
            "Sugar beet",

    };
}

在MainActivity类中,增加模型推理的逻辑。完成代码如下:

package com.example.myapplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;

import org.pytorch.IValue;

import org.pytorch.Module;
import org.pytorch.Tensor;
import org.pytorch.torchvision.TensorImageUtils;
import org.pytorch.MemoryFormat;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Bitmap bitmap = null;
        Module module = null;
        try {
            // creating bitmap from packaged into app android asset 'image.jpg',
            // app/src/main/assets/image.jpg
            bitmap = BitmapFactory.decodeStream(getAssets().open("1.png"));
            // loading serialized torchscript module from packaged into app android asset model.pt,
            // app/src/model/assets/model.pt
            module = Module.load(assetFilePath(this, "models.pt"));
        } catch (IOException e) {
            Log.e("PytorchHelloWorld", "Error reading assets", e);
            finish();
        }

        // showing image on UI
        ImageView imageView = findViewById(R.id.image);
        imageView.setImageBitmap(bitmap);

        // preparing input tensor
        final Tensor inputTensor = TensorImageUtils.bitmapToFloat32Tensor(bitmap,
                TensorImageUtils.TORCHVISION_NORM_MEAN_RGB, TensorImageUtils.TORCHVISION_NORM_STD_RGB, MemoryFormat.CHANNELS_LAST);

        // running the model
        final Tensor outputTensor = module.forward(IValue.from(inputTensor)).toTensor();

        // getting tensor content as java array of floats
        final float[] scores = outputTensor.getDataAsFloatArray();

        // searching for the index with maximum score
        float maxScore = -Float.MAX_VALUE;
        int maxScoreIdx = -1;
        for (int i = 0; i < scores.length; i++) {
            if (scores[i] > maxScore) {
                maxScore = scores[i];
                maxScoreIdx = i;
            }
        }
        System.out.println(maxScoreIdx);
        String className = ImageNetClasses.IMAGENET_CLASSES[maxScoreIdx];

        // showing className on UI
        TextView textView = findViewById(R.id.text);
        textView.setText(className);
    }

    /**
     * Copies specified asset to the file in /files app directory and returns this file absolute path.
     *
     * @return absolute file path
     */
    public static String assetFilePath(Context context, String assetName) throws IOException {
        File file = new File(context.getFilesDir(), assetName);
        if (file.exists() && file.length() > 0) {
            return file.getAbsolutePath();
        }

        try (InputStream is = context.getAssets().open(assetName)) {
            try (OutputStream os = new FileOutputStream(file)) {
                byte[] buffer = new byte[4 * 1024];
                int read;
                while ((read = is.read(buffer)) != -1) {
                    os.write(buffer, 0, read);
                }
                os.flush();
            }
            return file.getAbsolutePath();
        }
    }
}

然后运行。

image-20220210143529635

  • 35
    点赞
  • 254
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 26
    评论
### 回答1: 要将PyTorch模型部署Android设备上,可以使用以下步骤: 1. 将PyTorch模型转换为ONNX格式。可以使用PyTorch官方提供的torch.onnx模块将模型转换为ONNX格式。 2. 使用ONNX Runtime for Android将ONNX模型部署Android设备上。可以使用ONNX Runtime for Android提供的Java API将模型加载到Android应用程序中。 3. 在Android应用程序中使用模型进行推理。可以使用Java API调用模型进行推理,并将结果返回给应用程序。 需要注意的是,在将模型部署Android设备上之前,需要确保模型的大小和计算量适合在移动设备上运行。可以使用模型压缩和量化等技术来减小模型的大小和计算量。 ### 回答2: PyTorch是一个开源的Python机器学习库,它为深度学习提供了强大的支持。PyTorch模型可以在计算机上进行训练和调试,但当我们需要将模型部署到移动设备(如Android)上时,我们需要将PyTorch模型转换并集成到移动应用程序中,这需要一系列的步骤。 首先,我们需要将PyTorch模型转换为TorchScript格式,这是一种在移动设备上运行的地图。使用TorchScript脚本将PyTorch模型序列化为可运行的形式,它可以在没有Python运行时进行部署。我们可以使用以下代码将PyTorch模型转换为TorchScript格式: ``` import torch import torchvision # load the PyTorch model model = torchvision.models.resnet18(pretrained=True) # set the model to evaluation mode model.eval() # trace the model to generate a TorchScript traced_model = torch.jit.trace(model, torch.randn(1, 3, 224, 224)) ``` 上面的代码将一个预训练的ResNet模型转换为TorchScript格式,现在我们可以将其保存到文件中以备以后使用: ``` traced_model.save('resnet18_model.pt') ``` 接下来,我们需要将TorchScript模型集成到Android应用程序中。我们可以使用Android Studio提供的Android Neural Networks API(NNAPI)来加速我们的深度学习推理。NNAPI是一个Google开发的Android框架,它提供了一些API,可以加速计算机视觉和自然语言处理应用程序中的神经网络推理。我们可以在Gradle文件中添加以下代码,以添加NNAPI支持: ``` dependencies { implementation 'org.pytorch:pytorch_android:1.7.0' implementation 'org.pytorch:pytorch_android_torchvision:1.7.0' } ``` 然后将TorchScript模型文件复制到Android项目中的`assets`文件夹中。 最后,我们需要编写代码将TorchScript模型加载到我们的应用程序中,并使用它来进行推理。下面是一个简单的Android应用程序,可以使用加载的TorchScript模型对图像进行分类: ```java import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.widget.ImageView; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import org.pytorch.IValue; import org.pytorch.Module; import org.pytorch.Tensor; public class MainActivity extends AppCompatActivity { private TextView mResultTextView; private ImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mResultTextView = findViewById(R.id.result_text_view); mImageView = findViewById(R.id.image_view); // Load the TorchScript model from the assets folder Module module = Module.load(assetFilePath(this, "resnet18_model.pt")); // Load the image and convert it to a PyTorch Tensor Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.test_image); float[] mean = new float[]{0.485f, 0.456f, 0.406f}; float[] std = new float[]{0.229f, 0.224f, 0.225f}; Tensor inputTensor = TensorImageUtils.bitmapToFloat32Tensor(bitmap, mean, std); // Run the input through the model IValue outputTensor = module.forward(IValue.from(inputTensor)); // Get the predicted class index from the output Tensor float[] scores = outputTensor.toTensor().getDataAsFloatArray(); int predictedIndex = -1; float maxScore = 0.0f; for (int i = 0; i < scores.length; i++) { if (scores[i] > maxScore) { predictedIndex = i; maxScore = scores[i]; } } // Display the result String[] classNames = {"cat", "dog", "fish", "horse", "spider"}; mResultTextView.setText("Prediction: " + classNames[predictedIndex]); mImageView.setImageBitmap(bitmap); } public static String assetFilePath(Context context, String assetName) { File file = new File(context.getFilesDir(), assetName); try (InputStream is = context.getAssets().open(assetName)) { try (OutputStream os = new FileOutputStream(file)) { byte[] buffer = new byte[4 * 1024]; int read; while ((read = is.read(buffer)) != -1) { os.write(buffer, 0, read); } os.flush(); } return file.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); } return null; } } ``` 上面的代码将载入从`assets`文件夹中加载的TorchScript模型,为它准备好图像数据,并将其运行给模型模型返回一个输出张量,我们得到预测的类别。 总之,将PyTorch模型部署Android可以通过转换为TorchScript格式,集成到Android应用程序中,以及编写可以使用它进行推理的代码来实现。厂商和第三方可用工具也可以帮助简化部署过程。 ### 回答3: 在让PyTorch模型部署Android设备之前,你需要确保你的模型可用且现在运行良好。这涉及到以下步骤: 1. 在PyTorch中定义并训练模型 首先在PyTorch中定义并训练模型。你需要训练一个模型,这个模型可以处理你希望在移动设备上使用的数据。你需要确保在训练模型时,使用了适当的数据预处理和清理过程。然后,导出模型以便在Android设备上使用。 2. 将PyTorch模型转换为TorchScript格式 将训练好的PyTorch模型转化成TorchScript格式,这是 PyTorch模型导出方面提供的一种功能强大的框架。你可以使用 torch.jit.load() 函数来加载 TorchScript 模型,并在移动设备上使用它。你可以使用torchscript_builder.py 脚本来转换 PyTorch 模型,这个脚本也可以根据你的需要在运行时执行转换。 3. 集成模型Android应用中: Android应用可以使用自己的Java代码,但也可以使用C++接口以及原生代码。所以,集成模型Android 应用可以使用两种方式: Java 接口和 C++ 接口。 3.1 Java 接口 Java 接口可以用于创建用 Java 编写的 Android 应用程序。以下是使用 Java 接口加载 TorchScript 模型的步骤: - 创建一个 Android 应用程序项目。 - 在 Android Studio 中安装 PyTorch 的 Gradle 插件。 - 将 torch-android 库和 pytorch_android 库添加到项目中的 build.gradle 文件中。 - 在代码中使用 TorchScript 加载模型,并使用该程序的 Android 功能来运行。 3.2 C++ 接口 使用 C++ 接口可以创建用 C++ 编写的 Android 应用程序。以下是使用 C++ 接口加载 TorchScript 模型的步骤: - 创建一个 Android 应用程序项目。 - 编写 C++ 代码来加载 TorchScript 模型。 - 在 Android Studio 中创建一个 Android.mk 文件和 Application.mk 文件。 - 将 C++ 代码编译成共享库,然后将共享库打包到 Android 应用程序 APK 文件中。 - 在代码中使用 TorchScript 加载模型,并调用 C++ 程序的 Android 功能来运行。 以上是部署 PyTorch 模型Android 设备的步骤和过程。在集成模型Android 应用中时,需要注意处理异常和各种错误,确保模型可以在 Android 设备上成功加载。
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI浩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值