Python3+Keras2のモデルをCore ML形式に変換する（2018年5月）

# TLDR

2018年5月時点で

Python3 :o: 
Keras2 :o:

変換コードはこれだけ

```
pip install coremltools
```
をした上で、

```python
import coremltools

coreml_model = coremltools.converters.keras.convert('my_keras_model.h5')
coreml_model.save('my_keras_model.mlmodel')
```
だけでできた。かなり簡単になってる（のだと思う）
ただいくつか躓いたのでまとめまちた。

# 環境
- ubuntu16.04 + nvidia-docker2 等々
- Python 3.5.5（重要？）
- coremltools (0.8)（重要）
- Keras (2.0.6)（重要）
- tensorflow (1.1.0)（重要）
- pip 9.0.1

現時点では、公式ドキュメント通りにやってもうまく行かないと思ふ。公式ドキュメントは
[github.com/apple/coremltools](https://github.com/apple/coremltools)
の docs をmakeすれば見れるっぽい（makeの仕方はこのページ下の方参照っ！）

# 変換

とりあえず成功したやり方です

## 新しいPython環境を作る

新しいPython環境を作って適切なバージョンでモジュールを揃えまつ

ここでは（yyuuさんの?）pyenv-virtualenvを使う方法を紹介
（pyenv-virtualenvの環境構築は[この記事](https://qiita.com/maskedw/items/aaa2fd7abfd493cf2820)が分かりやすかった）

```
$ mkdir convert && cd $_
$ pyenv install 3.5.5
$ pyenv virtualenv 3.5.5 coreml
$ pyenv local coreml
$ pip install coremltools==0.8
$ pip install tensorflow==1.1
$ pip install keras==2.0.6
$ pip install h5py==2.7.1
```

## 新しい環境で、再度Kerasのモデルファイルを作る。

違うPython環境で作ったモデルは、ほぼほぼ使えなさそうです。
重みファイルは使えました。

- 他の環境で作ったモデルを新しい環境で読みこもうとするとこんなエラーが出る
 
> ValueError: bad marshal data (unknown type code)


ということで、新しいPython環境のKerasでモデルを定義し直し、必要があればload_weights等を使って新しくモデルファイルを作る。

```
from keras.models import Model
from keras.layers import Geoffrey, Everest, Hinton
from keras.optimizers import Adam

inputs = Input(shape=shape, name="input")
x = inputs
x = something()(x)
outputs = x

model = Model(inputs=inputs, outputs=outputs)

# 重みデータは違うバージョンのKerasで作ったものも読み込める
model.load_weights("my_model_weights.h5", by_name=True)

# 新しいPython環境でのKerasモデルを保存
model.save('my_keras_model.h5')
```

## 新しい環境で変換

```python:convert.py
import coremltools

coreml_model = coremltools.converters.keras.convert('my_keras_model.h5')
coreml_model.save('my_keras_model.mlmodel')
```

で実行。

```
$ python convert.py
```


こんな出力がでた

>0 : input, \<keras.engine.topology.InputLayer object at 0x7f3c3387ca20\>
1 : input_permute_conv1d_19, \<keras.layers.core.Permute object at 0x7f3c338ebf60\>
2 : conv1d_19, \<keras.layers.convolutional.Conv1D object at 0x7f3c3387ca90\>
3 : activation_17, \<keras.layers.core.Activation object at 0x7f3c3387cbe0\>
：
：
22 : global_average_pooling1d_6_permute_, \<keras.layers.core.Permute object at 0x7f3c3387c160\>

無事 my_keras_model.mlmodel という、Core MLのファイルができた。

# 躓いたところ

### coremltools的に Python3.6 はNGのよう。

> ImportError: Python version mismatch: module was compiled for version 3.5, while the interpreter is running version 3.6.

- 3.5にしましょう。。。

### その他のバージョンはここを参考にしました

http://stack-overflow.ga/questions/45992720/coremltools-keras-simple-sequential-linear-regression-model-export-error-modul

- 「Keras 2.0.6 + Tensorflow 1.1 + h5py 2.7.1 がマジックコンボです！」

### Lambdaレイヤーが対応してない

> ValueError: Keras layer '\<class 'keras.layers.core.Lambda'\>' not supported.

- 気合でモデルを構成し直す。。。

### permuteは3次元しかだめ

> NotImplementedError: Supports only 3d permutation.

- いったんreshapeで3次元にして、permuteして、reshapeで2次元に戻せば問題なかった。


# ドキュメントの作り方

python2じゃないとコケる。

```
git clone https://github.com/apple/coremltools.git
cd coremltools
pyenv install 2.7.14
pyenv local 2.7.14
```

あとは公式に従って

```
pip install coremltools
pip install Sphinx==1.5.3 sphinx-rtd-theme==0.2.4 numpydoc
pip install -e git+git://github.com/michaeljones/sphinx-to-github.git#egg=sphinx-to-github
```
（Python3だと↑の3行目でこける。pip installらへんの仕方がPython2と3で違うから？）

```
cd docs
make html
```

これで、 coremltools/docs/_build/html 以下にhtmlファイルができるのでダブルクリックとかしたら見れるようになる。

# おわり

読んでくださってありがとうございますっっ

```math
\def\textlarge#1{%
  {\rm\Large #1}
}
\def\textsmall#1{%
  {\rm\scriptsize #1}
}
```

（精一杯小声で）
　　$\textsmall{よ　か　っ　た　ら　い　い　ね　く　だ　さ　い　！}$