頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


TensorFlow2.0の学習結果を.h5→.pb→.mlmodelと変換してiOSで使う

やりたいことは、TensorFlow 2.0 + Kerasで学習させた結果をiOSで使いたい。
iOSで係数だけをもらうことも可能(※1)だが、mlmodel形式だと一番使いやすいのでベスト。

度重なる試行錯誤の結果、自分の場合はこれでいけた、というのをシェア。


TensorFlow 2.0で学習し、その結果を.h5ファイルで保存する。

virtualenvでTensorFlow 1.14.0の環境を作成、そこで
(1).h5ファイルを.pbファイルに変換
(2)その.pbファイルを.mlmodelに変換
これでiOSでVision/CoreMLを使いすんなりと予測ができた。


(1).h5→.pbの変換
Deep Learningアプリケーション開発 (2) TensorFlow with Python - Qiita
.h5→.pbの変換は↑こちらのページにある通り。ただ感謝、感謝!

(2).pb→.mlmodelの変換
上記リンク内の通りに動かすと.pbファイルができる。同じフォルダに.jsonファイルも生成されて、そこを見て入出力の名前を確認しておく必要がある。確かにKerasで自分で付けた名前と違っていた。
後はtfcoremlを使って以下のようにして変換。
import tfcoreml as tf_converter

classLabels = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15']

tf_converter.convert(tf_model_path = PbFilePath,
mlmodel_path = MlmodelFilePath,
output_feature_names = ['y_out/Softmax:0'],
input_name_shape_dict = {'x_input:0':[1, height, width, 3]},
image_input_names = ['x_input:0'],
class_labels = classLabels,
image_scale = 1.0/255.0
)
なお、この2回の変換はTensorFlow 2.0だとすんなり動かず、、、私には書き換えられそうにないので諦めました。この変換だけ1.14.0で実行することにします。





以下は背景とか。

当初は、
Kerasでの学習結果をmlmodelにしてiOSで使う

ここに書いた方法の.h5ファイルを.mlmodelに変換、updateする、でなんとかなると思っていた。
MNIST(白黒、畳み込みなし)で検証していけることを確認したのだが、、、

いざ本番(※2)の学習結果を同様にやろうとしたらupdateがうまくいかない。一応保存まではするんだが、
RuntimeWarning: You will not be able to run predict() on this Core ML model. Underlying exception message was: Error compiling model: "compiler error: Espresso exception: "Invalid argument": generic_reshape_kernel: Invalid bottom shape (32 8 2 1 1) for reshape to (20480 -1 1 1 1)".
RuntimeWarning)

なんて警告が出る。
途中での計算がうまくいってないんだろうか?MNISTは畳み込みを使っていないモデル、白黒画像を入力だったが、今回は畳み込みあり、カラー画像入力というように多少異なる。そのあたりに起因するcoremltoolsのバグなのかなんなのか、、、?
試しにXcodeで使おうとしても、

Xcodeでのエラーメッセージ

↑同じエラーが表示されビルドできなかった。






※1
係数だけ出力してiOSでそれを読み込む、というのもやったことあるが、iOS内でニューラルネットを構成して係数を読み込んで、、、とか記述が膨大。一度mlmodelを味わうともうやってられない。

※2
個体値カメラ
↑先日リリースしたこのポケモンGO用の個体値チェックアプリではバーの部分の画像(カラー)を入力画像として予測している。リリース版ではTensorFlow 1.14を使っていたが、macOSの破損→クリーンインストールを機に、TensorFlow 2.0 + Kerasで学習させ、その結果をiOSで使えるようにしたいのだ。
スポンサーサイト






iOSアプリ「個体値カメラ」のリジェクト対応

iOSアプリ「個体値カメラ」をリリースしました(ポケモンGO用)
↑今回リリースした「個体値カメラ」というiOSアプリは4回リジェクトされたのでその辺りの対応を情報共有します。

上記リンクにあるデモ動画のように、ポケモンGOアプリを表示してるiOSデバイスを別なiOSデバイスのカメラでポケモンの個体値を表示するアプリ、です。
審査する方も勘違いするかもなあ?ってややこしさかもしれません。



(その1)
Guideline 2.3.4 - Performance - Accurate Metadata

Guideline 4.1 - Design - Copycats

Guideline 4.2.3 - Design - Minimum Functionality

↑最初のリジェクトは3項目ありました。
詳細は省きますが、どれもreviewerの勘違いです。App preview内に手が写っているとかアプリがポケモンGOに似た画像を使っている、とか。
なので再度申請ではなく、App Store Connect内で説明を書いて返信。
このやりとりにはファイルを添付できるので、ポケモンGOのスクショを2枚添付して、添付画像に対してこのアプリを使ってみて!とアピール。

すると返信してから数時間後に
「よお!審査に少し時間がかかるで」
みたいな返事と共に、アプリのstatusは In Review(審査中)に変わりました。



(その2)

