Bash on Ubuntu on Windows で XGBoostを動かす


（R-packageのインストール方法を追記しました．http://qiita.com/TomokIshii/items/b43321448ab9fa21dc10#%E8%BF%BD%E8%A8%98r-package-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB 2016/9/2）

Windows 10のAnniversary Updateがリリースされ，Bash on Ubuntu on Windowsが使えるようになった．「TensorFlowも動いた！」との報告もあるが，今回は，XGBoost(Python-package)の環境整備を試みることにした．XGBoostは，勾配ブースティング法を実装したライブラリ(Xgboost = eXtreme Gradient Boosting)である．C++のプログラムであるが，Python, R, Julia, Javaからの使用もサポートしている．

少し前に，WindowsへXGBoostをインストールした際には，MinGWのインストールから始めて結構な手間がかかったことを覚えている．改善を期待して，「今回は，こんなにインストール簡単！」的な記事を書こうと思いつつ作業を進めたが，多少のトラブルに見舞われたのでその状況を紹介する．

（今回，作業した環境は，Windows 10, ver.1607, Bash on Ubuntu on Windows(Windows Sybsystem for Linux), Python 3.5.2, pyenv, miniconda3-4.0.5, xgboost ver.0.6になります．）

## 基本的なツールの導入
Microsoftのブログ記事等を参考に，Bash on Ubuntu on Windowsのインストールを行うとUbuntu 14.04LTS の環境が入るが，開発環境としてほとんどプログラムが入っていない．そこで，まず基本的なツールの導入を行った．

#### git インストール

```bash
sudo apt-get install git
```

#### gcc, g++ インストール

```bash
sudo apt-get install gcc
sudo apt-get install g++
```

```bash
$ gcc --version
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```

ということで，gcc 4.8.4が入った．

#### make インストール
`make`もディフォルトで入っていないのでインストール．

```bash
sudo apt-get install make
```

## XGBoostのビルドとPython関連のインストール

gcc, g++他がインストールできたので，XGBoostのビルドを行う．

#### XGBoost build

```bash
git clone --recursive https://github.com/dmlc/xgboost 
cd xgboost
make -j4

```

以前トライしたWindow 10ネイティブ環境ではビルドできるまで相当な苦労があったが，今回は，一発でビルド完了．`xgboost/lib` ディレクトリには，`libxgboost.a` と `libxgboost.so` ができていた．　　
　　
#### pyenv インストール
まだPython2が必要になるケースもあると考えられるので，pyenv の環境を作ってPython2と3を切り替えるようにする．（参考）https://github.com/yyuu/pyenv#installation

PATH関連で環境変数の追加が必要になるが，ここでは初めから入っていた`vi`を用いて`.bashrc`の編集を行った．

#### miniconda インストール

pyenvを用いてインストールするpythonを選択する．選択肢のリスト表示は以下．

```bash
pyenv install -l
```

ここでは（フルパッケージの）Anaconda系か（最小パッケージの）miniconda系かの選択に迷うが，今回は miniconda3-4.0.5 を選択した．

```bash
pyenv install miniconda3-4.0.5
```

その後，数値計算に必要なモジュールをインストール．

```bash
conda install numpy, scipy, scikit-learn
conda install ipython

```

## XGBoostのPython-package インストール

ここまでとても順調に進み，もう大丈夫，のはずだったが，最後につまずくことになった．
まず，XGBoostのドキュメントに従い，コマンドを打つと，

```bash
cd python-package; sudo python setup.py install
```

いろいろと足りないとのメッセージでエラーが発生する．これに対しては，python-setuptoolsが必要．（XGBoostのドキュメントにきちんと書いてありました．）

```bash
sudo apt-get install python-setuptools
```

この後，一つ上のステップに戻って，

```bash
sudo python setup.py install
```

で回復と思ったが，「コマンド見つからない」系のエラー．原因は，pyenvの環境整備をユーザー・レベルで行っていた一方で，上記コマンドがシステム・レベル（root権限）で行おうとしたミスマッチにある．
（ pyenvは，ディフォルト(?)で ＄HOME/.pyenv以下にshimを敷いて複数環境の切り替えを行う．）

そこで，ユーザー・レベルでインストールを再度行う．

```bash
python setup.py install
```

インストールが無事完了．（と思っていた．．．）
xgboostのテストを，配布コードの predict_first_ntree.py で行う．

```bash
$ python predict_first_ntree.py
OMP: Error #100: Fatal system error detected.
OMP: System error #22: Invalid argument
中止 (コアダンプ)
```

原因不明（予想外）の結果である．手がかりとなるのは**"OMP"**のワードだけである．ネットで検索するとOMP = OpenMP (Open Multi-Processing) とのこと．これに関連しそうなのは，Minicondaで入れた，Intel製の数値計算ライブラリ**MKL** (Math Kernel Library)である．（Numpy, Scipyの前提ライブラリとしてインストールされます．）

MKLは，数値計算関係のライブラリ Numpy, Scipy などをサポートし，パフォーマンスを改善するものであるが，環境整備という点では，しばしばトラブルを起こすので要注意である．以前，Ubuntu環境（仮想環境なし）で（何がきっかけだったか不明ですが）いきなり，Deep Learning FrameworkのTheanoとTensorFlowが同時にエラーを発生する状況となり，あわてて調べた結果，MKL起因だったということがあった．

今回は，Ubuntu仮想環境ということでMKLに対応ができていなかった模様．MKL関係のライブラリを入れ換えて試した．入れ換えは，`nomkl`をインストールする，というコマンドになる．MKLライブラリが外され，代わりに openblasがインストールされた．

```bash
conda install nomkl

```

この後，predict_fist_ntree.py を実行，シンプルな二値分類問題のデモである．
（冒頭部分は，配布コードに改変を加えました．）

