はじめに
決定木は、質問を繰り返すことでデータを分類するモデルです。それは「もし〜ならば」の連続で、データに含まれるパターンを学習します。このプロセスは、実際の木の枝分かれに似ており、それぞれの分岐がデータの特徴に基づいた質問に対応しています。最終的に、モデルはデータを特定のクラスに分類する結論に達します。
実装手順
1. ライブラリのインポート
まずは、Pythonでデータサイエンスを行う上で必要な基本的なライブラリをインポートします。numpy
は数値計算を効率的に行うため、pandas
はデータの操作や分析を行うため、matplotlib.pyplot
はグラフを描画するために使用します。
2. データセットのインポート
機械学習の実験にはデータセットが必要です。ここでは、sklearn
ライブラリから提供されるワインデータセットを使用します。このデータセットには、ワインの化学的分析結果が含まれており、3つの異なる種類のワインを分類するために使用できます。
データセットの説明
- 178サンプルのワインデータが含まれています。
- 13種類の異なる特徴量(例:アルコール度数、マグネシウムの量など)があります。
- 目的は、これらの特徴量を基にワインの種類を予測することです。
from sklearn import datasets
dataset = datasets.load_wine()
# データセットの特徴量をDataFrameに変換
df = pd.DataFrame(dataset.data, columns=dataset.feature_names)
# 目標変数(ターゲット)をDataFrameに追加
df['target'] = dataset.target
3. データセットの確認
データセットの概要を確認し、特徴量と目的変数を確認します。また、データの形状や欠損値の有無もチェックします。
pd.set_option('display.max_columns', None)
df.head()
出力:

print(f'データの形式:{df.shape}')
print(f'欠損値の数:{df.isnull().sum().sum()}')
出力:
データの形式:(178, 14)
欠損値の数:0
4. 相関関係の確認
特徴量間の相関関係を調べます。相関関係を知ることで、どの特徴量が目標変数に強い影響を与える可能性があるかを把握することができます。df.corr()
はDataFrame内の全ての特徴量間の相関係数を計算し、それらの関係を示す表を返します。相関係数は-1から1までの値を取り、1に近いほど正の相関が、-1に近いほど負の相関が、0に近いほど相関がないことを示します。
corr_matrix = df.corr() # 相関行列を計算
# "target"との相関が高い順に列を並び替える
sorted_columns = corr_matrix.abs().sort_values('target', ascending=False).index
# 並び替えた列順でDataFrameの相関行列を表示
sorted_corr_matrix = corr_matrix[sorted_columns].loc[sorted_columns]
sorted_corr_matrix
出力:

