決定木の違いについて (E資格対策)

決定木,Random Forest,勾配ブースティング,バギング・・・

木構造のアルゴリズムって多くて何が何だか分からなくなったのでまとめます。

目次
[決定木](#決定木)
[バギング](#バギング)
[Random Forest](#Random Forest)
[勾配ブースティング](#勾配ブースティング)
[まとめ](#まとめ)



#決定木
決定木とはYesかNoでこたえられる質問で構成された木構造の手法。
メリットとしては
・結果のモデルが容易に理解できる
・データのスケールに対して完全不変なので正規化や標準化が不要
があげられます。

```python
import mglearn
mglearn.plots.plot_animal_tree()
```

![tree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604787/356ed0b4-fd02-2602-1030-8b4dcba681e9.png)

上図のように各分岐点に特徴量への質問が用意されており、それにしたがって、分類や回帰を行います。

コードで書くとこんな感じ。


```python
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
cancer=load_breast_cancer()

X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, test_size=0.25)

tree=DecisionTreeClassifier(random_state=0)
tree.fit(X_train,y_train)
print("Accuracy on training set:{:3f}".format(tree.score(X_train,y_train)))
print("Accuracy on test set:{:3f}".format(tree.score(X_test,y_test)))
```

結果

```
Accuracy on training set:1.000000
Accuracy on test set:0.909091
```

構造を可視化できます。

```python
from sklearn.tree import export_graphviz
export_graphviz(tree, out_file='tree.dot', class_names=["malignant", "benign"],
                feature_names=cancer.feature_names, impurity=False, filled=True)

import graphviz

with open("tree.dot") as f:
  dot_graph=f.read()

graphviz.Source(dot_graph)
```


![chapter2.ipynb - Colaboratory - Google Chrome 2020_04_20 14_14_58 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604787/4b72db78-f81d-2cef-9383-aa6a8531aa0e.png)


過学習抑制のためにmax_depth,max_leaf_nodesなどが用意されています。


#バギング
弱いモデルを複数用意し、多数決を取る手法。過学習しにくい点がメリットです。

#Random Forest
決定木のデメリットとして過剰適合しやすい点があげられます。
そこで少しずつ異なる決定木を用意して多数決をとる手法をランダムフォレストといいます。バギングの手法の一つでもあります。


```python
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_moons

X,y=make_moons(n_samples=100, noise=0.25,random_state=0)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, stratify=y)

forest=RandomForestClassifier(n_estimators=5,random_state=2)
forest.fit(X_train,y_train)

fig,axes=plt.subplots(2,3,figsize=(20,10))
for i,(ax,tree) in enumerate(zip(axes.ravel(), forest.estimators_)):
  ax.set_title("Tree{}".format(i))
  mglearn.plots.plot_tree_partition(X_train,y_train,tree,ax=ax)

mglearn.plots.plot_2d_separator(forest, X_train, fill=True, ax=axes[-1,-1],alpha=.4)
axes[-1,-1].set_title("Random Forest")
mglearn.discrete_scatter(X_train[:,0],X_train[:,1],y_train)

```

結果

![rf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604787/1784a7b7-edc9-db43-2355-0305ca06112a.png)

例では木を5個用意して境界線を求めています。

先ほど決定木で求めたデータにランダムフォレストを適用してみましょう。


```python

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
cancer=load_breast_cancer()

X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, test_size=0.25)

forest=RandomForestClassifier(n_estimators=100,random_state=2)
forest.fit(X_train,y_train)
print("Accuracy on training set:{:3f}".format(forest.score(X_train,y_train)))
print("Accuracy on test set:{:3f}".format(forest.score(X_test,y_test)))
```

木の数は100個です。
結果は

```
Accuracy on training set:1.000000
Accuracy on test set:0.993007
```
と通常の決定木より精度が良くなりました。

#勾配ブースティング
ランダムフォレストは木を並列にしますが、勾配ブースティングは木を直列に並べるイメージです。

```python

from sklearn.ensemble import GradientBoostingClassifier

grbt = GradientBoostingClassifier(random_state=0)
grbt.fit(X_train, y_train)

print("Accuracy on training set:{:3f}".format(grbt.score(X_train,y_train)))
print("Accuracy on test set:{:3f}".format(grbt.score(X_test,y_test)))
```

デフォルトでは木の数は100個です。
結果は

```
Accuracy on training set:1.000000
Accuracy on test set:0.993007
```

#まとめ
決定木：YesかNoでこたえられる質問で構成された木構造
バギング：データの一部を使って学習器を作り、何個も組み合わせて最後に多数決をとる手法
ランダムフォレスト：決定木を複数組み合わせて最後に多数決をとる手法
勾配ブースティング：学習器Aが解けない問題を解く学習器Bが解けるようにし、学習器Bが解けない問題を学習器Cが解けるようにし・・・を繰り返す手法

参考文献
Pythonではじめる機械学習――scikit-learnで学ぶ特徴量エンジニアリングと機械学習の基礎