【機械学習】XGboostを勉強してみる

# XGBoostの概要
XGBoostは *"eXtreme Gradient Boosting"* の略であり、勾配ブースティングを使ったツリーのアンサンブル学習です。その優れた性能と速さから、KaggleやKDDCupなどで上位の成績を修めたモデルにもよく使われています。実際2015年のKaggleコンペでは29の優勝モデルのうち、17モデルがXGBoostを使ったモデルでした。

# XGBoostのアルゴリズム

### 目的変数の推定方法
<img width="760" alt="Screenshot 2020-03-03 at 17.15.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407366/e4600451-6bd3-0ee7-41e9-4af8cf0866fb.png">


```math
\widehat {y}_i=\phi \left( x_{i}\right) =\sum ^{K}_{k=i}f_{x}\left( x_{i}\right) ,f_{k}\in F
```

```math
F =\{f\left( x\right) = 
 W_q \left(x)\right \}\left(q:R^{m}\rightarrow T, w\in R^{T}\right)
```

$F$は決定木(CART)の空間を表しています。各ツリーで求めらられたスコアをクラスごとに集計し、$\widehat {y}_i$を求めます。$K$はスコアを足す際に使われる関数です。

### モデルの評価と学習方法

モデルの評価方法は次のようになります。


```math
\mathcal{L}(\phi)=\sum_{i} l\left(\hat{y}_{i}, y_{i}\right)+\sum_{k} \Omega\left(f_{k}\right)
```
```math
\Omega(f)=\gamma T+\frac{1}{2} \lambda\|w\|^{2}

```
yの損失は、L1正則化に、学習した重みもを滑らかにするためのペナルティー項をたしたものです。
上の関数の最適化にあたり、通常のユークリッド空間上の最適化手法を使うことができないため、**greedy**に$y_t$を足すことで、徐々に最適なLを求めていきます。
そのようにして求めた、構造 qを持つ決定木の上での重みwと、それに対応する評価式は次のように求められます。

```math
w_{j}^{*}=-\frac{\sum_{i \in I_{j}} g_{i}}{\sum_{i \in I_{j}} h_{i}+\lambda}
```

```math
\tilde{\mathcal{L}}^{(t)}(q)=-\frac{1}{2} \sum_{j=1}^{T} \frac{\left(\sum_{i \in I_{j}} g_{i}\right)^{2}}{\sum_{i \in I_{j}} h_{i}+\lambda}+\gamma T
```
また、各ノードの評価式は

```math
\mathcal{L}_{s p l i t}=\frac{1}{2}\left[\frac{\left(\sum_{i \in I_{L}} g_{i}\right)^{2}}{\sum_{i \in I_{L}} h_{i}+\lambda}+\frac{\left(\sum_{i \in I_{R}} g_{i}\right)^{2}}{\sum_{i \in I_{R}} h_{i}+\lambda}-\frac{\left(\sum_{i \in I} g_{i}\right)^{2}}{\sum_{i \in I} h_{i}+\lambda}\right]-\gamma
```
で求められます。
またXGBoostでは過学習を防ぐために、**Shrinkage**というテクニックと**feature subsampling** というテクニックを使います。Shrinkageは古い情報からの学習を減らしていく方法です。
以上のようなテクニックを使うことで、XGBoostでは効率的にかつ的確に学習をすることが可能となっています。

*詳細は[こちら](https://arxiv.org/pdf/1603.02754.pdf)をご参照ください。*

# XGBoostのパラメター
よく指定するパラメターを紹介します。


| パラメター |概要|値   |デフォルト   |
|---|---|---|---|
| booster  |弱学楽器の種類   | gbtree, dart (ツリーモデル) gblinear(線形モデル)|gbtree   |
|  verbosity | ログの出力 |  0(無), 1(警告), 2(info), 3(debug) | 1  |
|  validate_parameters |入力されたパラメターが使われたかどうかをチェック   | false/true  | false  |
| nthread  | 並列処理のスレッド数  |int   |CPUのmax   |
|  eta | Shrinkageのサイズ。学習率lrと同等。大きいほど保守的なモデルになる。  | [0,1] | 0.3  |
| gamma  | 新しいノードを作成するために必要な損失減少の最小値。大きいほど保守的なモデルになる。  |[0, inf] |0   |
| max_depth  | 木の深さ。大きいほど過学習する。  |   int |  6 |
| min_child_weight  | 各child nodeでのwの合計の最小値。大きいほど保守的なモデルになる。 |  [0,inf] |0   |
| subsample |ツリーの作成に使うサンプルの大きさ。|(0, 1]|1|
| sampling_method |サブサンプルの選択方法|uniform, gradient_based | uniform |
| lambda |L2正則化項|[0, inf]|1|
| alpha |L1正則化項|[0, inf]|0|
| objective |学習の目的| reg:squarederror, reg:squaredlogerror, reg:logistic, binary:logistic,multi:softmax... | reg:squarederror |
| eval_metric |モデルの評価方法| rmse, rmsle, mae, logloss, error |objectiveに対応|
| seed |乱数のseed|seed|0|

*詳しくは[こちら](https://xgboost.readthedocs.io/en/latest/parameter.html)をご参照ください。*

# XGBoostをPythonで実行

```python
from xgboost.sklearn import XGBClassifier
 
model = XGBClassifier(
 learning_rate =0.01,
 n_estimators=5000,
 max_depth=4,
 min_child_weight=6,
 gamma=0,
 subsample=0.8,
 colsample_bytree=0.8,
 reg_alpha=0.005,
 objective= 'binary:logistic',
 nthread=4,
 scale_pos_weight=1,
 seed=27
)

model.fit(X_train, y_train)
y_pred = model.predict(X_test)
```

詳しくは[こちら](https://www.analyticsvidhya.com/blog/2016/03/complete-guide-parameter-tuning-xgboost-with-codes-python/)をご参照ください。