Pythonで機械学習を組み込んだアプリケーションを作成すると、大体scikit-learn、それでなくてもNumpyやScipyに依存することが多いです。
これらは様々なライブラリに依存しているため、Heroku上にデプロイするには一筋縄ではいきません。AWSなどで自前のサーバーがたてられる場合はそちらに立てれば良いですが、お金もかかるしHerokuでやりたい!という場合もあると思うのでそのための手法を紹介します。
Docker Container
HerokuでもDocker Containerを利用したデプロイが可能になったため、buildpackをいそいそと編集するよりもこちらを利用するほうが便利です。以下に公式のサンプルがあるため、こちらをご参考にしていただければと。
heroku-examples/python-miniconda
これでもうapt-getでいろいろインストールしたりslag sizeが大きすぎると文句を言われることもありません!
Conda buildpack
NumpyやScipyといったライブラリは普通にpip
からインストール、つまりソースコードからビルドしようとするとかなり大変です。これを回避できる、つまりコンパイル済みバイナリをインストールできるMinicondaという実行環境があるのですが、これをHeroku上でも使えるビルドパックが提供されています。
Herokuにビルドパックを設定するには、作成時に指定する方法と後で変える方法の2種類があります。
作成時に指定
heroku create --buildpack https://github.com/kennethreitz/conda-buildpack.git
後から指定
heroku config:add BUILDPACK_URL=https://github.com/kennethreitz/conda-buildpack.git
使用方法としては、condaでインストールするためのconda-requirements.txt
(condaにおけるrequirements.txt
)を用意しておくだけです。condaでは提供されていないものはpipを使ってインストールすることもできるので、pipでインストールする必要があるものは今まで通りrequirements.txt
に書いておけばOKです。
※condaでmkl最適化されたnumpy, scipyなどを使うようになって、ファイルサイズがかなり大きくなりました。これにより、Herokuのslug sizeのリミットを超えてしまうケースがあります。その場合はmkl最適化版を使わないようnomkl
をconda-requirements.txt
に加えるようにしてください(#21)。
難点としては、condaで作成する環境はvirtualenvと競合するため、併用することができない点です。そのため、Herokuでのデプロイを見据える場合は仮想環境の作成にはcondaを使っておく必要があります。condaコマンドの簡単な使い方はこちらをご参照ください。
Herokuにビルドパックを設定し、conda用の設定ファイルを用意しておく。これで機械学習系ライブラリを搭載したアプリケーションもHerokuで動かすことができます。
実際にconda-buildpackを使ってみたリポジトリを作りましたので、参考にしてください。Heroku Buttonを付けているのでそのままデプロイできます。
Heroku buildpack
こちらは私がconda-buildpack
の存在を知らなかったために作成した、通常通りpipベースでのデプロイを行うビルドパックです。
ただし、scipyのコンパイルには非常に時間がかかるため、Heroku上でタイムアウトになってしまいます(Numpyのビルドまでは通ることを確認)。これを克服するにはより良いDynoを使うしかないので、無償枠では難しいと思います。
Heroku buildpack: Python with Numpy, Scipy, scikit-learn
NumpyやScipyだけに対応しているわけではなく、そのコンパイル環境を整備するような作りになっているので、似たようなライブラリに依存しているものには汎用的に効くはずです(そうしたものはcondaで提供されていると思いますが・・・)。Herokuデプロイ時にpipがうまくいかなくてあきらめていたものがあれば、それについてもうまく動くようになるかもしれないです。
ここで使っている、Heroku環境にapt-getでライブラリをインストールできるheroku-buildpack-aptや複数のビルドパックをつなげて使えるheroku-buildpack-multiは、他のシーンでも利用できる可能性があるので覚えておくと得をするかもしれません。
heroku-buildpack-multiはbowerなどを利用している場合に使えます(Node.js用のビルドパックでbowerを処理し、その後本体用のビルドパックで処理を流す)。