# AWS 上的分布式 XGBoost YARN
這是關于如何在 AWS EC2 集群上設置和運行分布式 [XGBoost](https://github.com/dmlc/xgboost) 的分步教程。分布式 XGBoost 運行在各種平臺上,如 MPI, SGE 和 Hadoop YARN 。 在本教程中,我們使用 YARN 作為示例,因為這是分布式計算廣泛使用的解決方案。
## 準備條件
我們需要獲得一個 [AWS key-pair(密鑰對)](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) 來訪問 AWS 服務。我們假設我們正在使用一個 `mykey` 的 key(鍵)和相應的權限文件 `mypem.pem` 。
我們還需要 [AWS credentials](http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html),其中包括 `ACCESS_KEY_ID` 和 `SECRET_ACCESS_KEY` 。
最后,我們需要一個 S3 bucket(桶)來托管數據和模型, `s3://mybucket/`
## 設置 Hadoop YARN 集群
本節將介紹如何從頭開始部署 Hadoop YARN 集群。 如果你已經有一個部署好的 Hadoop YARN 集群,那么你可以直接跳過這一步。 我們將使用 [yarn-ec2](https://github.com/tqchen/yarn-ec2) 來啟動集群。
我們可以先使用下面的命令來 clone yarn-ec2 腳本
```
git clone https://github.com/tqchen/yarn-ec2
```
要使用該腳本,我們必須將環境變量 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY` 設置正確。這可以通過在 `~/.bashrc` 中添加以下兩行來完成(用正確的替換字符串)
```
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```
現在我們可以從 EC2 啟動集群的 master 了
```
./yarn-ec2 -k mykey -i mypem.pem launch xgboost
```
等待幾分鐘,直到 master 啟動完成。
master 機器啟動之后,可以使用以下命令查詢 master 機器的公共 DNS 。
```
./yarn-ec2 -k mykey -i mypem.pem get-master xgboost
```
它會顯示 master 機器的公共 DNS 就像下面這樣 `ec2-xx-xx-xx.us-west-2.compute.amazonaws.com` 現在我們可以打開瀏覽器,輸入(用 master DNS 替換 DNS)
```
ec2-xx-xx-xx.us-west-2.compute.amazonaws.com:8088
```
這將顯示 YARN 集群的 job tracker 。需要注意的是,在 master 完成引導和啟動 job tracker 之前我們可能需要等待幾分鐘。
在 master 機器啟動后,我們可以自由添加更多的 slave 機器到集群中。 以下的命令將 m3.xlarge 實例添加到集群中了。
```
./yarn-ec2 -k mykey -i mypem.pem -t m3.xlarge -s 2 addslave xgboost
```
我們也可以選擇添加兩個 spot 實例
```
./yarn-ec2 -k mykey -i mypem.pem -t m3.xlarge -s 2 addspot xgboost
```
slave 機器將啟動,引導并向 master 報告。 你可以單擊 job tracker 上的 Nodes 鏈接來檢查 slave 機器是否已連接。 或者只需輸入以下 URL(將 DNS 替換為 master DNS)
```
ec2-xx-xx-xx.us-west-2.compute.amazonaws.com:8088/cluster/nodes
```
我們需要注意的一件事情是,并不是 job tracker 中的所有的鏈接都會起作用。 這是由于它們中的許多使用 AWS 的私有 IP,只能由 EC2 訪問。 我們可以使用 ssh 代理來訪問這些包。 現在我們已經建立了一個 master 和兩個 slaves 的集群。我們準備好運行這個實驗。
## 使用 S3 構建 XGBoost
我們可以通過以下命令登錄到 master 服務器上。
```
./yarn-ec2 -k mykey -i mypem.pem login xgboost
```
我們將使用 S3 來托管數據和結果模型,因此在集群關閉后數據不會丟失。 要做到這一點,我們需要構建 S3 支持的 xgboost 。我們唯一需要做的就是設置 `USE_S3` 變量為 true 。這可以通過以下的命令來實現。
```
git clone --recursive https://github.com/dmlc/xgboost
cd xgboost
cp make/config.mk config.mk
echo "USE_S3=1" >> config.mk
make -j4
```
現在我們已經構建了 S3 支持的 XGBoost 。如果您打算在 HDFS 上存儲數據,您也可以啟用 HDFS 支持,只需要打開 `USE_HDFS` 就可以了。
XGBoost 也依賴環境變量來訪問 S3,所以你需要在 `~/.bashrc` 中添加以下兩行(用正確的字符串替換)在 master 機器上也是如此。
```
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export BUCKET=mybucket
```
## 在 S3 上托管數據
在這個例子中,我們將把 xgboost 中的示例數據集復制到 S3 bucket(存儲桶)中作為輸入。 在正常使用情況下,數據集通常是從 existing distributed processing pipeline (現有的分布式處理 pipeline)創建的。 我們可以使用 [s3cmd](http://s3tools.org/s3cmd) 將數據復制到 mybucket(用真實的 bucket 名稱替換 ${BUCKET}) 。
```
cd xgboost
s3cmd put demo/data/agaricus.txt.train s3://${BUCKET}/xgb-demo/train/
s3cmd put demo/data/agaricus.txt.test s3://${BUCKET}/xgb-demo/test/
```
## 提交作業
現在一切準備就緒,我們可以將 xgboost 分布式作業提交到 YARN 集群了。 我們將使用 [dmlc-submit](https://github.com/dmlc/dmlc-core/tree/master/tracker) 腳本來提交作業。
現在我們可以在 distributed training folder(分布式訓練文件夾)(用真實的 bucket 名稱替換 ${BUCKET}) 中運行以下腳本。
```
cd xgboost/demo/distributed-training
# Use dmlc-submit to submit the job.
../../dmlc-core/tracker/dmlc-submit --cluster=yarn --num-workers=2 --worker-cores=2\
../../xgboost mushroom.aws.conf nthread=2\
data=s3://${BUCKET}/xgb-demo/train\
eval[test]=s3://${BUCKET}/xgb-demo/test\
model_dir=s3://${BUCKET}/xgb-demo/model
```
所有配置如 `data` 和 `model_dir` 也可以直接寫入配置文件。 請注意,我們只指定文件的文件夾路徑,而不是文件名。 XGBoost 將讀取該文件夾下的所有文件作為訓練和評估數據。
在這個命令中,我們使用了 2 個 workers,每個 worker 使用兩個正在運行的線程。 XGBoost 可以從每個 worker 使用多個 cores 中受益。 工作 cores 的常見的選擇范圍從 4 到 8 。 訓練好的模型將被保存到指定的模型文件夾中。您可以瀏覽模型文件夾。
```
s3cmd ls s3://${BUCKET}/xgb-demo/model/
```
以下是分布式訓練的輸出示例。
```
16/02/26 05:41:59 INFO dmlc.Client: jobname=DMLC[nworker=2]:xgboost,username=ubuntu
16/02/26 05:41:59 INFO dmlc.Client: Submitting application application_1456461717456_0015
16/02/26 05:41:59 INFO impl.YarnClientImpl: Submitted application application_1456461717456_0015
2016-02-26 05:42:05,230 INFO @tracker All of 2 nodes getting started
2016-02-26 05:42:14,027 INFO [05:42:14] [0] test-error:0.016139 train-error:0.014433
2016-02-26 05:42:14,186 INFO [05:42:14] [1] test-error:0.000000 train-error:0.001228
2016-02-26 05:42:14,947 INFO @tracker All nodes finishes job
2016-02-26 05:42:14,948 INFO @tracker 9.71754479408 secs between node start and job finish
Application application_1456461717456_0015 finished with state FINISHED at 1456465335961
```
## 分析模型
模型訓練后,我們可以分析學習的模型,并將其用于未來的預測任務。 XGBoost 是一個可移植的框架,所有平臺的模型都是 **_exchangable(可交換)_** 。 這意味著我們可以在 python/R/Julia 中加載訓練好的模型,并利用這些語言中的 data science pipelines (數據科學 pipeline)來做模型分析和預測。
例如,你可以使用 [這個 ipython notebook](https://github.com/dmlc/xgboost/tree/master/demo/distributed-training/plot_model.ipynb) 來繪制 feature importance (特征重要性)和可視化的學習模型。
## 故障排除
遇到問題的時候,最好的方法可能是使用以下命令獲取容器的 stdout 和 stderr 的日志,以檢查導致問題的原因。
```
yarn logs -applicationId yourAppId
```
## 未來發展方向
在本教程中,您已經學會了在 YARN 上使用分布式 XGBoost 。 XGBoost 是用于漸變增強的可移植和可伸縮框架。 您可以在 [資源頁面](https://github.com/dmlc/xgboost/blob/master/demo/README.md) 中查看更多的示例和資源。
該項目的目標是為所有平臺提供最佳的可擴展機器學習解決方案。 API 被設計為可移植的,相同的代碼也可以在其他平臺上運行,例如 MPI 和 SGE 。 XGBoost 正在積極發展,我們正在開發更多令人興奮的功能,如分布式 xgboost python/R 包。查看 [路線圖](https://github.com/dmlc/xgboost/issues/873) 來了解更多的細節并且歡迎你為這個項目你做出貢獻。