```py
import os
# check os environment
if os.name == 'nt':  # Windows case ... add mingw lib path
    mingw_path = 'C:\\usr\\mingw-w64\\x86_64-5.4.0-win32-seh-rt_v5-rev0\\mingw64\\bin'
    os.environ['PATH'] = mingw_path + ';' + os.environ['PATH']
if os.name == 'posix':  # Linux case
    break

import numpy as np
import xgboost as xgb

# load data
dtrain = xgb.DMatrix('./data/agaricus.txt.train')
dtest = xgb.DMatrix('./data/agaricus.txt.test')
param = {'max_depth':2, 'eta':1, 'silent':1, 'objective':'binary:logistic' }
watchlist  = [(dtest,'eval'), (dtrain,'train')]
num_round = 3
bst = xgb.train(param, dtrain, num_round, watchlist)
print ('start testing prediction from first n trees')
# predict using first 1 tree
label = dtest.get_label()
ypred1 = bst.predict(dtest, ntree_limit=1)
# by default, we predict using all the trees
ypred2 = bst.predict(dtest)
print ('error of ypred1=%f' % (np.sum((ypred1>0.5)!=label) /float(len(label))))
print ('error of ypred2=%f' % (np.sum((ypred2>0.5)!=label) /float(len(label))))

```

以下，計算結果．

```bash
$ python predict_first_ntree.py
[15:25:08] 6513x127 matrix with 143286 entries loaded from ./data/agaricus.txt.train
[15:25:08] 1611x127 matrix with 35442 entries loaded from ./data/agaricus.txt.test
[0]     eval-error:0.042831     train-error:0.046522
[1]     eval-error:0.021726     train-error:0.022263
[2]     eval-error:0.006207     train-error:0.007063
start testing prediction from first n trees
error of ypred1=0.042831
error of ypred2=0.006207
```

ということで正常動作となった．今回の環境(Bash on Ubuntu on Windows)がMKL未対応であるとの情報は，既にQiitaにも上がっていた．（後から知りました．．．）

(Qiita記事 - PikkamanVさん)
http://qiita.com/PikkamanV/items/d308927c395d6e687a6a
（その引用元）
https://scivision.co/anaconda-python-with-windows-subsystem-for-linux/

## まとめと感想

まだ，Bash on Ubuntu on... の環境を使い始めたところあるが，この環境に期待するところは大きい．MKL未対応については残念であるが，以前の
- Windows + ライブラリ「あれ」+ コンパイラ「これ」+ ツール「それ」
のような状態からは大きな改善と思われる．

また，XGBoost 自体も(ver.0.5をスキップして) ver.0.6に上がったところなので，今後勉強を進めてXGBoostに対する理解を深めたいと考えている．

ここへ来て，Docker for Windows もリリースされ，（Bash on..とは用途は異なるのかも知れないが）windowsのプログラミング環境，面白くなってきた．（悩ましくもありますが．）

## （追記）R-package のインストール
前提パッケージとして{devtools}が必要となる．さらにRパッケージ{devtools}に必要なCライブラリがBash on Ubuntuの初期状態では入っていないので，パッケージを２つほど `sudo apt-get install` でインストールする必要があった．

{devtools}が入ったら，Rインタープリタを立ち上げて，

```R
library(devtools)
install('xgboost/R-package')

```

でOKなはずだった．（'xgboost/R-package' は相対パスなので，カレントディレクトリにより適切にパスを指定する必要があります．）

上記スクリプトの実行した結果が以下．

```R
> library(devtools);install('R-package')
Installing xgboost
 URL 'https://cran.rstudio.com/src/contrib/Matrix_1.2-7.1.tar.gz' を試しています
Content type 'application/x-gzip' length 1805890 bytes (1.7 MB)
==================================================
downloaded 1.7 MB

sh: 1: /bin/gtar: not found
sh: 1: /bin/gtar: not found
 system(cmd, intern = TRUE) でエラー:  命令の実行中にエラーが起きました
 追加情報:  警告メッセージ:
 utils::untar(src, exdir = target, compressed = "gzip") で:
  ‘/bin/gtar -xf '/tmp/RtmplJiuv1/Matrix_1.2-7.1.tar.gz' -C '/tmp/RtmplJiuv1/devtools24847e356e71'’ returned error code 127

```

Matrix_1.2-7.1.tar.gz を展開する際に `/bin/gtar` がないというエラーメッセージである．Bash on Ubuntu には `/bin/tar` があるのでそれを使って欲しいのだが，インストール・スクリプトはそのようにできていないらしい．ルートにリンクを張ってもいいのだが，ネットで調べるとstackoverflowに対策法が載っていた．

[Error in untar( ) while using R](http://stackoverflow.com/questions/21118468/error-in-untar-while-using-r)

```R
Sys.setenv(TAR = '/bin/tar')
```

Rインタープリタ上で上記をセットして，その後，'install(R-package)' を実行してインストールが完了できた．

## 参考 web site
- Microsoft MSDN, Bash on Ubuntu on Windows
https://msdn.microsoft.com/en-us/commandline/wsl/about
- pyenv - github
https://github.com/yyuu/pyenv
- Continuum, Anaconda site
https://www.continuum.io/
- Dmlc, XGBoost - github
https://github.com/dmlc/xgboost
- Cygwin絶対殺すマン ～物理のオタクがWindows Subsystem for Linuxで数値計算できるようになるまで～ - Qiita
http://qiita.com/PikkamanV/items/d308927c395d6e687a6a
- Anaconda Python with Windows Subsystem for Linux
https://scivision.co/anaconda-python-with-windows-subsystem-for-linux/
- Error in untar() while using R
http://stackoverflow.com/questions/21118468/error-in-untar-while-using-r