9.9 デシジョン・ツリー

oml.dtクラスは、分類にデシジョン・ツリー・アルゴリズムを使用します。

デシジョン・ツリー・モデルは、軸とパラレルなルールを含む分類モデルです。ルールは、人間が理解でき、レコード・セットを識別するためにデータベース内で使用できる条件文です。

デシジョン・ツリーは、一連の質問を問うことによってターゲット値を予測します。各段階で問われる質問はそれぞれ、直前の質問に対する回答によって決まります。最終的に特定のターゲット値を一意に識別できるような質問を重ねていきます。図形的には、このプロセスがツリー構造を形成します。

デシジョン・ツリー・アルゴリズムは、トレーニング・プロセスにおいて、ケース(レコード)のセットを2つの子ノードに分割する最も効率的な方法を繰り返し見つける必要があります。oml.dtクラスでは、この分岐の計算用に2つの同種メトリック(giniおよびentropy)を使用できます。デフォルトのメトリックはジニです。

oml.dtクラスの属性およびメソッドの詳細は、help(oml.dt)を呼び出すか、Oracle Machine Learning for Python APIリファレンスを参照してください。

デシジョン・ツリー・モデルの設定

次の表は、デシジョン・ツリー・モデルに適用される設定のリストです。

表9-4 デシジョン・ツリー・モデルの設定

設定名 設定値 説明
CLAS_COST_TABLE_NAME

table_name

モデルの作成および適用に使用するアルゴリズムのコスト・マトリックスを格納する表の名前。コスト・マトリックスは、分類ミスに関連するコストを指定します。

コスト・マトリックス表は、ユーザーが作成します。表の列の要件は次のとおりです。

  • 列名: ACTUAL_TARGET_VALUE

    データ型: 有効なターゲット・データ型

  • 列名: PREDICTED_TARGET_VALUE

    データ型: 有効なターゲット・データ型

  • 列名: COST

    データ型: NUMBER

CLAS_MAX_SUP_BINS

2 <= 数値 <= 2147483647

各属性のビンの最大数を指定します。

デフォルト値は32です。

CLAS_WEIGHTS_BALANCED

ON

OFF

ターゲットの分布を平均化するモデルをアルゴリズムが作成する必要があるかどうかを示します。分布の平均化では、主要なクラスを重視する全体精度ではなく、平均精度(クラスごとの精度の平均)を向上できるため、この設定は稀なターゲットが存在する場合に最適です。デフォルト値はOFFです。

TREE_IMPURITY_METRIC

TREE_IMPURITY_ENTROPY

TREE_IMPURITY_GINI

デシジョン・ツリー・モデルのツリー不純メトリック。

ツリー・アルゴリズムでは、各ノードでのデータの分岐に最適なテスト質問が検索されます。最適な分岐および分岐値は、ノードのエンティティに対するターゲット値の同質性(純度)が最大限に高くなるものです。純度は、メトリックに従って測定します。デシジョン・ツリーでは、純度メトリックとしてジニ(TREE_IMPURITY_GINI)またはエントロピ(TREE_IMPURITY_ENTROPY)のいずれかを使用できます。デフォルトでは、アルゴリズムでTREE_IMPURITY_GINIが使用されます。

TREE_TERM_MAX_DEPTH

2 <= 数値 <= 100

分岐の条件: ツリーの最大深度(ルート・ノードとリーフ・ノードとの間(リーフ・ノードを含む)の最大ノード数)。

デフォルトは7です。

TREE_TERM_MINPCT_NODE

0< = 数値 <= 10

トレーニング・データ内の行の割合として表現されたノード内のトレーニング行の最小数。

デフォルト値は0.05で、0.05%を示します。

TREE_TERM_MINPCT_SPLIT

0 < 数値 <= 20

トレーニング行の割合として表現された、ノードの分割を検討するために必要な行の最小数。

デフォルト値は0.1で、0.1%を示します。

TREE_TERM_MINREC_NODE

数値 >= 0

ノード内の行の最小数。

デフォルト値は10です。

TREE_TERM_MINREC_SPLIT

数値 > 1

分岐の条件: 値として表現される親ノードのレコードの最小数。レコード数がこの値よりも少ない場合、分岐は試行されません。

デフォルト値は20です。

例9-9 oml.dtクラスの使用

この例では、oml.dtクラスの様々なメソッドの使用方法を示します。この例のリストでは、省略記号で示されているように、出力の一部が表示されていません。

import oml
import pandas as pd
from sklearn import datasets 

# Load the iris data set and create a pandas.DataFrame for it.
iris = datasets.load_iris()
x = pd.DataFrame(iris.data,
                 columns = ['Sepal_Length','Sepal_Width',
                            'Petal_Length','Petal_Width'])
y = pd.DataFrame(list(map(lambda x:
                           {0: 'setosa', 1: 'versicolor',
                            2:'virginica'}[x], iris.target)),
                 columns = ['Species'])