5. 説明変数と目的変数に分割
データセットを、説明変数(特徴量)と目的変数(予測したい値)に分割します。この例では、前ステップで目的変数(target
)と相関関係が強い特徴量flavanoids
とod280/od315_of_diluted_wines
の2つの特徴量を説明変数として選択し、ワインの種類を目的変数とします。
X = df.loc[:, ['flavanoids','od280/od315_of_diluted_wines']].values
y = df.loc[:, 'target'].values
6. 訓練データとテストデータに分割
モデルの性能を評価するためには、データセットを訓練データとテストデータに分割します。一般的にはデータの75%を訓練に、残りの25%をテストに使用します。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)
7. 特徴量のスケーリング
多くの機械学習アルゴリズムでは、入力特徴量が同じスケールになっていないと性能が落ちることがあります。例えば、ある特徴量が0から1の間で変動し、別の特徴量が100から1000の間で変動する場合、後者の特徴量が結果に大きな影響を与えがちです。これを防ぐために、特徴量のスケーリングを行います。StandardScaler
は特徴量を標準化するために用いられ、各特徴量の平均を0、標準偏差を1に調整します。
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
8. 訓練データによるモデルの学習
学習したモデルを訓練データに適合させます。これにより、新しいデータポイントに対する予測が可能になります。
from sklearn.tree import DecisionTreeClassifier
classifier = DecisionTreeClassifier(criterion = 'entropy', max_depth=3, random_state = 0)
classifier.fit(X_train, y_train)
9. 新しいデータセットで予測
学習したモデルを使って、新しいデータポイントがどのクラスに属するかを予測します。ここでは、新しいデータポイントの特徴量をnew_data
に設定し、predict
メソッドを用いて予測を行っています。データのスケーリングも忘れずに行います。
new_data = [[3.00,3.50]]
print(f'Wine_class_{classifier.predict(sc.transform(new_data))[0]}')
出力:
Wine_class_0
10. テストデータで予測
テストデータセットを使って、モデルがどの程度正確に予測できるかを評価します。predict
メソッドにテストデータセットを渡し、予測結果を取得します。
y_pred = classifier.predict(X_test)
11. 混同行列の作成と性能確認
混同行列はモデルの性能を評価するための有用なツールです。実際のクラスと予測されたクラスを比較して、どれだけ正確に予測できたか、どのような間違いがあったかを視覚的に理解できます。confusion_matrix
を使って混同行列を生成し、accuracy_score
で正解率(全データの中で正しく予測できた割合)を計算します。
from sklearn.metrics import confusion_matrix, accuracy_score
cm = confusion_matrix(y_test, y_pred)
print(cm)
accuracy_score(y_test, y_pred)
出力:
[[16 0 0]
[ 6 13 2]
[ 0 0 8]]
0.8222222222222222
12. 訓練データの結果の可視化
訓練データに基づいてモデルの予測結果をグラフに可視化します。これにより、モデルがどのようにデータを分類しているかを直感的に理解することができます。特徴量を標準化してモデルを訓練したので、元のスケールに戻してからグラフを描画します。
#可視化範囲の設定
from matplotlib.colors import ListedColormap
X_train_set, y_train_set = sc.inverse_transform(X_train), y_train
X_test_set, y_test_set = sc.inverse_transform(X_test), y_test
X1, X2 = np.meshgrid(np.arange(start = np.concatenate((X_train_set[:, 0], X_test_set[:, 0])).min() - 0.1, stop = np.concatenate((X_train_set[:, 0], X_test_set[:, 0])).max() + 0.1, step = 0.005),
np.arange(start = np.concatenate((X_train_set[:, 1], X_test_set[:, 1])).min() - 0.05, stop =np.concatenate((X_train_set[:, 1], X_test_set[:, 1])).max() + 0.05, step = 0.005))
plt.contourf(X1, X2, classifier.predict(sc.transform(np.array([X1.ravel(), X2.ravel()]).T)).reshape(X1.shape),
alpha = 0.50, cmap = ListedColormap(('red', 'blue','green')))
plt.xlim(X1.min(), X1.max())
plt.ylim(X2.min(), X2.max())
for i, j in enumerate(np.unique(y_train_set)):
plt.scatter(X_train_set[y_train_set == j, 0], X_train_set[y_train_set == j, 1], c = ListedColormap(('red', 'blue','green'))(i), label=f'Wine_{dataset.target_names[j]}')
plt.title('Decision Tree Classification (Training set)')
plt.xlabel('flavanoids')
plt.ylabel('od280/od315_of_diluted_wines')
plt.legend()
plt.show()
出力:

13. テストデータの結果の可視化
同様に、テストデータに対する予測結果もグラフにして可視化します。これにより、モデルが未知のデータに対してどのような予測を行うかを確認できます
plt.contourf(X1, X2, classifier.predict(sc.transform(np.array([X1.ravel(), X2.ravel()]).T)).reshape(X1.shape),
alpha = 0.50, cmap = ListedColormap(('red', 'blue','green')))
plt.xlim(X1.min(), X1.max())
plt.ylim(X2.min(), X2.max())
for i, j in enumerate(np.unique(y_test_set)):
plt.scatter(X_test_set[y_test_set == j, 0], X_test_set[y_test_set == j, 1], c = ListedColormap(('red', 'blue','green'))(i), label=f'Wine_{dataset.target_names[j]}')
plt.title('Decision Tree Classification (Test set)')
plt.xlabel('flavanoids')
plt.ylabel('od280/od315_of_diluted_wines')
plt.legend()
plt.show()
出力:

14. 条件分岐の可視化
決定木モデルの強力な側面の一つは、その決定プロセスを可視化しやすいことです。条件分岐の可視化は、モデルがどのようにデータを分割し、最終的に予測を行うかを理解するのに役立ちます。このプロセスは、決定木の各ノード(分岐点)が質問に相当し、それに応じてデータが左右のブランチに分岐していく様子を図式化したものです。
import graphviz
from IPython.display import Image
import pydotplus
from sklearn.tree import export_graphviz
dot_data = export_graphviz(classifier, filled=True, rounded=True,
feature_names=['flavanoids','od280/od315_of_diluted_wines'],
class_names=['0','1','2'],
out_file=None)
graph = graphviz.Source(dot_data)
png_bytes = graph.pipe(format='png')
Image(png_bytes)
出力:

まとめ
このホームページでは、決定木を用いた分類の基本的な流れを、ステップバイステップで説明しました。各ステップは、機械学習モデルの開発における重要なプロセスをカバーしています。初学者でもこのページを通じて、決定木分類の基礎を理解し、実際にコードを書いてみましょう。
本コンテンツへの意見や質問