Windows/Python3でpylearn2を使う

正直不可能だと思い始めていたが、なんとかできたのでその足跡を残す。PythonではできるだけWindowsを避けること、が真理ではある。

* 事前準備
* Theanoのインストール
* pylearn2のインストール

## 事前準備
今回は[Miniconda](http://conda.pydata.org/miniconda.html)を利用して環境を構築する。これはバイナリライブラリの取得が楽だからだが、virtualenvでも[Windowsバイナリ](http://www.lfd.uci.edu/~gohlke/pythonlibs/)を利用すれば同様に環境構築可能(この場合、Git shellで作業していれば後述のpylearn2インストール時の問題は発生しない)。

普段はバイナリ版でスキップする忌々しい`vcvarsall.bat`エラーは今回不可避になるので、Visual Studioを入れるかWindows SDKを使うかしてコマンドを使えるようにしておく。

Visual Studioインストール後の設定
[Python で “error: Unable to find vcvarsall.bat” が出た場合。](http://mimumimu.net/blog/2014/06/01/python-%E3%81%A7-error-unable-to-find-vcvarsall-bat-%E3%81%8C%E5%87%BA%E3%81%9F%E5%A0%B4%E5%90%88%E3%80%82/)

このためにVisual Studio?冗談じゃないという方のためにwindows SDKを利用する方法の参考。
[sms tools in Windows](https://github.com/MTG/sms-tools/wiki/sms-tools-in-Windows)

*-----以下の準備は、libpythonをインストール(conda install libpython)すればOKのはず(念のため残しておく)。*

Cコンパイルが避けられないのでMinGWをインストールする。インストール方法は以下が分かりやすいと思う。

[MinGWのインストールと使い方(2014年版)](http://web.plus-idea.net/2014/06/mingw-install-2014/)
[Windows に MinGW-w64 と MSYS を導入する](http://www.hnagata.net/archives/182)

MSYSも必要なので導入しておく(勝手に入ってくれた気もするが・・・)。まずは`gcc`/`g++`を使えるようにする。

次に、定義ファイルを作成するためのコマンド`gendef`をインストールする。これは後々重要な役割を果たす。

[gendef](http://sourceforge.net/p/mingw-w64/wiki2/gendef/)
[Setting up a MinGW-w64 build environment/Setup Python for compilation of extensions](http://ascend4.org/Setting_up_a_MinGW-w64_build_environment)

ソースを[ここ](http://sourceforge.net/p/mingw-w64/code/HEAD/tree/trunk/mingw-w64-tools/gendef/)から落としてきて、ディレクトリ上でコンパイルを仕掛ける。この作業はMSYSコンソールで行う必要がある(MSYSインストールディレクトリにある`msys.bat`を実行すると立ち上がる)。

```
cd ~/gendef 
./configure --prefix=/mingw
make -j4 && make install
```

これで`gendef`コマンドが使用できることを確認。

*-----(libpythonがあれば不要と思われる準備、ここまで)*

後は、`conda`コマンドで環境を作成して準備完了(以下は最小構成。Theanoのテストを動かしてみたいなら`nose`、またpylearnで画像系の処理を行いたい場合はPIL、SVMならscikit-learnなどが必要だが、これらは簡単に入れられるはず。詳細な依存は[公式](http://deeplearning.net/software/pylearn2/)参照。)。

```
conda create -n my_learn numpy scipy cython libpython matplotlib ipython pip
```

`activate my_learn` (my_learnの名前はお好きに)で環境を有効化しておくのを忘れずに。これを忘れるとグローバルに入ってえらい目に合う。なお、`pip`を仮想環境に入れておくと、`pip install`を行ったときに仮想環境にのみインストールしてくれる。これでcondaとpipの併用が可能になるのだ。

## Theanoのインストール
`pip install Theano`で快適に行きたいところだが、pipでインストールできるバージョンではPython3が[サポートされていないらしい(2014/11現在)](https://github.com/Theano/Theano/issues/1527)ので最新版を使用する(インストール手順は[公式](http://deeplearning.net/software/theano/install.html#install)も参照。ただ、実はうまくいかないけど、の注意書きが多い)。

以下のコマンドを実行するのだが、注意点が何点か。

```
pip install --upgrade --no-deps git+git://github.com/Theano/Theano.git
```

※なお、`git clone`からの`python setup.py develop`ではpythonのソースを2to3で変更する処理が[動かない](https://groups.google.com/forum/#!msg/theano-users/fUpX3Dv5Qbw/2qi4vAokWjAJ)ので、うまくいかない。また、`git://`のプロトコルが使えない場合はここを`https://`にする。

### pipバグ対応(1.5.6)
[Windows上で発生するエラー](https://github.com/pypa/pip/issues/1674)がpipにあるので(1.5.6現在。ただ、[修正は完了している](https://github.com/pypa/pip/pull/1745)ので時期リリースでは多分治る)、ソースを一部修正する。修正するファイルは、仮想環境に入れたpipのファイルということを忘れずに。Minicondaインストールディレクトリの`envs`に作成した仮想環境のフォルダがあるので、そこの`Lib\site-packages\pip\util.py`を以下のように一時的に変更。

```
def rmtree_errorhandler(func, path, exc_info):
    """On Windows, the files in .svn are read-only, so when rmtree() tries to
    remove them, an exception is thrown.  We catch that here, remove the
    read-only attribute, and hopefully continue without problems."""
    exctype, value = exc_info[:2]
    if not ((exctype is WindowsError and value.args[0] == 5) or #others
            (exctype is OSError and value.args[0] == 13) or #python2.4
            (exctype is PermissionError and value.args[0] == 5) #python3.3
            ):
        pass #raise
```

`exctype is PermissionError and value.args[3] == 5`の箇所でエラーになるので、インデックスを修正しかつ例外を`raise`を揉み消す。不要ファイルを削除するための処理のようだが、コメント化しても削除されるので問題ない。心配な場合`C:\Users\xxxxxx\AppData\Local\Temp`をチェックすること。


### import theanoでのエラー対処  
Theanoはimport時に走るコンパイルがあり(lazylinker)、これでしこたまエラーになるので対応を行う。

*-----以下は、libpythonがインストールされている場合対応不要なはず(念のため残しておく)。*

コンパイルのために、Python用の定義ファイルを作成する。仮想環境フォルダの直下で、以下を実行(`pythonXX.dll`のXXはバージョンにより読み替え)。

```
gendef pythonXX.dll
dlltool --as-flags=--64 -m i386:x86-64 -k --output-lib libpythonXX.a --input-def pythonXX.def
```

dlltoolコマンドの`--as-flags=--64 -m i386:x86-64`は64bit用なので、32bitの場合不要。
これでできた`libpythonXX.a`ファイルを、`libs`フォルダに移す(`Lib`ではないので注意。ヘッダーファイルが入っているフォルダ)。

そして、theanoの設定ファイルである`.theanorc`を`%USERPROFILE%`フォルダに作成する(`C:\Users\[your_user]`直下)。

```:.theanorc
[blas]
ldflags = 

[gcc]
cxxflags = -shared -I[mingw installed folder]/include -L[conda env folder]/libs -lpython34
```

[mingw installed folder]はMinGWをインストールしたフォルダ、[conda env folder]は作成した仮想環境のフォルダになる。


詳細はこちらを参考。

[Python:Installing Theano on Windows 64bit with Python 3](http://rosinality.ncity.net/doku.php?id=python:installing_theano)

*-----(libpythonがインストールされている場合対応不要なはずな処理、ここまで。)*

これで`import theano`がつつがなく完了すれば第一段階OK。


## pylearn2のインストール
pylearn2はもともと`pip`でインストールできないので、`git clone`でとってきて使用する。
手順は[こちら](http://deeplearning.net/software/pylearn2/#download-and-installation)の通りだが、Windowsだと`pylearn2/utils\_window_flip.c(2133) : warning C4013: 関数 'rand_r' は定義されていません。int 型の値を返す外部関数と見なします。`の後` failed with exit status 1120`で落ちる。

これはWindowsで`rand_r`という関数が定義されていないために起こるが、実はこの対応は既に[pylearn側で行われている](https://github.com/lisa-lab/pylearn2/pull/949)。ただ、この修正の中の分岐がPython3ではうまく動かないので、ここをちょっと修正する。

```py:pylearn2/utils/_window_flip.pyx
IF UNAME_SYSNAME == u"Windows":
    cdef extern from "stdlib.h":
        int rand()
```

`UNAME_SYSNAME == "Windows"`だと[比較が上手くいかないようなので](https://github.com/lisa-lab/pylearn2/issues/914)、これをユニコード文字列にして比較する(Python3では区別がなくなったはずだが・・・)。

最終的に`import pylearn2`がエラーなくできれば完了。それと、以下の環境変数を設定しておく。

* PYLEARN2_DATA_PATH : データの補完先
* PYLEARN2_VIEWER_COMMAND : 画像データを表示する際のスクリプト。Windowsの場合以下を設定。  
`start /wait %SystemRoot%\System32\rundll32.exe "%ProgramFiles%\Windows Photo Viewer\PhotoViewer.dll", ImageView_Fullscreen`  

セットアップは以上。お疲れ様でした。
※なお、これで`import pylearn2`は通るようになりますがいろいろ動きません。[こちら](https://github.com/lisa-lab/pylearn2/pull/1251)のマージをいましばらく待ちましょう。