決定木(分類)のハイパーパラメータとチューニング２

# はじめに
　乳癌の腫瘍が良性であるか悪性であるかを判定するためのウィスコンシン州の乳癌データセットについて、決定木とハイパーパラメータのチューニングにより分類器を作成する。データはsklearnに含まれるもので、データ数は569、そのうち良性は212、悪性は357、特徴量は30種類ある。
　前回の記事で最適なハイパーパラメータを決定した。本記事ではmax_depthとAccuracyの関係と決定木の視覚化について記載する。

シリーズ

- [線形重回帰による決定係数の算出とモデルの選択](https://qiita.com/FujiedaTaro/items/4ef757370ca19abe783c)
- [線形重回帰による決定係数の算出とモデルの選択 part_2](https://qiita.com/FujiedaTaro/items/a7a23ce321f7733ae9cf)
- [単回帰分析による寄与率の算出](https://qiita.com/FujiedaTaro/items/090bad07672c322bceeb)
- [線形回帰と特徴量の絞り込み](https://qiita.com/FujiedaTaro/items/3fd874ae91b511eb1d1f)
- [ロジスティック回帰(分類)とハイパーパラメータのチューニング](https://qiita.com/FujiedaTaro/items/5784eda386146f1fd6e7)
- [線形SVC(分類)とハイパーパラメータのチューニング](https://qiita.com/FujiedaTaro/items/3e469688ad6f0dca62c0)
- [非線形SVC(分類)とハイパーパラメータのチューニング](https://qiita.com/FujiedaTaro/items/e5583f8767173e6a6f9a)
- [決定木とハイパーパラメータのチューニング](https://qiita.com/FujiedaTaro/items/47e06c758b451cbda412)
- [決定木とハイパーパラメータのチューニング２](https://qiita.com/drafts/0cc107bd69e9a0d2ce38/edit)

# max_depthとAccuracyの関係
　max_depth以外のパラメータを前回最適化した値とし、max_depthを1～10まで振ったときのAccuracyを以下の図に示す。max_depthとは、木の深さの最大値を示す。max_depthが3～5の時、Accuracyは最大となるが、max_depthが6以降はAccuracyが低下していく。これは、max_depthを大きくしすぎたことによる過学習が起きているためと思われる。なお、プログラム上、Accuracyが最大となるmax_depthは3と判定している。

![tree_graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252172/9b1b41c5-65af-5b2a-8c96-93b74781332b.png)

# 決定木の可視化
　決定木をdotファイルに変換し、Graphvizによって可視化した図をいかに示す。ハイパーパラメータは最適化した値に設定している。max_depthは3のため、3段階に分岐していることがわかる。評価するサンプル数は426あり、徐々にふるいにかけていく。最初のパラメータがWorst radiusのため、これが最も重要なパラメータと思われる。以下、条件についてTrue or Falseでふるいにかけていき、対象の腫瘍がbenign（良性）であるかmalignant（悪性）であるかを判定している。
![tree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252172/2a61bd48-b5b3-50a0-6b87-84ebf49da084.png)

# 手順
乳癌データの読み込み
トレーニングデータ、テストデータの分離
条件設定
決定木の実行
決定木をdotファイルに変換
グラフのプロット

```python
%%time
import matplotlib.pyplot as plt 
from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score

#乳癌データの読み込み
cancer_data = load_breast_cancer()

#トレーニングデータ、テストデータの分離
train_X, test_X, train_y, test_y = train_test_split(cancer_data.data, cancer_data.target, random_state=0)

#条件設定
max_score = 0
accuracy = []
depth_list = [i for i in range(1, 11)]

#決定木の実行
for depth in tqdm(depth_list):
    clf = DecisionTreeClassifier(criterion="entropy", splitter="random", max_depth=depth, min_samples_split=4, min_samples_leaf=1, random_state=41)
    clf.fit(train_X, train_y)
    accuracy.append(clf.score(test_X, test_y))
    if max_score < clf.score(test_X, test_y):
        max_score = clf.score(test_X, test_y)
        depth_ = depth

#決定木をdotファイルに変換
clf = DecisionTreeClassifier(criterion="entropy", splitter="random", max_depth=depth_, min_samples_split=4, min_samples_leaf=1, random_state=41)
clf.fit(train_X, train_y)
tree.export_graphviz(clf, out_file="tree.dot", feature_names=cancer_data.feature_names, class_names=cancer_data.target_names, filled=True)

#グラフのプロット
plt.plot(depth_list, accuracy)
plt.title("Accuracy change")
plt.xlabel("max_depth")
plt.ylabel("Accuracy")
plt.show()

print("max_depth:{}".format(depth_))
print("ベストスコア:{}".format(max_score))
```

出力

```
max_depth:3
ベストスコア:0.972027972027972
Wall time: 112 ms
```

# おわりに
　max_depthがAccuracyに大きく影響することがわかった。また、決定木を可視化することで難解なAIの思考についての説明をなんとなくできた気がする。