scikit-learnを使った決定木分析

投稿者: | 2019-09-22
Table of Content

scikit-learnを使った決定木モデルの構築

scikit-learnを使って決定木でのクラス分類をやっていきたいと思います。

決定木分析

決定木は、データに対して、もっともデータをうまく分類できる特徴量の条件を次々と定義していき、その一つ一つの条件に沿って分類していく方法です。

決定木を使う利点は以下になります。

モデルの結果の解釈が容易

決定木はモデルの特徴量に対して条件を設定して、その条件に沿って分類していきます。
分類の条件を見ればモデルがどのような条件でデータを分類しているのかが分かるのでディープラーニングなどの手法と比べて解釈が容易です。

質的データから量的データまで様々な変数を扱える

決定木は特徴量に対して条件を設定するので、カテゴリカル変数も連続値の変数もモデルの入力とすることができます。
モデルを使用する際の前処理なども少ないので、扱いやすいモデルです。

外れ値に頑健

外れ値があっても、もっともうまく分類できる条件で、分類の条件を設定するので外れ値の影響が少ないのが特徴です。

以下ではワインの品種を分類するサンプルデータを用いて、scikit-learnの決定木を用いた学習のコードサンプルを紹介します。

ライブラリのインポート

必要なライブラリをインポートします。

In [21]:
import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, roc_auc_score, confusion_matrix, precision_score, recall_score 
import warnings
warnings.filterwarnings('ignore')

データセットのロードとデータの確認

関数load_wineを使ってワインの品種分類についてのデータを読み込みます。

このデータを使って、ワインの品種を分類するモデルを作成します。

In [9]:
data = load_wine()

特徴量データと教師データの作成

load_wineで読み込んだデータはディクショナリ形式でデータが入っているので、
モデルに入力できるように、pandasのデータフレームとnumpy配列に読み込みます。

In [13]:
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target
print(X.shape)
print(y.shape)
(178, 13)
(178,)
In [19]:
X.dtypes
Out[19]:
alcohol                         float64
malic_acid                      float64
ash                             float64
alcalinity_of_ash               float64
magnesium                       float64
total_phenols                   float64
flavanoids                      float64
nonflavanoid_phenols            float64
proanthocyanins                 float64
color_intensity                 float64
hue                             float64
od280/od315_of_diluted_wines    float64
proline                         float64
dtype: object

トレーニングデータと検証用データの分割

scikit-learnのtrain_test_splitを使って、トレーニングデータの一部を検証用データとして分けておきます。

In [14]:
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

モデルの作成と学習

決定木モデルを構築します。

scikit-learnのDecisionTreeClassifierで良く使うパラメーターは以下になります。

パラメーター変数 概要 設定可能な値
max_depth 木の深さを設定します。木の深さを浅く設定することで過学習を抑えます 木の最大の深さを整数で設定します。(デフォルトはNone)Noneの場合は葉の全てのサンプルが1つのクラスになるか、ノードのサンプル数がmin_samples_split以下になるまで木を深くします。
min_samples_split 1ノードあたりのサンプル数を設定します。サンプル数を増やすことで過学習を抑えることができます。 整数か小数の値を設定できます。整数を設定した時は、1ノードあたりのサンプル数の最小値。小数を設定した時は、小数×サンプル数が1ノードあたりのサンプル数の最小値になります。(デフォルト値は2)
min_samples_leaf 1 つのサンプルが属する葉の数の最小値 整数か小数の値を設定できます。整数を設定した時は、サンプルが属する葉の数の最小値。小数を設定した時は、小数×サンプル数がサンプルが属する葉の最小値になります。(デフォルト値は1)
max_features 木を分割する時に考慮する特徴量の数 文字列で、'auto', 'sqrt', 'log2',か Noneを設定する(デフォルトはNone)
class_weight クラスの数に偏りがある場合に、クラスごとの重みを調整する変数 {class_label: weight}のdict形式か'balanced'が設定できる(デフォルトはNone(全てのクラスが同じ重み))
In [15]:
tree_clf = DecisionTreeClassifier(max_depth=3)
tree_clf.fit(X_train, y_train)
Out[15]:
DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=3,
                       max_features=None, max_leaf_nodes=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, presort=False,
                       random_state=None, splitter='best')

検証データでの精度の検証

検証データを使ってモデルの精度を検証します。
今回は正解率を出してみます。

In [16]:
y_pred = tree_clf.predict(X_val)
accuracy_score(y_val, y_pred)
Out[16]:
0.9444444444444444

検証データでの正解率は約94%でした。

決定木の可視化

決定木を可視化することができます。
以下のPythonのライブラリを使用するので、pipでインストールします。

pip install pydotplus
pip install graphviz

また、オープンソースのグラフ可視化ソフトウェア、 GraphVizをインストールする必要があります。
macでhomebrewを使って以下のコマンドでインストールできます。

brew install graphviz

以下で決定木を可視化するためのライブラリをインポートします。

In [18]:
from io import StringIO
import graphviz
import pydotplus
from IPython import display
Out[18]:
array([0, 0, 2, 0, 1, 0, 1, 2, 1, 2, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1,
       1, 2, 2, 2, 1, 1, 1, 0, 0, 1, 2, 0, 0, 0])
In [24]:
g = StringIO()
export_graphviz(
    tree_clf,
    out_file=g,
    feature_names=data.feature_names,
    class_names=data.target_names,
    rounded=True,
    filled=True
)
graph = pydotplus.graph_from_dot_data(g.getvalue())
display.display(display.Image(graph.create_png()))

上の決定木の見方は、
1行目がノードを分ける条件になります。
例えば、一番上のノードは、「color_intensity」が3.82以下の時は左側のノードに分類し、残りは左のノードに分類されます。

2行目はそのノードのジニ係数になります。(ノードの不純度を表す指標です。不純度が最も低ければジニ係数の値は0,不純度が高くなればなるほどジニ係数の値が1に近づきます。)

3行目はそのノードのサンプル数です。

4行目はクラスごとのサンプル数です。

5行目はそのノードがどのクラスに分類されるかを表します。

まとめ

この記事ではscikit-learnの決定木を使ったクラス分類をワインのサンプルデータを使って紹介しました。

決定木は、解釈もしやすくどのような変数が分類や回帰の結果に影響しているかがわかりやすいので分析にも使うことができます。

また、モデルの学習と予測だけでなく、決定木の可視化方法についても紹介しました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です