【決定木分析（分類）】機械学習特訓 ver.6（まとめ）

<b> 【特訓 ver.6】 決定木分析スタート！！</b>
※この記事では、決定木を用いた分類手法についてまとめます

## ▼学習の流れ
まずは決定木（分類）の基本を押さえ、具体的な分析例を通して理解を深める。
※なお、決定木は、回帰・分類それぞれに用いることができる手法（回帰→回帰木、分類→分類木と呼ぶ）。今回は、分類問題について扱っていきます。

■使用するデータ
Social_Network_Ads.csv
年齢とお給与をもとに、商品を「購入したかどうか」

※データセット：後日

<font color="#FF0000">■ 決定木分析について学習する</font>

大まかな流れ）
① データ読み込みや前処理、分割
　- 質的変数も適切に数値化（エンコーディング）すれば使用できる

② モデルの設定と訓練
　- 「決定木」で実施する

③ モデルの精度の確認
　- 精度について、以下6項目で確認していく

分類における「学習モデルの性能評価」について確認していく！
(1) 混同行列（confusion matrix）
(2) 正解率（accuracy）
(3) 適合率（precision）
(4) 再現率（recall）
(5) F1スコア（F1-score）
(6) AUC（曲線下面積）
<br>

## ▼復習
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/4b35c745-e827-65d6-8d2c-2be9926e07bc.png)
前回扱ったSVM分析に続き、分類手法をもう少し深めていく。
今回は、その中でもよく名前が出てくる、決定木についてみていく。

## ▼決定木分析とは？
データに基づいた<b>意思決定</b>を行うときに用いられる方法であり、非常にイメージがしやすいものである。

<b>・意思決定とは？</b>
→ 何らかの基準に従って物事を自分で判断すること

例）どのスマートフォンを購入するかを決める
・性能が高いスマートフォン
・価格が手頃なスマートフォン
・カメラ機能が優れているスマートフォン
・バッテリー持続時間が長いスマートフォン

<b>・意思決定を自動化する</b>
→ 自分に代わって誰かに物事を判断してもらうこと

例）コンサル系やショップの販売員がそのお仕事に近い
現状のお悩みや、大切にしたい価値観（「しょっちゅう充電しないといけないのが面倒」「綺麗な写真を撮りたいのに画質がイマイチ」など。）を伝えた上で、提案を受ける（店員さんに判断してもらう）。

上記のようなものを、<b>データに基づいて意思決定を行いたい</b>際に、<b>決定木分析</b>を用いることがある。

## ▼決定木の特徴
赤か青かを分割したい時。
Yes or No で答えられる条件によって分類をしていく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/5301e5ba-bbbd-9fc1-64b1-defefe4dd95a.png)

ちなみに、これらの条件設定は決定木が自動でしてくれるため、人間が行わなくてよい。

<b>＜具体例＞</b>
勉強時間、睡眠時間、過去問を解いたかどうかをもとにテストに「合格」するか「不合格」になるかを分類。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/ee290c1b-1faa-d75c-f721-8f3d18f0b576.png)

実際のデータをもとに用いながら、決定木の理解をさらに深めていく。
特に、条件分岐を増やしすぎると過学習につながることもあるため、条件数を適切に選ぶことを意識する。

## それでは実際に使ってみよう！！
### 【決定木（分類木）】
<b>大まかな流れ</b>
① データ読み込みや前処理、分割
　- 質的変数も適切に数値化（エンコーディング）すれば使用できる

② モデルの設定と訓練
　- 「決定木分析」で実施する
　- <b>その１）枝刈りなし ver.
　- その２）枝刈りあり ver.</b>

③ モデルの精度の確認
　- 精度について、以下6項目で確認していく
　　(1) 混同行列（confusion matrix）
　　(2) 正解率（accuracy）
　　(3) 適合率（precision）
　　(4) 再現率（recall）
　　(5) F1スコア（F1-score）
　　(6) AUC（曲線下面積）


<b>① データ読み込みや前処理、分割</b>
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# データの読み込み
df = pd.read_csv("/content/Social_Network_Ads.csv")
df.head()
```
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/b91da5a1-7875-2505-1489-fe54fc5ea936.png" width=50%>

〔説明変数〕
・Age（年齢）、EstimatedSalary(お給与)

〔目的変数〕
・Purchased・・・1=購入する、0=購入しない


```python
#説明変数と目的変数に分ける
x = df[["Age","EstimatedSalary"]]
y = df["Purchased"]

#データを学習用と検証用に分割
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(
    x,y,train_size=0.7,random_state=0)
```
決定木分析をする際には、<font color="#FF0000">標準化を行わなくてよい</font>ことが非常に魅力的✨

そのため、データの準備はこれにて終了！
<br>

### まずは、<font color="#FF0000">枝刈りなし</font>で決定木分析
<b>② モデルの設定と訓練</b>

```python
#決定木
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(max_depth=10)
model.fit(x_train,y_train)
```
パラメータについて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/56746e33-5727-af12-a5f2-a4634b097ca4.png)
`max_depth`が大事。


```python
#決定木の可視化
from sklearn.tree import export_graphviz
import pydotplus
from io import StringIO
from IPython.display import Image

dot_data = StringIO()
feature_names = ["Age", "EstimatedSalary"]
export_graphviz(model, out_file=dot_data,
                feature_names=feature_names,
                class_names=["No", "Yes"],
                filled=True, rounded=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/c661f442-4d07-9d9f-b71b-0bfaa87b05de.png)


※参照：特徴量の可視化（何が分岐条件に影響を与えているか）
```python
#特徴量の可視化
feature_names = ["Age", "EstimatedSalary"]
n_features = len(feature_names)
plt.barh(range(n_features), model.feature_importances_, align="center")
plt.yticks(np.arange(n_features), feature_names)
plt.xlabel("Feature Importance")
plt.ylabel("Features")
```
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/184c3428-c7c4-2b9f-f603-730c3c1ca01c.png" width=70%>



