頭と尻尾はくれてやる!

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


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) - プログラミング入門者向けサイト


Macのクリーンインストール顛末

すでにCatalinaがリリースされてたけどまだ私のMac mini (Late 2014)はMojaveだった。

ある日のこと。
アプリ作成作業中にXcodeでビルドしたら処理が終わらない。Macが固まったのか?と思ってたらディスプレイに駐車禁止みたいなマークが表示された。

駐車禁止マーク?

↑なんだこれは?Appleのサポートページを調べると

駐車禁止マークの説明

macOSを再インストールする必要があるだと?面倒だな、、、
サポートページの通りに⌘+rで最後にインストールされてたバージョンのmacOS (Mojaveだ)がインストールされるようにしようとしたが、、、

EL Capitanインストール画面

なぜ、EL Capitan?
仮にEL Capitanをインストールしたとしてもすぐに最新のにアップデートする必要があるから、どうせならと(まだためらっていた)Catalinaをインストールしようと腹をくくった。
サポートページによると⌘+option+r。

macOS Catalinaインストール中

待つこと数時間、、、
また駐車禁止マークがでた。やばい、、、

3回ほど繰り返すもやはり駐車禁止マーク、、、


翌日になりAppleのサポートに電話。
データを消してクリーンインストールせよ!データ救出は外付けHDDにmacOSをインストールしそこから起動すればデータを取り出せるかも、とのこと。

外付けHDDを持っていなかったので近所の電気屋で1TのHDDを購入。税別7,000円しなかった。Amazonだと1Tで税込7,000円しないくらいか→ Amazonで"外付けHDD 1T"でみる

ディスクユーティリティ(もちろん⌘+option+rで見えるやつ)で消去してもフォーマットが適合しなくてできない。もしかして買ってはいけないHDDを買ってしまったの?
とか思ったが実はディスクユーティリティの左上にある表示ってとこで「すべてのデバイスを表示」として出てくる一番上のからやると消去&フォーマットができた(デフォはボリュームのみを表示になってた)。

でィスクユーティリティの画面

フォーマット後にそのHDDにCatalinaをインストール。

Catalina起動直後の画面

↑外部ディスクから起動成功。右上のが外付けHDDの起動ディスク。

この外付けHDDをTime machineの保存先にはできそうにない(ボリューム追加もしてみたが)のであきらめて普通にドラッグ、ドロップで外付けハードディスクに必要そうなデータを保存した。そういえばAppleのサポートさんもドラッグ&ドロップで、と言ってたしな。

後は元のを消去(さらっと書いてるけど心臓に悪い作業だよ)。
そしてCatalinaをインストール。

これでなんとかMacは復活した!


復活したMacに外付けHDDにある救出したデータをコピー。
その後外付けHDDは消去しTime Machineの保存先にした。
実はTime MachineってのはAppleが売り出してるバックアップ用のハードのことだと思ってた。他メーカーの外付けHDDでできるなんて知らなかった。
この程度の金額でTime Machineっていけたのか、さっさとやっておけばよかったと今更言っても仕方ない。それにしても、Time Machineのなんたる安心感。


iOS 13のショートカットで13時間後のアラームを設定する

ヨーグルトメーカーでR-1複製200回成功
↑時々記事にもしているようにウチでは頻繁にヨーグルトメーカーでヨーグルトを作っている。

いつもヨーグルトメーカー(タイマーは付いてない)に牛乳パックをセットしたら13時間後にアラームがなるようにSiriに言ってセットしている。
このアラーム設定にショートカットを使ってみようということだ。

一定時間後なら通常タイマーを使うべきなんだろうけど、iOSのタイマーは同時に2つ以上はできない。13時間の間に短いタイマー、例えばお風呂のお湯入れだったり、読書や料理などいろいろと使う。
なのでヨーグルトの13時間のだけはアラームを使う。

ところがiOSのアラームは決まった時刻で設定する。例えば6:30とか22:00とか。「現在時刻から13時間後」というような相対的な設定ではないのだ。
なのでこれをショートカットで実現するのに随分苦労したのでメモ。