Guidelines 2.3.7 - Performance - Accurate Metadata
それからおよそ8日後に2度目のリジェクト。
「タイトル、サブタイトルに”Pokémon GO”なんて使ったらあかんやろ?!」
とのこと。

2.3.7の一部を引用すると
2.3.7 独自性のあるApp名を選び、Appを正確に説明するキーワードを割り当ててください。App Storeのシステムを悪用する目的で、メタデータに商標登録用語、人気のApp名、その他無関係のフレーズを含めることはできません。

当初のアプリ名称は
IVs Camera for Pokémon GO
個体値カメラ for ポケモンGO(日本語版)
でした。
こういう特定のアプリに関連するアプリだとアプリ名にfor ポケモンGOとか付けたくなるし、実際そういうアプリがストアにたくさん並んでいます。
それらがこのガイドラインが無い頃に審査が通過したのか、reviewerが見逃したのか、もしくは"悪用ではない"と判断したのか分かりませんが文句を言っても仕方ないので、泣く泣くタイトルを
IVs Camera
個体値カメラ(日本語版)
↑このように変更しました。なんのアプリかよくわからないですね。
アプリ名をアプリ内で表示していたのでアプリのバージョンを1.0.1とし再度アーカイブ、再申請しました。



(その3)
5.1.1 Legal: Privacy - Data Collection and Storage
3度目のリジェクトの指摘は
「カメラの使用目的をはっきり記述せえや!」
とのこと。
プライバシー関連で、カメラなどを使うアプリだとInfo.plistに記述する必要があるわけだが、、、それが
This app uses the camera
このアプリはカメラを使います(日本語版)
↑みたいな記述でした、多分。

5.1.1 (ii)許可
必ず、「目的」でデータの用途を明確かつ十分に説明してください。
↑一部だけどそういうことなんだろう。確かに不十分だったな、ということで、、、

This app uses the camera to see the image of Pokémon GO app.
このアプリはポケモンGOアプリの画像を得るためにカメラを使用します。(日本語版)
に変更しました。

また、5.1.1を読んでて気付いたのですが、

5.1.1 データの収集および保存
(i)プライバシーポリシー:すべてのAppには、App Store Connectのメタデータフィールドと各App内にアクセスしやすい形で、プライバシーポリシーへのリンクを必ず含める必要があります。プライバシーポリシーはわかりやすく明確なものである必要があります。
↑App内にプライバシーポリシーへのリンクが必須、とある。知らなかった、、、
ずっと自分のアプリ紹介サイトにプライバシーポリシーを記述し、申請時にそのリンクを入力することで済まして他のだが。
こりゃまずいかも、と思いアプリ内にプライバシーポリシーを記述しました。
これを1.0.2として再提出。



(その4)
Guideline 2.3.3 - Performance - Accurate Metadata
2.3.3 スクリーンショットは、単なるタイトル画面、ログインページ、スプラッシュ画面ではなく、Appにおける実際の画面を写したものである必要があります。(以下略)

「スクショが使用状況を反映してへんやろ!」という指摘、、、
そう、最初のApp previewと同じ勘違い。

reviewerの指摘内容がアレなので面白いのだが書くのも悪いのでやめとこう。
最初と同じようにテキストでやりとり。
私「スクショは使用時に撮影したものです」

reviewer「情報おおきにな!再提出したアプリの審査をするの、楽しみにしてるで!」

私「ほんとに使ってる時に撮影したものです」

みたいなやりとり後、、、

突然アプリのstatusは配信準備完了(Ready for Sale)に変わったのでした!


そんなわけで案外reviewerの勘違いもある、とか何か参考になれば幸いです。



おまけ
今回、App preview内およびスクリーンショットでポケモンGOの画面をぼかしています。

Appプレビュー - App Store - Apple Developer
掲載する権利がある素材だけを使用してください。
↑このような記載があったから。
今回のアプリの場合、そのままポケモンGO画面を使用しても著作権的には”引用”ってことで問題はないような気もしますが、Appleのサイトに上記のように書いてるし、引用ならOKってのが世界共通なのか知らないし他の法律に引っかかるかもしれないし、、、ってことで安全側にしてぼかしときました。ポケモンGOユーザーならどの画面かわかるだろうし。



参考
App Store Reviewガイドライン - Apple Developer



coremltoolsでKerasでの学習結果をmlmodelにconvertしたい

Kerasでの学習結果をmlmodelにしてiOSで使う
↑これを書きながら、.h5ファイルの出力まではTensorFlow2.0でやって、.h5ファイルを読み込んでconvertするところは別にTensorflow 1.xでもいいのでは?と思ったので試してみた。

pyenv envTF1
として環境を作成しそこでTensorFlow 1.14などをインストールしてみた
(envTF1) pip install tensorflow==1.14.0 coremltools