<b>③ モデルの精度を確認</b>
```python
from sklearn.metrics import confusion_matrix,precision_score,recall_score,f1_score,roc_auc_score

# 混同行列の出力
print("Confusion Matrix:")
print(confusion_matrix(y_true=y_test, y_pred=model.predict(x_test)))

# 性能指標の計算と表示
print("正解率(train) =", model.score(x_train, y_train))
print("正解率(test) =", model.score(x_test, y_test))
print("適合率 =", precision_score(y_true=y_test, y_pred=model.predict(x_test)))
print("再現率 =", recall_score(y_true=y_test, y_pred=model.predict(x_test)))
print("F1スコア =", f1_score(y_true=y_test, y_pred=model.predict(x_test)))
print("AUC =", roc_auc_score(y_true=y_test, y_score=model.predict_proba(x_test)[:, 1]))
```

▼ 回帰式の精度を確認
　(1) 混同行列（confusion matrix）
　(2) 正解率（accuracy）
　(3) 適合率（precision）
　(4) 再現率（recall）
　(5) F1スコア（F1-score）
　(6) AUC（曲線下面積）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/cb5cec58-f56b-a318-c744-7d0b1d91c7ef.png" width=40%>

今回の学習結果を見てみると、正解率（train)と正解率（test）の結果に、大きく差があることがわかる。これは、<b>過学習</b>の傾向であり、trainデータにフィットし過ぎてしまっていることが原因である。

`max_depth`=10で設定していたため、枝分かれ多すぎており、よい学習モデルが出来上がらなかったと言える。

実際、農家でも、枝分かれが多すぎると必要な養分が果物に行かないため、全体の味が落ちる傾向があるとのことで、多すぎる枝をカットするらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/948cc90f-dc8e-4815-1a87-0202f9fcfa6b.png)

これを<b>剪定</b>といい、決定木分析でも同じように剪定を行うことが大切で、これをすることでモデルの精度の向上が見込める。


### 次に、<font color="#FF0000">枝刈りあり</font>で決定木分析

<b>① データ読み込みや前処理、分割</b>
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/dfa7e4dc-7d85-7e8c-e1b7-c7ba6eaab900.png" width=40%>

 ここまでは同じ。

<b>② モデルの設定と訓練</b>
```python
#決定木
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(max_depth=4)
model.fit(x_train,y_train)
```
先ほどは`max_depth`=10で設定していたのに対して、今回は`max_depth`=4で設定。

```python
#決定木の可視化
from sklearn.tree import export_graphviz
import pydotplus
from io import StringIO
from IPython.display import Image

dot_data = StringIO()
feature_names = ["Age", "EstimatedSalary"]
export_graphviz(model, out_file=dot_data,
                feature_names=feature_names,
                class_names=["No", "Yes"],
                filled=True, rounded=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/63e442dd-c36c-10b5-bfed-7e0df2172a75.png)



※参照：特徴量の可視化（何が分岐条件に影響を与えているか）
```python
#特徴量の可視化
feature_names = ["Age", "EstimatedSalary"]
n_features = len(feature_names)
plt.barh(range(n_features), model.feature_importances_, align="center")
plt.yticks(np.arange(n_features), feature_names)
plt.xlabel("Feature Importance")
plt.ylabel("Features")
```
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/6dce02ab-25de-ac0d-ee44-ea6d82a40562.png" width=70%>

<b>③ モデルの精度を確認</b>
```python
from sklearn.metrics import confusion_matrix,precision_score,recall_score,f1_score,roc_auc_score

# 混同行列の出力
print("Confusion Matrix:")
print(confusion_matrix(y_true=y_test, y_pred=model.predict(x_test)))

# 性能指標の計算と表示
print("正解率(train) =", model.score(x_train, y_train))
print("正解率(test) =", model.score(x_test, y_test))
print("適合率 =", precision_score(y_true=y_test, y_pred=model.predict(x_test)))
print("再現率 =", recall_score(y_true=y_test, y_pred=model.predict(x_test)))
print("F1スコア =", f1_score(y_true=y_test, y_pred=model.predict(x_test)))
print("AUC =", roc_auc_score(y_true=y_test, y_score=model.predict_proba(x_test)[:, 1]))
```

▼ 回帰式の精度を確認
　(1) 混同行列（confusion matrix）
　(2) 正解率（accuracy）
　(3) 適合率（precision）
　(4) 再現率（recall）
　(5) F1スコア（F1-score）
　(6) AUC（曲線下面積）

 <p float="left">
　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/6e618b35-7334-7713-c828-a24aab7f04af.png" width="47.1%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853135/d556155f-55d9-ce62-e471-6a526a452d7f.png" width=48%">
</p>
<b>左図</b>：`max_depth`=4の結果　<b>右図</b>：`max_depth`=10の結果


今回の学習結果を見てみると、正解率（train)と正解率（test）の結果に、大きく差があることがわかる。これは、右図は、<b>過学習</b>の傾向であり、`max_depth`は適切に設定する必要がある。
<br>

<b>＜まとめ＞</b>
決定木の特徴して以下がわかった。
・メリット
　学習結果の解釈がしやすい、図示のイメージがわかりやすい
　データの前処理が少ない、標準化などが必要ない。

・デメリット
　条件分岐が複雑になりすぎると、過学習になりやすい。
 　→ 剪定（枝刈り）で回避する
　精度が非常に高いわけではない
　→アンサンブル学習や、ランダムフォレストを使うと精度の向上が見込める。

<br>
<b>以上。</b>

<br>
続いては、 <b>アンサンブル学習</b>へGO！！！