機械学習のためのPython環境構築 2018.05

2018.05.10 公開

## 本稿の趣旨

* Pythonを触ったことがない人でも読める
* Mid-2018 に対応したPython環境構築手順メモ
* 方針
    * pipenv を使おう
    * pyenv は原則使わない
        * Python 2 系は原則使わない
    * anaconda も使わない

## はじめに
近年の機械学習ブームにより、ノン・プログラマーがPython環境の構築にチャレンジする機会も増えていることと思います。しかし、特に機械学習向けのPython環境を構築する方法に関しては、ここ数年で急速に整備が進んだこともあり、良質な情報と古い情報が混在してしまっています。
そこで、2018年5月現在の状況に対応した環境構築（python3、pipenvによるパッケージ管理、主なモジュールのインストール）を極力簡潔にまとめることを目指しました。
なお筆者は初学者のため、怪しい点も多々あるかと思います。ツッコミ等大歓迎です。

## 1. 筆者の環境

OS: Ubuntu 16.04 で動作確認をしています。

## 2. Python 3 のインストール
Ubuntuにはシステム用のPythonが既にインストールされているはずです。
早速ターミナルを開き、確認してみましょう。

```terminal
$ python --version
Python 2.7.12
$ python3 --version
Python 3.5.2
```
Python2系とPython3系の2種類がインストールされていることがわかります。これらには互換性がないため、気をつけて使いましょう。これからPythonを使いはじめる方は、Python3系のみを扱うこととなるでしょう。（Python 2系は2020年にサポートが終了します。）

## 3. 仮想環境・パッケージ管理
### 3.1 何を使うべきか
Pythonには、多くのパッケージをインストールすることで機能を追加していくことができます。プロジェクトごとに異なるパッケージを用いる場合、導入パッケージの異なる複数の環境を持つことができると便利です。これを実現できる機能が仮想環境です。
仮想環境を実現するための方法はpyenv, venv, virtualenv等いくつかあり、混乱のもととなっていましたが、Python 3.3 以降はvenvがPython標準機能として組み込まれています。

また、Pythonでは多くのパッケージをインストールすることで機能を追加していくことができますが、インストール・管理を支援するツールとして、Python 3.4 以降はpipが標準で組み込まれています。

venvとpipを組み合わせて一層使いやすくしたソリューションとして、現在pipenvがPython.org推奨として提供されており、これからの環境構築はこれを使うのが最適と考えられます。
公式機能が弱かった時代に作られたpyenvやconda等の公式外ツールは、今でも多くの人に使われていますが、必須ではなくなってきています。[^31]

[^31]: かつてはSciPyを入れるだけでも、condaを使わないとコンパイルが必要だったそうです。今ではpipで一発で入ります。

### 3.2 pipenvのインストール
それでは、pipenvを入れていきましょう。

```terminal
$ pip install --user pipenv
```

`--user`をつけることで、ユーザーディレクトリにインストールされ、システムの環境を壊すリスクが低減できます。

```terminal
$ pipenv --version
pipenv, version 11.10.4
```

インストールできました。

### 3.3 pipenvの使い方
#### 3.3.1 仮想環境の立ち上げ

hogeという仮想環境を作ってみましょう。

```terminal
$ mkdir hoge  # hogeフォルダを作る
$ cd hoge  # hogeフォルダに移動
~/hoge$ pipenv install  # 仮想環境 作成
```

これで、hogeフォルダに`Pipfile`と`Pipfile.lock`というファイルができたはずです。前者がこの環境の設定ファイル、後者がパッケージリストになっています。

```terminal
$ ls
Pipfile  Pipfile.lock
```

中身をのぞいてみましょう。


```terminal
$ cat Pipfile
[[source]]
verify_ssl = true
url = "https://pypi.org/simple"
name = "pypi"

[packages]

[requires]
python_version = "3.5"

[dev-packages]
```

Pipfileにはpython_versionが記載されています。Python 3.5が指定されています。

```terminal
$ cat Pipfile.lock
{
    "_meta": {
        "hash": {
            "sha256": "f05f9e300c88030ff492b1c6c019990ad9d8656221ef7c28e7636a2f86a79791"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.5"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {},
    "develop": {}
}

```

Pipfile.lockはjsonになっています。パッケージを入れていないので空の状態です。

さて、`pipenv shell`で仮想環境内のshellを起動します。
Pipfileのとおり、デフォルトではPython 3系の環境になります [^32] 。もちろんpipもこの環境にひも付きます。

[^32]: `--python 2`のようにバージョンを指定することができます。（そのバージョンのPythonがインストール済である必要があります。）

