1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-06-22

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

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?