Mac で pyenv / pipenv の環境を作って keras 動かすところまでのメモ

tensorflow.js で遊んでたら keras でモデルを作って import してみましょうみたいな章に差し掛かったので、python の環境構築した。

TensorFlow.js tutorials - import-keras

環境構築

keras ついでに pyre を試してみたいので、 pyre で keras が書ける、というところをゴールにした。

pipenv は ruby の bundler みたいな体験を目指して入れてみた。

ググってみると Mac で Anaconda は地雷みたいな意見が多かったので、とりあえず homebrew から pyenv と pipenv を入れて、pyenv から python を管理することにした。

brew install pyenv
brew install pipenv

.bash_profile などに環境変数の設定

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

自分は POSIX 非互換の fish を使ってるので ~/.config/fish/config.fish に以下を追記

set PATH $HOME/.pyenv/shims $PATH
eval (pyenv init - | source)

ここで、 xcode-select --install して、 pyenv install 3.7.0 とすれば python が入るらしいが、自分の環境では次の記事と同じ問題が起きた。

pyenv install 3.6.6 でエラーが発生する。 – digitalnauts – Medium

おそらくだが、自分が homebrow を ~/brew にインストールしている関係で、python-build が期待してる環境変数からずれてしまってそう。

結論から言うと、上記の記事と同じように、色々と環境変数で渡すとビルドが成功した

# python 3.6/3.7 install

$ CFLAGS="-I$(brew --prefix readline)/include -I$(brew --prefix openssl)/include -I$(xcrun --show-sdk-path)/usr/include" \
LDFLAGS="-L$(brew --prefix readline)/lib -L$(brew --prefix openssl)/lib" \
PYTHON_CONFIGURE_OPTS=--enable-unicode=ucs2 \
pyenv install -v 3.6.6

$ CFLAGS="-I$(brew --prefix readline)/include -I$(brew --prefix openssl)/include -I$(xcrun --show-sdk-path)/usr/include" \
LDFLAGS="-L$(brew --prefix readline)/lib -L$(brew --prefix openssl)/lib" \
PYTHON_CONFIGURE_OPTS=--enable-unicode=ucs2 \
pyenv install -v 3.7.0

keras 起動まで

3.6 と 3.7 を入れた理由だが、 python 3.7 で async が予約語になった関係で、 tensorflow のコード中にある async 変数でパースエラーになる。なので python 3.6 を使う必要がある。

Unable to install TensorFlow on Python3.7 with pip · Issue #20444 · tensorflow/tensorflow

$ mkdir try-keras
$ cd try-keras
$ pipenv --python 3.6
$ pipenv install tensorflow
$ pipenv install keras
$ pipenv shell
$ python --version # => 3.6.6

コードを書く

src/hello-keras.py

from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
$ python src/hello-keras.py

Using TensorFlow backend.
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz
11493376/11490434 [==============================] - 6s 1us/step

動いた。

pyre-check を動かしてみる

Python 3 系は型の構文が予約されてるが、処理系にバリデータがあるわけではない。

その Type Checker の実装に mypy と pyre がある。 JS の flow と同じ作者の雰囲気を感じるので、今回は pyre を使った。

$ pip3 install pyre-check

$ mkdir try-pyre
$ cd try-pyre
$ pyre init

$ mkdir src
$ vim src/hello-pyre.py # type your code
$ pyre --source-directory src check

 ƛ Setting up a .pyre_configuration file may reduce overhead.
 ƛ Found 1 type error!
src/test.py:2:4 Incompatible return type [7]: Expected `int` but got `str`.

自分で書くコードに型をつけるには便利だが…

keras で使うと import path を知らないと言ってくるのを、だまらせる設定が必要だった。

こうするとさっきのコードに pyre-check が通る。

from keras.datasets import mnist  # pyre-ignore
(x_train, y_train), (x_test, y_test) = mnist.load_data()  # pyre-ignore
print(x_train)

結構だるい。mypy は 知らないモジュールの import を無視するオプションがあるらしいが、 pyre にはない。

(facebook はたぶん pytorch 使ってるんだろう…)

環境 & エディタ

vscodepython を開くと vscode が yapf を有効化する?ってきいてきたので、yes にしたら勝手にフォーマットされるようになった。便利

終わり

本記事と関係ないけど最初は Python でプログラミングを覚えたが、就活の頃(2012 年頃)全く python の仕事がなかったのと 2 系と 3 系の移行期で混乱していたので、 Node.js/JavaScript に切り替えた記憶がある。

昔も同じように環境構築で苦しんだ記憶があるが、その体験はあまり変わっていない。