Pythonで0からディシジョンツリーを作って理解する
1.概要編 - 2. Pythonプログラム基礎編 - 3. データ分析ライブラリPandas編 - 4.データ構造編 - 5.情報エントロピー編 - 6.ツリー生成編 - (番外編) 離散化
ID3によるディシジョンツリー生成は、数値データを扱うことができません
数値データの100,10,1があるとします。次のような関係があります。
100 >> 10 > 1
数値データ以外には、例えば、文字型のデータ(名義尺度とも呼ばれます)があり、100,10,1を文字として扱うと次のようになります。
"100" ≠ "10" ≠ "1"
「大きい、小さい」という情報が消えるだけでなく、10は、100よりも1に近い、という情報も消えてしまいます。
離散化せずに、ID3によるディシジョンツリーを作成する場合の問題点
このデータから、Pythonで0からディシジョンツリーを作って理解する (1. 概要編)によってディシジョンツリーを作成すると、次のようになります。
ゴルフ〇はゴルフに行く、×は行かないとして、ゴルフに行くのには天気が最も重要で、晴なら次は湿度、雨なら風が次に重要になると分かります。
一方、温度を離散化せずに数値データのまま、同様にディシジョンツリーを作成してみます。
温度は、29度以外はすべて単独の値であるため、それぞれの温度のときにゴルフに行く/行かないが決定されます。おそらくこのディシジョンツリーを見ても、人が何かの気づきを得ることは難しいでしょう。
数値データをグルーピングして文字型のデータに分けることを離散化といいます
一般的には、データの数値を等間隔に分割して離散化する方法、データの数を同じように分割する等頻度の方法があります。
等間隔でデータを離散化する
例えば上のようなデータの場合、データから離散化された文字に変換する計算式は、次のようになります。
# math.floor (小数点以下の切り捨て)を使うために、インポートします。
import math
# この数値を、これから離散化します。
values = [1,5,7,11,12,14,19,20]
# span変数の間隔内にある数値は、同じラベルの数値として離散化します。
span = 10
# 離散化後の各グループの名前を決めておきます。
labels = ["小さい方","大きい方"]
# 離散化する計算式は、 「( x - 最小値 ) / 1グループの大きさ」として結果の小数点を切り捨てます。
# そこでまず最初に「最小値」を求めておきます。
mi = min(values)
# map関数によって、values配列の各値を離散化します。listは、mapの結果からリスト(配列)を作るというものです。
discretized_values = list(map(lambda x:labels[math.floor((x-mi)/span)],values))
# 以下のように離散化後のデータが作成されます。
print(discretized_values)
# ['小さい方', '小さい方', '小さい方', '大きい方', '大きい方', '大きい方', '大きい方', '大きい方']
等頻度でデータを離散化する
# math.floor (小数点以下の切り捨て)を使うために、インポートします。
import math
# この数値を、これから離散化します。
values = [1,5,7,11,12,14,19,20]
# n変数の個数だけ1つのグループにして、離散化します。
n = 4
# 離散化後の各グループの名前を決めておきます。
labels = ["最初の方","後の方"]
# 離散化する計算式は、配列の添え字(インデックス)を i として、「i / n」として小数点を切り捨てます。
# [ x for i in range(n) ] はリストの内包表記というもので、forを使って配列を生成、初期化するものです。
discretized_values = [labels[math.floor(i/n)] for i in range(len(values))]
# 以下のように離散化後のデータが作成されます。
print(discretized_values)
# ['最初の方', '最初の方', '最初の方', '最初の方', '後の方', '後の方', '後の方', '後の方']
独自にデータを分類して離散化する
これまでの2例は、客観的な視点に立ってデータを離散化してきました。一方、データの意味を考慮して離散化する方法もあります。
例えばあるゲームでのランキングに影響を与える要素を分析したい場合、そのランキングを1位、2位のような数値データではなく、ランキング上位、下位のように離散化した方が良いわけですが、この「ランキング上位」は、恣意的に決めることもできます。1位では無ければ意味がないと考えるならば、1位とそれ以外と離散化しても良いでしょう。また、2分割ではなく、ランキング上位、中位、下位と分けても良いでしょう。
参考
自動的に数値データを離散化してディシジョンツリーを作成するC4.51というアルゴリズムが知られています。このアルゴリズムを使用することも、データを離散化する1つの手法となりますが、結果のディシジョンツリーが複雑になりやすいことから、自らマニュアルでデータを離散化する、という方法がとられることもあります。
-
Quinlan, J. R.: C4.5: Programs for Machine Learning. Morgan Kaufmann Publishers, (1993). ↩