```terminal
$ pipenv shell
(hoge-qr0Xjim8)$ python --version
Python 3.5.2
(hoge-qr0Xjim8)$ pip --version
pip 10.0.1 from /home/(user)/.local/share/virtualenvs/hoge-qr0Xjim8/lib/python3.5/site-packages/pip (python 3.5)
(hoge-qr0Xjim8)$ exit # shellから抜ける
$
```

#### 3.3.2 パッケージのインストール
パッケージ管理もpipenvで行われます。pipをご存知な方は、pipを使うようにpipenvを使うことができます。
インストールは`pipenv install [package]`でOKです。

```terminal:NumPyをインストールする場合
$ pipenv install numpy
Installing numpy…
Collecting numpy
  Downloading https://files.pythonhosted.org/packages/7b/61/11b05cc37ccdaabad89f04dbdc2a02905cf6de6f9b05816dba843beed328/numpy-1.14.3-cp35-cp35m-manylinux1_x86_64.whl (12.1MB)
Installing collected packages: numpy
Successfully installed numpy-1.14.3

Adding numpy to Pipfile's [packages]…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (17cf22)!
```

…………けっこう時間かかりましたよね？　[公式でもこの問題は認識しているようです](https://github.com/pypa/pipenv/issues/1785)。[^33]

[^33]: 依存関係グラフを再生成するために、パッケージ全体をダウンロードしてsetup.pyをクロールしているようです。ハッシュ生成にも時間がかかっているようです。

パッケージ追加のたびにこれだけの時間がかかるのは耐えられないので、`--skip-lock`オプションをつけましょう。寝る前など時間のある時に`pipenv lock`でlockファイルを生成するのがよいでしょう。美しくないですが、現状はやむをえないようです。（Pipfileの方は更新されます。）

```terminal:NumPyをインストールする場合（lockファイル更新はスキップ）
$ pipenv install numpy --skip-lock
$ pipenv lock  # とても遅い
```

インストールされているパッケージの確認は次のコマンドでできます。

```terminal:
$ pipenv graph
numpy==1.14.3
```

## 4 機械学習向けの構成例
どのパッケージをインストールするかはもちろん個人個人が選べばいいのですが、いわゆる定番とされるパッケージがいくつかあるため、構成例を提示します。

### 4.1 Jupyter Notebook
Jupyter NotebookはPythonコードを含んだ実験ノートのようなものを作ることができます。機械学習分野ではデファクトスタンダードになっています。

```terminal
$ pipenv install jupyter --skip-lock
```

次のコマンドでノートブックサーバを起動します。

```terminal
$ pipenv shell
(~)$ jupyter notebook
```

Jupyter Notebookの使い方については多くの情報があるためここでは触れませんが、NumPyが使えるかだけ確認してみます。

```python:test.ipynb
> import numpy as np
> ar = np.asarray([1,2,3])
> ar
array([1, 2, 3])
```

動きました。

### 4.2 定番ライブラリ
機械学習における定番ライブラリをざっくりまとめてみました。
それぞれの詳細については、まとまった資料がいくつもあるので割愛します。

* 基本パッケージ
    * NumPy : 数値計算ライブラリ（ベクトル計算・行列計算）
    * SciPy : 科学計算ライブラリ（NumPyも自動で入ります）
    * matplotlib : グラフ描画ライブラリ
    * pandas : データフレームを扱うためのライブラリ
    * flake8 : コードチェッカー
* 機械学習用パッケージ
    * scikit-learn : 基本的な機械学習
* Deep Learning フレームワーク
    * TensorFlow : Google謹製
        * Keras : 主にTensorFlowを使いやすくする
    * MXNet : 
        * Gluon : Amazon, Microsoft謹製、MXNetを使いやすくする
    * Caffe : 初期のフレームワーク、現在も広く使われる
    * Caffe2 : Facebook謹製。
    * Chainer : 和製ライブラリ、Define by Run の提唱者
    * PyTorch : Chainerのフォーク、Define by Run で書ける

## おわりに
類似の記事も多い中、私個人の事例紹介という形でご参考いただければ幸いです。
こみいった部分は極力排除しましたが、必要に応じて適宜加筆・修正したいと思っています。

## 参考資料

#### 最近のPython環境構築
* [[覚え書き] Pythonの環境構築について](https://qiita.com/nakasan/items/73c6d6546f9994c0083c)
* [2018年のPythonプロジェクトのはじめかた](https://qiita.com/sl2/items/1e503952b9506a0539ea)

#### pipenv
* [公式](http://pipenv-ja.readthedocs.io/ja/translate-ja/)

#### Deep Learning ライブラリ
* [Deep Learning フレームワークざっくり一覧](https://qiita.com/bonotake/items/cbd44abbcbe333f264d8)