概要
既存のJava製AndroidネイティブアプリにPyTorchベースの推論処理を実装する必要があったので、備忘として調べた結果をまとめます。
- PyTorch Java APIで推論処理を記述する
- Python(Chaquopy)で記述した推論処理を呼び出す(本記事)
環境
ハードウェア: SHARP SH-T01
プロセッサ: Snapdragon 665 (2GHz & 1.8GHz - Octa)
メモリ: 4GB
OS: Android 12
推論実行方法
推論処理をJavaやC++で書き直すのは大変なので、Pythonで書いた処理をそのまま使いたいという場合、ライブラリ(Chaquopy)を使ってJavaからPythonスクリプトを呼び出すことができます。
※KivyなどAndroidアプリ全体をPythonで開発するためのライブラリはいくつかありますが、一部の処理のみをPythonで記述するライブラリは執筆時点(2022/09)でおそらくChaquopyだけかと思います。
雑ではありますが、本記事ではmatplotlibを呼び出す公式のデモを元に推論処理を呼び出します。
前準備
- AndroidManifest.xmlの更新
学習済みのmodelのダウンロードにインターネットへのアクセスが必要になるため、下記を追加します。パーミッションが足りていないと、URLError: <urlopen error [Errno 7] No address associated with hostname>
のエラーが発生します。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- 依存関係の追加
python {
pip {
install "torch==1.8.1"
install "torchvision==0.9.1"
}
}
推論処理
chaquopy-matplotlib/app/src/main/python
配下に以下のスクリプトを追加します。適当なinputに対するforwardの結果を出力します。
import torch
import torchvision
def forward():
model = torchvision.models.mobilenet_v3_small(pretrained=True)
model.eval()
value = model.forward(torch.rand(1, 3, 224, 224))
print(value)
推論呼び出し
MainActivity.kt
を下記の通り書き換えます。アプリを起動し、plotボタンを押下すると推論の結果がLogcatに表示されます。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (! Python.isStarted()) {
Python.start(AndroidPlatform(this))
}
val py = Python.getInstance()
// 以下書き換え
val module = py.getModule("inference") // スクリプト名
findViewById<Button>(R.id.button).setOnClickListener {
try {
module.callAttr("forward") // 関数名
} catch (e: PyException) {
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
}
}
}
}
備考
Chaquopyを使う場合、下記の事項に留意する必要があります。
- 対応しているPythonやライブラリのバージョンが最新ではない
- 主要なライブラリはカバーされているものの、対応していないライブラリがある
In our most recent tests, Chaquopy could install over 90% of the top 1000 packages on PyPI.
Java製Androidネイティブアプリへの追加という制約を考えなければ、Androidアプリ自体をPythonで開発し、そのままPythonで推論を記述することが可能かもしれません。