Python + scikit-learn + Django で機械学習を利用したツールを作る

過去のデータから未来の数値を予測するちょっとしたツールを社内向けに作りました。単に学習済のモデルを使って予測値とグラフを表示するだけなら [Jupyter Notebook](http://jupyter.org/) でも良いのですが、非プログラマーが想定ユーザーだったので Web アプリケーションにしました。この方がユーザーとって不要な Python のコードが表示されませんし、データの追加・修正を安全に行うことができます。

## 仕様など

社内用のツールなので詳細は伏せますが、今回作るのは過去のデータから未来のデータを予測し、数値とグラフを表示します。過去データは手動で入力し、バッチ処理により学習と予測を行います。想定ユーザーは社内で1名のみ。予測結果は今後のユーザーが業務上で意思決定を行うときに参考データのひとつとして利用されます。

バージョンは下記の通りです。

```bash
$ python --version
Python 3.6.2 :: Anaconda, Inc.
$ pip --version
pip 9.0.1 from /root/.pyenv/versions/anaconda3-5.0.0/lib/python3.6/site-packages (python 3.6)
$ python -m pip list | grep Django
Django (1.11.7)
$ python -m pip list | grep scikit-learn
scikit-learn (0.19.0)
```

## Django

すべて Python で書きたかったので、 Python の Web フレームワークを選びました。また、マイグレーションツールや OR マッパーもあるとサクッと DB まわりの処理を書けるので、 Django を選びました。 Django には公式のチュートリアルがあるので、まずはそれをやってみました。 Web フレームワーク特有の用語が頻出するので、まったくの初心者には読みにくい内容になっていますが、 Ruby on Rails などの他のフレームワークを使ったことのある人にとっては逆にテンポよく進められるので、とてもいい教材です。日本語版もあります。

[さぁ始めましょう。 \| Django documentation \| Django](https://docs.djangoproject.com/ja/1.11/intro/)

## scikit-learn

scikit-learn は機械学習ライブラリのデファクトスタンダードです。これの使い方を覚えるだけで、機械学習の前処理、学習、評価、チューニングなどを一通りできる、にわか機械学習エンジニアになれます。ディープラーニングをがっつりやるなら、これに加えて TensorFlow や Keras などが必要になってくるかと思いますが、今回は線形回帰などのシンプルなモデリング手法の方が相性が良かったので、 scikit-learn 単体で使いました。本当にびっくるするくらい簡単にモデルを構築できます。

[O'Reilly Japan \- Pythonではじめる機械学習](https://www.oreilly.co.jp/books/9784873117980/)

## フロントエンド

グラフの表示には [Chart.js](http://www.chartjs.org/) を使いました。シンプルなのでサクッとグラフを書くには最適です。あとは Bootstrap で適当に見た目を整えます。

```html
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
});
</script>
```

## バッチ処理

過去データを使った学習と予測はバッチ処理で定期的に実行します。一方で DB にある実績データを触って予測結果を保存したいので、 Django のコンテキスト上で実行したいです。 Django にはカスタムコマンドの機能があるので、それを使ってコマンド実行で学習と予測を実行できるようにします。

こちらが大変参考になります: [Djangoのカスタムコマンドにパラメータを追加する \- Qiita](https://qiita.com/nnsnodnb/items/b81b61b2aed2de92c877)

下記の要領でモデル(機械学習のモデルではなく MVC のほう)をインポートして使うことができます。便利！

```py3:myapp/train.py
from ...models import User

class Command(BaseCommand):

    def handle(self, *args, **options):
        users = User.objects.order_by('id')
```

カスタムコマンドを定義すればコマンド実行できるので、あとはこれを cron で定期実行させるだけで十分です。

```shell-session
$ python manage.py train # 学習
$ python manage.py predict # 予測
```

## デプロイ環境

実行環境は [gitでシンプルなデプロイ環境を作る \- Qiita](https://qiita.com/zaburo/items/8886be1a733aaf581045) を参考に `git push` でデプロイされるようにしました。 Web サーバーは `python manage.py runserver` で起動させています。これは開発用のサーバーなので間違った使い方なのですが、想定ユーザー1名なのでこれで十分でしょう。問題が出てくれば Nginx なりちゃんとした Web サーバーを用意すればいいと思います。 DB も SQLite です。

さて、これで機械学習を利用した予測結果を表示する Web アプリケーションができました。うん、これもまた AI だね！