非エンジニアサラリーマンがお届けする、コピペでできる機械学習シリーズの決定木の回帰編です。決定木は以前も分類問題で紹介しましたが、今回は回帰問題です。
- 分類問題は分けるもの
- 回帰問題は量を予測するもの
問題解決にコードは最低限でいいと考えています。コードはコピーして、データ収集や結果の解釈に力を注いで下さい。だれでも、すぐに実践できるようにscikit-learnのデータセットを使います。また、自身のデータでもすぐにコピペできるように、scikit-learnのデータセットを一旦データフレームにしてから機械学習を実施していきます。
環境構築は、【2020年最新】Anacondaのインストール方法
それでは、やっていきましょう!
必要なライブラリ―をインポート
import pandas as pd import numpy as np from sklearn.datasets import load_boston import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns import warnings warnings.filterwarnings('ignore')
今回のデータセットはscikit-learnのデータセットにあるbostonを使用します。
データセットを整える
目的変数:住宅価格(の中央値)
説明変数:目的変数に関係しそうな、さまざまなデータ
boston = load_boston() df = pd.DataFrame(data = boston.data, columns = boston.feature_names) df['PRICE'] = boston.target df
上のコードはデータフレームにするためのコードです。
bostonのデータセットで実践する場合は上のコードを実行して下さい。
自身のデータを使用する場合は、以下のコードから実行して下さい。
機械学習がしやすいデータの形に整える
X = df.iloc[:,:-1].values # 説明変数(最後の列以外) y = df.iloc[:,-1].values # 目的変数(最後の列のみ)
訓練用のデータとテスト用のデータに分割する
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 = 1)
決定木回帰分析
from sklearn.tree import DecisionTreeRegressor from sklearn.model_selection import GridSearchCV dtr = DecisionTreeRegressor(random_state=0) gs_dtr = GridSearchCV(dtr, param_grid = {'max_depth': [2, 3, 4, 5]}, cv = 10) gs_dtr.fit(X_train, y_train) y_train_pred = gs_dtr.predict(X_train) y_test_pred = gs_dtr.predict(X_test) gs_dtr.best_estimator_
出力:
DecisionTreeRegressor(max_depth=4, random_state=0)
もっとも精度が高かったのは、4回分割(max_depth=4)するものであった。
決定木回帰による予測結果と実際の結果との関係を可視化してみる
plt.scatter(y_test, y_test_pred) plt.savefig('test_pred_plot.jpg')
各点が、右肩上がりの直線に近いほうが当てはまりが良い。
plt.scatter(y_train_pred, y_train_pred - y_train, c='steelblue', marker='o', edgecolor='white', label='Training data') plt.scatter(y_test_pred, y_test_pred - y_test, c='limegreen', marker='s', edgecolor='white', label='Test data') plt.xlabel('Predicted values') plt.ylabel('Residuals') plt.legend(loc='upper left') plt.hlines(y=0, xmin=-10, xmax=50, color='r', lw=1.5, alpha=0.5) plt.xlim([-10, 50]) plt.tight_layout() plt.savefig('graph_dtr.jpg') plt.show()
出力:
各点が赤線に近いほうが当てはまりが良い。まあ、悪くはないかな、という感じですかね。
モデルの評価(決定木回帰)
from sklearn.metrics import r2_score from sklearn.metrics import mean_squared_error print('MSE train: %.3f, test: %.3f' % ( mean_squared_error(y_train, y_train_pred), mean_squared_error(y_test, y_test_pred))) print('RMSE train: %.3f, test: %.3f' %( np.sqrt(mean_squared_error(y_train, y_train_pred)), np.sqrt(mean_squared_error(y_test, y_test_pred)))) print('R^2 train: %.3f, test: %.3f' % ( r2_score(y_train, y_train_pred), r2_score(y_test, y_test_pred)))
出力:
MSE train: 9.036, test: 13.826
RMSE train: 3.006, test: 3.718
R^2 train: 0.886, test: 0.860
MSE:小さいほうが当てはまりがよい
RMSE:小さいほうが当てはまり良い
R²:1に近いほうが良い
訓練データ(train)と、テストデータ(test)で上の評価を実施する。
以前紹介した、線形回帰(R²train:0.717、R²test:0.779)やRidge回帰(R²train:0.715、R²test:0.778)、Lasso回帰(R²train:0.717、R²test:0.779)の結果より良いことが分かります。
下のコードで、予測とテストの差をヒストグラムで可視化する。
一応、正規分布になっているほうが、いいとされています。
sns.distplot((y_test-y_test_pred),bins=50)
決定木回帰回帰の可視化
from sklearn import tree from IPython.display import Image from sklearn.tree import export_graphviz from pydotplus import graph_from_dot_data feature_names = df.iloc[:,:-1].columns # もとのデータフレームの最後の列以外の説明変数名を指定 dot_data = export_graphviz(gs_dtr.best_estimator_, filled=True, rounded=True, feature_names = feature_names) graph = graph_from_dot_data(dot_data) Image(graph.create_png())
一番上は、LSTATが9.755以下はTrue、LSTATが9.755より大きかったらFalseに向かう。
from dtreeviz.trees import dtreeviz viz = dtreeviz(gs_dtr.best_estimator_, X_train, y_train, feature_names=feature_names, target_name='PRICE' ) display(viz)
出力:
縦の点線がしきい値、横の点線がしきい値で分けたときの各平均値を表しています。
回帰問題でも分かりやすく表してくれています。
コメント