決定木は,回帰と分類の両方を行うことができる教師付き機械学習アルゴリズムとして,最も頻繁に広く使われているものの一つである.決定木アルゴリズムの背後にある直観は単純であるが、非常に強力でもある。
データセットの各属性に対して、決定木アルゴリズムはノードを形成し、最も重要な属性はルートノードに配置される。評価のためには、ルートノードから始めて、条件または「決定」に合致する対応するノードを辿ってツリーを下っていく。このプロセスは、決定木の予測または結果を含む葉ノードに到達するまで続けられる。
このように、意思決定ツリーというのは少し複雑に聞こえるかもしれませんが、実は皆さんも知らず知らずのうちに意思決定のために使っているのです。例えば、ある人から車を1日貸してほしいと頼まれ、車を貸すかどうか決断しなければならない場面を考えてみましょう。決断の材料となる要素はいくつかありますが、そのいくつかを以下に列挙します。
-
- その人は親しい友人か、それとも単なる知り合いか?1.親しい友人なのか、それとも単なる知り合いなのか?
- 2.その人は初めて車を貸してくれるのか?そうであれば車を貸し、そうでなければ次のステップに進む。
-
- 前回車を返したとき、その車は壊れていたか?はい」なら断り、「いいえ」なら貸し出す。
上記のシナリオのデシジョンツリーは次のようになる。
決定木の利点
予測分析に決定木を使用することには、いくつかの利点がある。
-
- 決定木は連続値と離散値の両方の予測に使用できる。すなわち、回帰と分類の両方のタスクでうまく機能する。
-
- アルゴリズムの訓練に必要な労力が比較的少なくて済む。
-
- 非線形分離可能なデータの分類に使用することができる。
-
- KNNや他の分類アルゴリズムと比較して、非常に高速かつ効率的である。
Python Scikit Learnによる決定木の実装
このセクションでは、PythonのScikit-Learnライブラリを使って決定木アルゴリズムを実装します。以下の例では、決定木を使用して、分類と回帰の両方の問題を解決します。
注:分類と回帰の両方のタスクは、Jupyter iPython Notebookで実行されました。
1. 分類のための決定木
このセクションでは、紙幣の画像の4つの異なる属性によって、紙幣が本物か偽物かを予測します。属性とは、ウェーブレット変換された画像の分散、画像の曲率、エントロピー、画像の歪度のことである。
データセット
このタスクのデータセットは、以下のリンクからダウンロードできる。
このデータセットに関するより詳細な情報は、このデータセットのUCI MLレポをチェックしてください。
Scikit-Learnでこのアルゴリズムを実装する残りのステップは、典型的な機械学習問題と同じです。ライブラリとデータセットをインポートし、いくつかのデータ分析を行い、データをトレーニングセットとテストセットに分け、アルゴリズムをトレーニングして予測を行い、最後にデータセットでアルゴリズムの性能を評価します。
ライブラリをインポートする
以下のスクリプトは、必要なライブラリをインポートします。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
データセットのインポート
今回のファイルはCSV形式なので、パンダの read_csv
メソッドを使ってCSVデータファイルを読み込むことにします。以下のスクリプトを実行してください。
dataset = pd.read_csv("D:/Datasets/bill_authentication.csv")
ここでは、「D」ドライブの「Datasets」フォルダに「bill_authentication.csv」というファイルが格納されています。お客様の環境にあわせて変更してください。
データ解析
次のコマンドを実行すると、データセットの行と列の数が表示されます。
dataset.shape
出力は「(1372,5)」となり、データセットには1372レコードと5つの属性があることが分かる。
データセットの最初の5つのレコードを調べるには、次のコマンドを実行する。
dataset.head()
出力はこのようになります。
| 分散|歪度|カートーシズ|エントロピー|クラス
| — | — | — | — | — | — |
| 0 | 3.62160 | 8.6661 | -2.8073 | -0.44699 | 0 |
| 1 | 4.54590 | 8.1674 | -2.4586 | -1.46210 | 0 |
| 2 | 3.86600 | -2.6383 | 1.9242 | 0.10645 | 0 |
| 3 | 3.45660 | 9.5228 | -4.0112 | -3.59440 | 0 |
| 4 | 0.32924 | -4.4552 | 4.5718 | -0.98880 | 0 |
データの準備
このセクションでは、データを属性とラベルに分割し、その結果得られたデータをトレーニングセットとテストセットの両方に分割します。こうすることで、あるデータセットでアルゴリズムを学習させ、その後、アルゴリズムがまだ見ていない全く別のデータセットでテストすることができる。これにより、学習したアルゴリズムが実際にどのように動作するかを、より正確に把握することができる。
データを属性とラベルに分けるには、以下のコードを実行します。
X = dataset.drop('Class', axis=1)
y = dataset['Class']
ここで、変数 X
にはデータセットからラベルである “Class” カラムを除いた全てのカラムが格納されています。y変数には、"Class" カラムの値が格納される。X
変数は属性セットで、y
変数は対応するラベルを格納します。
最後の前処理は、データをトレーニングセットとテストセットに分割することです。Scikit-Learn の model_selection
ライブラリには train_test_split
メソッドが含まれており、これを使ってデータをランダムにトレーニングセットとテストセットに分割します。以下のコードを実行してください。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)
上記のコードでは、test_size
パラメータでテストセットの比率を指定しています。これは、データの20%をテストセット、80%をトレーニングセットに分割するために使用します。
学習と予測
データがトレーニングセットとテストセットに分割されたら、最後のステップはこのデータに対して決定木アルゴリズムを学習させ、予測を行うことである。Scikit-Learnにはtree
ライブラリがあり、様々な決定木アルゴリズム用のクラスやメソッドが組み込まれています。ここでは分類タスクを実行するので、この例では DecisionTreeClassifier
クラスを使用します。このクラスの fit
メソッドは、学習データに対してアルゴリズムを学習するために呼び出されます。このデータは fit
メソッドのパラメータとして渡されます。以下のスクリプトを実行して、アルゴリズムを学習してください。
from sklearn.tree import DecisionTreeClassifier
classifier = DecisionTreeClassifier()
classifier.fit(X_train, y_train)
さて、分類器の学習が終わったら、テストデータに対して予測を行ってみましょう。予測を行うには、DecisionTreeClassifier
クラスの predict
メソッドを用います。使い方は以下の通りです。
y_pred = classifier.predict(X_test)
アルゴリズムの評価
この時点で、我々はアルゴリズムを学習し、いくつかの予測を行った。ここで、我々のアルゴリズムがどの程度正確であるかを見てみましょう。分類タスクでよく使われるメトリクスは、混同行列、精度、再現率、F1スコアです。幸運なことに、Scikit=Learnの metrics
ライブラリには classification_report
と confusion_matrix
メソッドが含まれており、これらのメトリクスを計算するのに利用することが可能です。
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
これは以下のような評価になります。
[[142 2]
2 129]]
precision recall f1-score support
0 0.99 0.99 0.99 144
1 0.98 0.98 0.98 131
avg / total 0.99 0.99 0.99 275
混同行列から、275個のテストインスタンスのうち、我々のアルゴリズムが誤分類したのは4個だけであることがわかります。 これは98.5%の精度です。悪くないですね。
2. 回帰のための決定木
Scikit Learnを用いた決定木による回帰問題の解法は、分類の場合と非常によく似ています。しかし、回帰では木ライブラリの DecisionTreeRegressor クラスを使用します。また、回帰の評価指標は分類の評価指標とは異なります。それ以外のプロセスはほとんど同じです。
データセット
このセクションで使用するデータセットは、線形回帰の記事で使用したものと同じです。このデータセットを使って、ガソリン税(セント)、一人当たり収入(ドル)、舗装された高速道路(マイル)、運転免許を持つ人口の割合に基づいて、米国の48州におけるガソリン消費量(百万ガロン)を予測しようとするものである。
このデータセットは、以下のリンクから入手可能です。
このデータセットの詳細は、原文で確認できる。
上記のデータセットの最初の2列は有用な情報を提供しないので、データセットファイルから削除された。
では、このデータに決定木アルゴリズムを適用して、このデータからガス消費量を予測してみよう。
ライブラリをインポートする
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
データセットのインポート
dataset = pd.read_csv('D:Datasetspetrol_consumption.csv')
データ解析
今回もdataframeのhead
関数を使って、実際にデータがどのようなものかを見ていきます。
dataset.head()
出力はこのようになります。
| | Petrol_tax | Average_income | Paved_Highways | Population_Driver_license(%) | Petrol_Consumption
| 0 | 9.0 | 3571 | 1976 | 0.525 | 541 |
| 1 | 9.0 | 4092 | 1250 | 0.572 | 524 |
| 2 | 9.0 | 3865 | 1586 | 0.580 | 561 |
| 3 | 7.5 | 4870 | 2351 | 0.529 | 414 |
| 4 | 8.0 | 4399 | 431 | 0.544 | 410 |
データセットの統計的な詳細を見るには、次のコマンドを実行します。
dataset.describe()
Petrol_tax | Average_income | Paved_Highways | Population_Driver_license(%) | Petrol_Consumption | |
---|---|---|---|---|---|
カウント|48.000000|48.000000|48.000000|48.000000|48.000000|48.000000|48.000000 | |||||
平均値|7.668333|4241.83333|5565.41667|0.570333|576.770833||。 | |||||
std|0.950770|573.623768|3491.507166|0.055470|111.885816|です。 | |||||
最小値|5.000000|3063.000000|431.000000|0.451000|344.000000||||。 | |||||
25% | 7.000000 | 3739.000000 | 3110.250000 | 0.529750 | 509.500000 |
50% | 7.500000 | 4298.000000 | 4735.500000 | 0.564500 | 568.500000 |
75% | 8.125000 | 4578.750000 | 7156.000000 | 0.595250 | 632.750000 |
最大|10.00000|5342.000000|17782.000000|0.724000|986.000000|||||||。 |
データの準備
分類タスクと同様に、このセクションでは、データを属性とラベルに分割し、その結果、トレーニングセットとテストセットに分割します。
以下のコマンドを実行し、データをラベルと属性に分割します。
X = dataset.drop('Petrol_Consumption', axis=1)
y = dataset['Petrol_Consumption']
ここで、変数 X
には、ラベルである ‘Petrol_Consumption’ カラムを除く、データセットからの全てのカラムが格納されています。y変数には 'Petrol_Consumption' カラムの値が入ります。つまり、
X変数には属性セット、
y` 変数には対応するラベルが入ることになります。
以下のコードを実行し、データをトレーニングセットとテストセットに分割する。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
学習と予測
先に述べたように、回帰タスクでは、分類タスクとは異なる sklearn クラスを使用します。ここで使うクラスは、先ほどの DecisionTreeClassifier
とは異なり、DecisionTreeRegressor
クラスです。
ツリーを学習するために、 DecisionTreeRegressor
クラスをインスタンス化し、 fit
メソッドを呼び出します。
from sklearn.tree import DecisionTreeRegressor
regressor = DecisionTreeRegressor()
regressor.fit(X_train, y_train)
テストセットに対して予測を行うには、 predict
メソッドを用います。
y_pred = regressor.predict(X_test)
それでは、予測値と実際の値を比較して、どの程度の精度であったかを見てみましょう。
df=pd.DataFrame({'Actual':y_test, 'Predicted':y_pred})
df
出力はこのようになります。
| | 実績値 | 予測値
| 41 | 699 | 631.0 |
| 2 | 561 | 524.0 |
| 35 | 644 | 631.0 |
あなたの場合、トレーニングとテストの分割によって、比較されるレコードが異なる可能性があることを忘れないでください。train_test_split` メソッドはランダムにデータを分割するので、おそらく同じトレーニングセットとテストセットを持つことはないでしょう。
アルゴリズムの評価
回帰アルゴリズムのパフォーマンスを評価するために、一般的に使用されるメトリクスは、平均絶対誤差、平均二乗誤差、および二乗平均平方根誤差です。Scikit-Learnライブラリには、これらの値を計算するのに役立つ関数が含まれています。これを行うには、metrics
パッケージの以下のコードを使用します。
from sklearn import metrics
print('Mean Absolute Error:', metrics.mean_absolute_error(y_test, y_pred))
print('Mean Squared Error:', metrics.mean_squared_error(y_test, y_pred))
print('Root Mean Squared Error:', np.sqrt(metrics.mean_squared_error(y_test, y_pred)))
出力はこのようになります。
Mean Absolute Error: 54.7
Mean Squared Error: 4228.9
Root Mean Squared Error: 65.0299930801
このアルゴリズムの平均絶対誤差は54.7で、「Petrol_Consumption」列のすべての値の平均の10%未満です。これは、我々のアルゴリズムがうまく予測できたことを意味します。
さらに上を目指す – 手作りのEnd to Endプロジェクト
好奇心旺盛なあなたは、もっと先を目指したいと思っていませんか?そんなあなたには、ガイド付きプロジェクトがおすすめです。「ハンズオン住宅価格予測 – Pythonによる機械学習” をご覧ください。
をご覧ください。
このプロジェクトでは、Scikit-LearnとKerasのモデルから住宅価格を予測するために、従来の機械学習モデルや深層学習モデル、Ensemble Learning、メタラーを利用した強力な構築方法を学ぶことができます。
>
>
>
Tensorflowの上に構築された深層学習APIであるKerasを使って、アーキテクチャを試し、積み重ねたモデルのアンサンブルを構築し、メタラーナーのニューラルネットワーク(レベル1モデル)を訓練して、家の価格を割り出すことにします。
ディープラーニングは素晴らしいものですが、それに頼る前に、浅い学習アルゴリズムのような、より単純な技術で問題を解決することも試みることをお勧めします。ベースラインの性能は、ランダムフォレスト回帰アルゴリズムに基づくものです。さらに、Scikit-Learnを使用して、バギングや投票などの手法により、モデルのアンサンブルを作成することも検討します。
これはエンドツーエンドのプロジェクトであり、他の機械学習プロジェクトと同様に、探索的データ分析から始まり、データ前処理を経て、最後に浅い学習と深い学習のモデルを構築して、以前に探索とクリーニングを行ったデータに適合させます。
結論
この記事では、Pythonの人気ライブラリScikit-Learnを使って、分類と回帰の両方のタスクに決定木を使用する方法を紹介しました。決定木はそれ自体かなり単純なアルゴリズムですが、Scikit-Learnを使った実装はさらに簡単です。