try:
    oml.drop('COST_MATRIX')
    oml.drop('IRIS')
except: 
    pass

# Create the IRIS database table and the proxy object for the table.
oml_iris = oml.create(pd.concat([x, y], axis=1), table = 'IRIS')

# Create  training and test data.
dat = oml.sync(table = 'IRIS').split()
train_x = dat[0].drop('Species')
train_y = dat[0]['Species']
test_dat = dat[1]

# Create a cost matrix table in the database.
cost_matrix = [['setosa', 'setosa', 0], 
               ['setosa', 'virginica', 0.2], 
               ['setosa', 'versicolor', 0.8],
               ['virginica', 'virginica', 0],
               ['virginica', 'setosa', 0.5],
               ['virginica', 'versicolor', 0.5],
               ['versicolor', 'versicolor', 0],
               ['versicolor', 'setosa', 0.4], 
               ['versicolor', 'virginica', 0.6]]
cost_matrix = oml.create(
  pd.DataFrame(cost_matrix, 
               columns = ['ACTUAL_TARGET_VALUE', 
                          'PREDICTED_TARGET_VALUE', 'COST']),
               table = 'COST_MATRIX')

# Specify settings.
setting = {'TREE_TERM_MAX_DEPTH':'2'}

# Create a DT model object.
dt_mod = oml.dt(**setting)

# Fit the DT model according to the training data and parameter
# settings.
dt_mod.fit(train_x, train_y, cost_matrix = cost_matrix)

# Use the model to make predictions on the test data.
dt_mod.predict(test_dat.drop('Species'), 
               supplemental_cols = test_dat[:, ['Sepal_Length', 
                                                'Sepal_Width', 
                                                'Petal_Length', 
                                                'Species']])

# Return the prediction probability.
dt_mod.predict(test_dat.drop('Species'), 
               supplemental_cols = test_dat[:, ['Sepal_Length', 
                                                'Sepal_Width', 
                                                'Species']],
               proba = True)

# Make predictions and return the probability for each class
# on new data.
dt_mod.predict_proba(test_dat.drop('Species'), 
                     supplemental_cols = test_dat[:, 
                       ['Sepal_Length', 
                        'Species']]).sort_values(by = ['Sepal_Length',
                                                       'Species'])

dt_mod.score(test_dat.drop('Species'), test_dat[:, ['Species']])

この例のリスト

>>> import oml
>>> import pandas as pd
>>> from sklearn import datasets
>>>
>>> # Load the iris data set and create a pandas.DataFrame for it.
... iris = datasets.load_iris()
>>> x = pd.DataFrame(iris.data, 
...                  columns = ['Sepal_Length','Sepal_Width',
...                             'Petal_Length','Petal_Width'])
>>> y = pd.DataFrame(list(map(lambda x: 
...                            {0: 'setosa', 1: 'versicolor', 
...                             2:'virginica'}[x], iris.target)), 
...                  columns = ['Species'])
>>>
>>> # Create the IRIS database table and the proxy object for the table.
... oml_iris = oml.create(pd.concat([x, y], axis=1), table = 'IRIS')
>>>
>>> try:
...    oml.drop('COST_MATRIX')
...    oml.drop('IRIS')
... except: 
...    pass
>>>
>>> # Create training and test data.
... dat = oml.sync(table = 'IRIS').split()
>>> train_x = dat[0].drop('Species')
>>> train_y = dat[0]['Species']
>>> test_dat = dat[1]
>>> 
>>> # Create a cost matrix table in the database.
... cost_matrix = [['setosa', 'setosa', 0], 
...                ['setosa', 'virginica', 0.2], 
...                ['setosa', 'versicolor', 0.8],
...                ['virginica', 'virginica', 0],
...                ['virginica', 'setosa', 0.5],
...                ['virginica', 'versicolor', 0.5],
...                ['versicolor', 'versicolor', 0],
...                ['versicolor', 'setosa', 0.4], 
...                ['versicolor', 'virginica', 0.6]]
>>> cost_matrix = oml.create(
...  pd.DataFrame(cost_matrix, 
...               columns = ['ACTUAL_TARGET_VALUE', 
...                          'PREDICTED_TARGET_VALUE',
...                          'COST']),
...               table = 'COST_MATRIX')
>>>
>>> # Specify settings.
... setting = {'TREE_TERM_MAX_DEPTH':'2'}
>>> 
>>> # Create a DT model object.
... dt_mod = oml.dt(**setting)
>>> 
>>> # Fit the DT model according to the training data and parameter
... # settings.
>>> dt_mod.fit(train_x, train_y, cost_matrix = cost_matrix)

Algorithm Name: Decision Tree

Mining Function: CLASSIFICATION

Target: Species

Settings: 
                    setting name            setting value
