ディシジョンツリー作成時のデータの離散化について


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つの手法となりますが、結果のディシジョンツリーが複雑になりやすいことから、自らマニュアルでデータを離散化する、という方法がとられることもあります。


  1. Quinlan, J. R.: C4.5: Programs for Machine Learning. Morgan Kaufmann Publishers, (1993).