coremltoolsは3.1
import coremltools
coreml_model = coremltools.converters.keras.convert(H5FilePath,
以下略
これを実行するも
AttributeError: module 'coremltools.converters.keras' has no attribute 'convert'
↑こういうエラーが出る。

AttributeError: module 'coremltools.converters.keras' has no attribute 'convert' · Issue #266 · apple/coremltools · GitHub
↑standalone Kerasが必要というのをみたので

(envTF1) pip install keras==2.2.4
でKerasをインストール。

先ほどのコードに
Import keras
を追加して実行すると、、、

ValueError: Unknown initializer: GlorotUniform
↑エラーメッセージが変わったのだが、、、

このエラーは消せなかった。挫折。

以上がPython 3.7.4の話。
試しに元々インストールしてたPython 3.5.2があったのでそれでも試してみたが同様にダメだった。

結局tfcoremlで頑張るわ、、、orz



Kerasでの学習結果をmlmodelにしてiOSで使う

タイトル通りKerasで学習させ、その結果をmlmodelファイルで得て、それをiOSで使いたい。その変換に恐ろしく苦労した。

Python version 3.7.4
TensorFlow version 2.0.0
tf.keras version 2.2.4-tf
macOS Catalina 10.15.1

↑という環境。
自作のデータセットでMNISTをやってみた。

学習結果を
model.save(H5FilePath)
てな感じで.h5ファイルとして保存。まあここまではOK。

次にこの.h5ファイルを変換する。

GitHub - apple/coremltools: Core ML Community Tools.
Python3+Keras2のモデルをCore ML形式に変換する(2018年5月) - Qiita
Core MLモデルの入力の型をMLMultiArrayから画像(CVPixelBuffer)に変更する - Qiita

↑この辺りを参考にcoremltoolsを使いやってみたものの、、、できない。
AttributeError: module 'coremltools.converters.keras' has no attribute 'convert'
とか。
公式通りvirtualenv使ったり、Kerasをインストール(tf.kerasじゃダメ!って見たので)したり、Pythonのバージョンを3.5にしてみたり。
まあいろいろやってみたんだけど俺にはできなかった。

TensorFlowのバージョンを1.xに下げるといいともあったが、これは最後の手段ということで模索し続けた。


結局のところ、使ったのはtfcoremlだ、、、何?この敗北感。
import tfcoreml # 1.1

model = tfcoreml.convert(H5FilePath,
input_name_shape_dict={'x_input': (1, 28, 28, 1)},
output_feature_names=['Identity'],
image_scale = 1.0/255.0,
minimum_ios_deployment_target='13'
#(※1)
)

model.save(MlmodelFilePath)
↑これでやっと.mlmodelが出力された!
と喜んだのも束の間、iOSで使おうとすると

let vnmodel = try VNCoreMLModel(for: weights().model)
↑ここで落ちる。modelを作成自体できなかった。

さらに調べると
coremltools 3.1の環境構築(2019年11月版) - Qiita
↑mlmodelを修正というかupdateするなんてできるそうだ。

試してみたところ、確かにmlmodelの入力の形式が

Xcodeでmlmodelを見た結果1
↑MultiArray (Double 1 x 28 x 28 x 1) だったのが、、、

Xcodeでmlmodelを見た結果2
↑Image (Grayscale 28 x 28)に変わった。

これをiOSで使うとなんとか予測の計算はできた。

ただ、mlmodelの出力形式がMultiArray (Double)なので(Kerasの出力がsoftmax関数なので)、自分でどのラベルに該当するか処理を記述必要がある。VNClassificationObservationは使えず、VNCoreMLFeatureValueObservationからMLMultiArrayの中身を調べて最大なのを探すとか。
出力形式もupdateしたかったがやり方がわからなかった。

※1のところで
image_input_names = ['x_input’],
class_labels = classLabels,
などが指定できたらいいのだけど、できなかった。


macOS CatalinaにPython/TensorFlowをインストール

Macのクリーンインストール顛末
↑意図せずMacをクリーンインストールする羽目になったので、PythonやTensorFlowをまた使えるようにすることになった。

まずはPythonの設定から。

HomebrewのインストールからpyenvでPythonのAnaconda環境構築までメモ - Qiita
↑こちらの記事がとても参考になった。ありがとう!

Homebrewは公式サイトの通りでok(FFmpegをインストールするために入れてた)。

brew install pyenv
でpyenvをインストール。
Catalinaはbashじゃなくzshなので
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
とする。

pyenv install -l
で見ると

pyenv install -lの結果

↑ずらーっと表示されるのだが、anacondaが欲しかったので3で新しいのを、ってことで

pyenv install anaconda3-2019.10

でインストール。


ずっとPythonはXcodeで動かしてたのでその設定をする。

【開発環境】XcodeでPython【画面遷移あり】 - Qiita
頭と尻尾はくれてやる! Python3をXcodeで
などを見ながら設定。

次にTensorFlow。今は2.0が最新みたい。
インストールの方法を調べるもよくわからないから
TensorFlow
↑公式サイトにある通りに
pip install tensorflow
した。


XcodeでPythonを動かした結果

↑無事XcodeでPython3、TensorFlowが動いてるようだ。



参考ページ
pyenvを使ってMacにPythonの環境を構築する - Qiita
【Python入門】virtualenvで仮想環境を作ろう | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.