読者です 読者をやめる 読者になる 読者になる

tera-technology

プログラミングやIT技術中心のBlogです

pythonで機械学習してみた(決定木)

pythonを使って機械学習してみました。

pythonにはscikit-learnという機械学習用のライブラリがありまして、これを使えば簡単に機械学習を使うことができるみたいです。
今回はscikit-learnを使って決定木を作成したいと思います。

では早速やっていきましょう。


まず機械学習に使うデータを用意しましょう。
しかし自分でデータを用意するのは大変ですよね?手っ取り早く機械学習を学びたいのにデータを用意する手間なんてかけたくないですよね?
実はscikit-learnにはあらかじめ機械学習のためのデータセットがいくつか用意されていて、それを使うことで簡単に機械学習を試すことができます。優しい~
今回はそのデータセットの中の1つである、アヤメの分類用データセットのIrisを使って学習を行っていきたいと思います。

Irisデータを使う

データセットを使うためにまずはライブラリをインポートしましょう。

import sklearn.datasets as ds

次にこのデータセットからIrisのデータを取り出してみましょう。
2行目のprintでirisのデータの説明を確認してます。

iris = ds.load_iris()
print(iris.DESCR)

irisのdescriptionはこんな感じです

Data Set Characteristics:
    :Number of Instances: 150 (50 in each of three classes)
    :Number of Attributes: 4 numeric, predictive attributes and the class
    :Attribute Information:
        - sepal length in cm
        - sepal width in cm
        - petal length in cm
        - petal width in cm
        - class:
                - Iris-Setosa
                - Iris-Versicolour
                - Iris-Virginica
    :Summary Statistics:

    ============== ==== ==== ======= ===== ====================
                    Min  Max   Mean    SD   Class Correlation
    ============== ==== ==== ======= ===== ====================
    sepal length:   4.3  7.9   5.84   0.83    0.7826
    sepal width:    2.0  4.4   3.05   0.43   -0.4194
    petal length:   1.0  6.9   3.76   1.76    0.9490  (high!)
    petal width:    0.1  2.5   1.20  0.76     0.9565  (high!)
    ============== ==== ==== ======= ===== ====================

        ~以下略~

ここで注目してほしいのはirisは3つのクラスに分類できるということです。
分類には

  • sepal length
  • sepal width
  • petal length
  • petal width

の4つの特徴を使って分類していきます。

irisがどんなデータかざっくり理解したところで早速決定木の作成に移りたいと思います。

決定木の作成

まずこちらの決定木作成コードを見てください。

f:id:terakei818:20160521024202p:plain

解説をすると、irisのデータをロードしたらDecisionTreeClassifier()という決定木作成のための関数を使い、clfという変数に入れておきます。そしてfit()関数でirisのデータを突っ込んでやるだけで決定木が作成できてしまいます。すごく簡単ですね!

あとは作成した決定木をdotファイルで出力しています。
どんな木ができたか確認してみましょう。

f:id:terakei818:20160521030737p:plain

この図の葉の部分を見てもらうとわかるようにきちんとクラス通りに分けられているのがわかるかと思います。ただしここで注意してほしいのがこの決定木は過学習をしている可能性が高いということです。なぜかというとこの訓練データに対してフィットしすぎているからです。

例えばversicolorの条件をまとめると
・(2.45 < petal length <= 4.95) かつ (petal wedth <= 1.65)
・(4.95 < petal length <= 5.45) かつ (1.55 < petal wedth <= 1.75)
・(2.45 < petal length <= 4.85) かつ (1.75 < petal wedth) かつ (3.1 < sepal wedth)
となっています。
これでは新たなデータを分類分けするときに正しく分類分けできない可能性があります。未知データに対してデタラメな分類分けをされては困ります。

ではどうすればいいのでしょうか?

過学習の解決

決定木の過学習に対する対策としては大きく分けて以下の2つの方法があります。

  1. 子ノードに存在するデータ数の最小値を設ける
  2. ツリーの深さを制限する

要するに先ほどの結果からデータ数の最小値を決めることで値の範囲を広げ、また木の深さが深くなっていくほどクラス分けの条件が厳しくなっていくということなので深さを制限して条件を緩めようということです。

データ数の最小値の設定はDecisionTreeClassifier()の引数に min_samples_leaf = 数字 を、最大の深さは max_depth = 数字 を指定することで決めることができます。

clf = tree.DecisionTreeClassifier(min_samples_leaf = 3, max_depth = 4)  # 最低3件のデータが必要, 最大の深さは4

この決定木はこんな感じになりました。

f:id:terakei818:20160521035220p:plain

違う分類に入っているものもありますが先ほどのものよりは条件が緩くなっているため未知のデータに対しては強くなりました。
その証拠に交差確認法で評価してみましょう。
交差確認法とはデータを訓練データとテストデータに分けて検証する方法で詳しくはwikiなど見てください。
交差検証 - Wikipedia

pythonでは以下のコードを実行することで簡単に検証することができます。

scores = cv.cross_val_score(clf, iris.data, iris.target, cv=10)
print(scores.mean())

cvはK-分割交差検証のKにあたる部分でここでは10を指定しており、データを10分割し9個を訓練データ用に、残り1個をテスト用にする方法を用いています。
この実行結果は 0.96667 となりました。つまり大体96.7%位の正確さで分類できるということです。ちなみに制限を設けない決定木でのスコアは 0.95333 でしたので精度が上がっているのがわかると思います。
もっといいスコアを出すためのデータの最小値と最大の深さの組み合わせはforなどで組み合わせを変えつつスコアが高い組み合わせを探すのがいいかと思います。


ざっくりと説明しましたが無事決定木を作ることができました。まだまだ機械学習のほんの一部しか触っていませんが思ったより簡単だったのではないでしょうか?
またいろんな学習法など取り上げたいと思います。