Kerasベースの機械学習モデル(画像認識用)をiOS上で動かす手法の一つとして、coremltoolsでCoreMLベースに変換する方法があります。
この手続き、言うは易しなんですが、公式ドキュメントとかを注意深く読んでいないと色々ハマりまくるので、気づいた注意点を共有したいと思います。
#主な注意点
- バージョン環境・構築(各FWのバージョンを注意深く合わせましょう。)
- 変換関数の選択と引数(変換はできるけど動かない・・・などの事態に対する対策です。)
詳しくは以下で説明します。
#その1:バージョン・環境
※超重要です。互換性がないバージョンが組み合わさると謎のエラーに苦しめられることになります。実行する前に各バージョン番号をよく確認し、入れ替え作業をしましょう。
※現時点でcoremltools4.X系がリリースされているようです。こちらの確認は追ってやりたいと思っています。本記事では3.X系で試行します。
- Python v3.6.9 →現時点ではTensorflowがPython3.7以降をサポートしていないようです。
- Tensorflow v1.14 →coremltools3.4ではTensorfrow2.X系はうまく動きませんでした。(サポートはされているようですが・・・現状は1.X系を強くお勧めです。)
- Keras v2.3.1
- coremltools v3.4
- Google Colab →実行環境。これはローカルのJupyter Notebookなど、何でもいいと思います。
ちなみに変換後のモデルを動作させている環境は以下の通りです。
- iOS14.2
- Xcode 12.0
###環境構築
Google Colab上でバージョンを入れ替えます。Google Colabでは"!"を先頭につけることで、コマンド実行できます。
ローカルでやる方は、普通にコマンドライン・ターミナル等で"!"を除去してpipしましょう。
!pip install tensorflow==1.14
!pip install keras==2.3.1
!pip install coremltools==3.4
また、Kerasはtf.kerasとkerasの2通りのimportが存在します。この2つは別物と考えるべきもののようです。
今回はimport kerasのパターンを使用します。
tf.kerasをimportしている場合は、後述のconvertメソッドの書き方が変わるはずです。
import keras
#その2:変換関数の選択と引数
いよいよモデル変換処理です。予めKerasで構築・学習済みモデルを変数として用意してください。
(以下の例では、target_model変数が該当します。)
import coremltools
mlmodel = coremltools.converters.keras.convert(target_model,
input_names='image',
image_input_names='image', #重要!
output_names='prediction',
image_scale=1/255) #重要!
ここでの注意点を以下に列挙します。
###coremltools.converters.keras.convert関数を使用する
coremltools.convertersモジュールには、kerasの他にtensorflowその他各機械学習FWに対応するモジュールが含まれています。
適切なモジュール・関数を選択しないと、意図通りには動きません。
ここでは、Kerasのモデルなのでcoremltools.converters.keras.convertを選択します。
###引数 image_input_namesの指定
この引数を指定することで、CoreML変換後モデルのデフォルトの入力形式が画像になります。
この引数が未指定だと、入力がMultiArrayになり取り扱いが難しくなります。
(指定する値、ここでは'image'はなんでも大丈夫だと思います。)
###引数 image_scaleの指定
回帰モデルを作成されている方で、出力値がやたらと大きな数値なって謎・・・という方、これが原因の可能性があります。
画像識別モデルを作成する場合は、画素を標準化するのが一般的かと思いますが、
学習段階でその処理を行なっている場合、coremltoolsで変換する場合も同じスケーリングを指定する必要があります。
これを指定しておかないと、SwiftのVisionフレームワーク等を使用する場合に255スケールで画像入力されてしまうようです。
#最後に
以上、タイトル通りメモ書き程度ですが、誰かの役に立てば幸いです。
もし誤りや変な記載があればご指摘いただければと思います。