0                      ALGO_NAME       ALGO_DECISION_TREE
1           CLAS_COST_TABLE_NAME "OML_USER"."COST_MATRIX"
2              CLAS_MAX_SUP_BINS                       32
3          CLAS_WEIGHTS_BALANCED                      OFF
4                   ODMS_DETAILS              ODMS_ENABLE
5   ODMS_MISSING_VALUE_TREATMENT  ODMS_MISSING_VALUE_AUTO
6                  ODMS_SAMPLING    ODMS_SAMPLING_DISABLE
7                      PREP_AUTO                       ON
8           TREE_IMPURITY_METRIC       TREE_IMPURITY_GINI
9            TREE_TERM_MAX_DEPTH                        2
10         TREE_TERM_MINPCT_NODE                      .05
11        TREE_TERM_MINPCT_SPLIT                       .1
12         TREE_TERM_MINREC_NODE                       10
13        TREE_TERM_MINREC_SPLIT                       20

Global Statistics:
   attribute name  attribute value
0        NUM_ROWS              104

Attributes: 
Petal_Length
Petal_Width

Partition: NO

Distributions: 

   NODE_ID TARGET_VALUE  TARGET_COUNT
0        0       setosa            36
1        0   versicolor            35
2        0    virginica            33
3        1       setosa            36
4        2   versicolor            35
5        2    virginica            33

Nodes: 

   parent  node.id  row.count  prediction  \
0     0.0        1         36      setosa   
1     0.0        2         68  versicolor   
2     NaN        0        104      setosa   

                                        split  \
0  (Petal_Length <=(2.4500000000000002E+000))
1   (Petal_Length >(2.4500000000000002E+000))
2                                        None

                                  surrogate  \
0  Petal_Width <=(8.0000000000000004E-001))   
1   Petal_Width >(8.0000000000000004E-001))   
2                                      None   

                                  full.splits  
0  (Petal_Length <=(2.4500000000000002E+000))  
1   (Petal_Length >(2.4500000000000002E+000))  
2                                           (  
>>> 
>>> # Use the model to make predictions on the test data.
... dt_mod.predict(test_dat.drop('Species'), 
...                supplemental_cols = test_dat[:, ['Sepal_Length', 
...                                                 'Sepal_Width', 
...                                                 'Petal_Length', 
...                                                 'Species']])
    Sepal_Length  Sepal_Width  Petal_Length     Species  PREDICTION
0            4.9          3.0           1.4      setosa      setosa
1            4.9          3.1           1.5      setosa      setosa
2            4.8          3.4           1.6      setosa      setosa
3            5.8          4.0           1.2      setosa      setosa
...          ...          ...           ...         ...         ...
44           6.7          3.3           5.7   virginica  versicolor
45           6.7          3.0           5.2   virginica  versicolor
46           6.5          3.0           5.2   virginica  versicolor
47           5.9          3.0           5.1   virginica  versicolor
>>> 
>>> # Return the prediction probability.
... dt_mod.predict(test_dat.drop('Species'), 
...                supplemental_cols = test_dat[:, ['Sepal_Length', 
...                                                 'Sepal_Width', 
...                                                 'Species']], 
...                proba = True)
    Sepal_Length  Sepal_Width     Species  PREDICTION  PROBABILITY
0            4.9          3.0      setosa      setosa     1.000000
1            4.9          3.1      setosa      setosa     1.000000
2            4.8          3.4      setosa      setosa     1.000000
3            5.8          4.0      setosa      setosa     1.000000
...          ...          ...         ...         ...          ...
44           6.7          3.3   virginica  versicolor     0.514706
45           6.7          3.0   virginica  versicolor     0.514706
46           6.5          3.0   virginica  versicolor     0.514706
47           5.9          3.0   virginica  versicolor     0.514706

>>> # Make predictions and return the probability for each class
>>> # on new data.
>>> dt_mod.predict_proba(test_dat.drop('Species'), 
...                      supplemental_cols = test_dat[:, 
...                        ['Sepal_Length', 
...                         'Species']]).sort_values(by = ['Sepal_Length', 
...                                                        'Species'])
    Sepal_Length     Species  PROBABILITY_OF_SETOSA  \
0            4.4      setosa                    1.0   
1            4.4      setosa                    1.0   
2            4.5      setosa                    1.0   
3            4.8      setosa                    1.0   
...          ...         ...                    ...
42           6.7   virginica                    0.0   
43           6.9  versicolor                    0.0   
44           6.9   virginica                    0.0   
45           7.0  versicolor                    0.0   

    PROBABILITY_OF_VERSICOLOR  PROBABILITY_OF_VIRGINICA  
0                    0.000000                  0.000000  
1                    0.000000                  0.000000  
2                    0.000000                  0.000000  
3                    0.000000                  0.000000  
...                       ...                       ...
42                   0.514706                  0.485294  
43                   0.514706                  0.485294  
44                   0.514706                  0.485294  
45                   0.514706                  0.485294  
>>> 
>>> dt_mod.score(test_dat.drop('Species'), test_dat[:, ['Species']])
0.645833