(1)現在の日時を得る

最初のアクション。まずは現在の日時を得る必要がある。
「アクションを追加」タップで、

ショートカット検索画面

↑こういう画面が出てくる。どこか探ればあるのかもしれないがよくわからないので上部の検索窓で「日付」とでも入力してみよう。日時とかDateとかでもいけるかもしれない。

日付の検索結果1

↑検索結果に「日時」というのがあればそれを選択。

現在日時取得

↑これで最初のアクションはOK。


(2)13時間後を得る

日付の検索結果2

↑次のアクションも「日付」で検索すると出てくる「日付を調整」を選ぶ。

日付を調整を追加

↑その時点でこんな感じになってるはず。ここの「0 秒」を「13 時間」にしてやればOK。


(3)アラーム作成

アラーム検索結果

↑最後のアクションも検索で「アラーム」なんかで探せば見つかるであろう「アラームを作成」を選択する。

アラーム作成

↑すると自動的に「調整済みの日付」に対してのアラームになってる!別に変数をどうのこうのとする必要もない。
アラームの名称を適当なのに設定するとわかりやすい。

(4)ショートカット名

「次へ」をタップするとショートカット名が出てくるのでわかりやすいのを設定する。この文字列は自分のショートカット一覧の中でタイトルとして表示される。

以上でOK!

NFCタグを貼ったヨーグルトメーカー

↑ちなみにウチではこの処理をオートメーションで使っており、ヨーグルトメーカー上部にNFCタグを貼り付け、牛乳パックをセットしたらiPhoneを近づけるだけでアラーム設定が完了するようにした。上部の白い丸がNFCタグだ。

アラーム時のスクリーンショット

↑時間が来るとこのように表示される。何のアラームかわかりやすい😄
この文字列は(3)で指定したアラームの名称に相当する。




↑こちらがAmazonで購入したNFCタグ。中国からなので少し日数がかかったが。



iPhone XS Max
iOS 13.1.2


TensorFlowで画像の水増し時のパラーメタの検討方法

TensorFlowで学習時に画像を水増しする、というおなじみの手法。

画像の水増し方法をTensorFlowのコードから学ぶ - Qiita
TensorFlowを使った画像の水増しレシピまとめ
↑このあたりを見るとどのパラメータをいじるとどういう風に画像が変わるか、というのがざっとわかる。

自分がデータセットに使おうとするpng画像があるとして、それを水増し用処理した画像を表示するコードを紹介。
import tensorflow as tf
import numpy as np
from PIL import Image


def img_show(img) :
pil_img = Image.fromarray(np.uint8(img))
pil_img.show()


srcImg = Image.open(“lena.png")
img_show(srcImg)

if srcImg.mode == 'RGBA' :
# srcが4chの場合3chにする — (1)
rgbImg = Image.new('RGB', srcImg.size, (255, 255, 255))
rgbImg.paste(srcImg, mask=srcImg.split()[3])

elif srcImg.mode == 'RGB' :
rgbImg = srcImg

npArray = np.asarray(rgbImg)/255.0


with tf.Session() as sess :

tfImage = tf.convert_to_tensor(npArray, np.float32)


# いろいろな水増し処理
#tfImage = tf.image.adjust_brightness(tfImage, 0.4)
#tfImage = tf.image.adjust_contrast(tfImage, 1.4)
tfImage = tf.image.adjust_hue(tfImage, 0.25)
#tfImage = tf.image.adjust_saturation(tfImage, 2.0)


newNpArray = 255.0*tfImage.eval()
newNpArray = np.clip(newNpArray, 0, 255.0)
img_show(newNpArray)



(1)読み込んだ画像がアルファチャンネルを持っている場合に3chになるような処理をしている。というのもTensorFlowの水増し処理は3chでないとダメなのがあるため。

画像出力結果

↑実行すると別ウインドウで画像が表示される。


おまけ
保存して確認する場合は↓こんな感じで。
	saveImg = Image.fromarray(np.uint8(newNpArray))
saveImg.save(filePath)




TensorFlow 1.7.0-rc1
Python 3.5.2
macOS 10.14.6




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