# 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) 来了解更多的细节并且欢迎你为这个项目你做出贡献。