scikit-learn備忘録
pythonの機械学習ライブラリ、scikit-learnの学習を開始したので、備忘録として記事を残します。
決定木による回帰サンプル
決定木に関する学習を開始するために、まずは回帰のサンプルを学習します。
環境はAnaconda3 python3.8で専用の環境を構築して行いました。
あらかじめscikit-learn関係のライブラリとして
- scikit-image
- scikit-learn
- scikit-rf
をインストールしておきます。
実行環境はjupyterです。
これはsin波に決定木で回帰をするサンプルコードです。
Decision Tree Regression
print(__doc__)
# Import the necessary modules and libraries
import numpy as np
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt
# Create a random dataset
rng = np.random.RandomState(1)
X = np.sort(5 * rng.rand(80, 1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - rng.rand(16))
# Fit regression model
regr_1 = DecisionTreeRegressor(max_depth=2)
regr_2 = DecisionTreeRegressor(max_depth=5)
regr_1.fit(X, y)
regr_2.fit(X, y)
# Predict
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]
y_1 = regr_1.predict(X_test)
y_2 = regr_2.predict(X_test)
# Plot the results
plt.figure()
plt.scatter(X, y, s=20, edgecolor="black",
c="darkorange", label="data")
plt.plot(X_test, y_1, color="cornflowerblue",
label="max_depth=2", linewidth=2)
plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=5", linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()
このコードを読んでみることにします。
環境の情報
print(__doc__)
これはドキュメントスリングと呼ばれるもので、モジュールやメソッドのドキュメント、要するに説明を参照できるコードですが、内容は全開もやったので省略します。
必要なライブラリとモジュールのインポート
# Import the necessary modules and libraries
import numpy as np
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt
まず数値計算ライブラリのnumpy、
決定木の決定木回帰分析sklearn.tree.DecisionTreeRegressor、
pythonでグラフを表示する際に使うmatplotlib.pyplotをimportしています。
誤差を含めたデータセットの生成
# Create a random dataset
rng = np.random.RandomState(1)
X = np.sort(5 * rng.rand(80, 1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - rng.rand(16))
まずclass numpy.random.RandomState(seed=None)で疑似乱数(メルセンヌツイスター)のシードを1から生成します。疑似乱数というのがポイントで、これは正確な乱数ではなく、計算すると乱数のような値を出す計算式が内部で走っています。本物の乱数ではなく、疑似乱数を利用するのは、再現性の問題です。本物の乱数を使うと、実行の度に結果が異なるようになってしまい、アルゴリズムの問題等がわかりずらくなってしまうので、シードが同じなら常に同じ反応が返ってくる疑似乱数を使います。
次にシードからデータXを生成します。[numpy.random.rand]
(https://numpy.org/doc/stable/reference/random/generated/numpy.random.rand.html?highlight=rand#numpy.random.rand)では与えた引数の次元の配列が生成されるので、この場合は80行1列の配列が生成され、次にようになります。
この乱数の配列を5倍して、numpyのソートをかけます。numpy.sort
ソートの対象は乱数配列,ソートの軸は配列インデックスの0。これにより昇順にソートされます。
次はyをXからsin関数で作ります。numpy.sinで乱数からsin関数を作った後、numpy.ravelで80行1列の2次元配列を80要素の1次元配列にします。
y[::5]
これはpythonの配列のスライスで組み込み型の
s[i:j:k] s の i から j まで、 k 毎のスライス
のiとjを省略したので、配列の初めから終わりまで、ステップ5のインデックスということになります。つまり、5刻みのインデックスで16個の乱数を0.5から引いて3倍したものを加えているということになります。
これでデータセットの作成が完了しました。
学習モデルの作成
# Fit regression model
regr_1 = DecisionTreeRegressor(max_depth=2)
regr_2 = DecisionTreeRegressor(max_depth=5)
regr_1.fit(X, y)
regr_2.fit(X, y)
sklearn.tree.DecisionTreeRegressorを木の深さ、max_depthの違いで2つ作成して、fitメソッドで学習させています。
学習済みモデルによる推測
# Predict
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]
y_1 = regr_1.predict(X_test)
y_2 = regr_2.predict(X_test)
numpy.arangeにより0.0から5.0まで0.01刻みの配列を作成します。numpy.newaxisで80行1列の配列にしています。
作成した配列を学習済みモデルにpredictメソッドで読み込ませることで、推測させます。
グラフの表示
# Plot the results
plt.figure()
plt.scatter(X, y, s=20, edgecolor="black",
c="darkorange", label="data")
plt.plot(X_test, y_1, color="cornflowerblue",
label="max_depth=2", linewidth=2)
plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=5", linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()
まずグラフオブジェクトを作成します。
plt.figure()
そしてXとyの散布図をデータセットから描画します。
plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")
matplotlib.pyplot.scatter マーカーサイズはs=20、マーカーのエッジの色は黒、マーカーの色はダークオレンジ、 凡例はdataにします。
これにより、5つ毎にランダムなデータの入ったsin波がダークオレンジの点で描写されます(内部で描写されただけで表示されていません)。
深さ2の決定木による推測データを描画します。
plt.plot(X_test, y_1, color="cornflowerblue",
label="max_depth=2", linewidth=2)
matplotlib.pyplot.plot 色は青、ラベルはmax_depth=2、線の幅は2にします。
同様に深さ5の決定木による推測データを描画します。
plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=5", linewidth=2)
こちらは色は黄緑、ラベルはmax_depth=5、線の幅は2にします。
グラフ自体のラベル等を設定します
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
matplotlib.pyplot.xlabel
matplotlib.pyplot.ylabel
matplotlib.pyplot.title
グラフのxラベルはdata,yラベルはtarget,グラフのタイトルはDecision Tree Regressionに設定します。
plt.legend()
plt.show()
matplotlib.pyplot.legend グラフに凡例を描画します。
matplotlib.pyplot.show 最後に内部で描画されていたグラフを表示します。
これで以下のような画像が表示されました。
考察
-
決定木の深さを深くすると外れ値を拾うようになり、オーバーフィットの傾向が出てくる
-
決定木でsin関数の近似は難しい
決定木は連続したデータには向いておらず、非連続なデータに適していることが見て取れました。
離散的なデータに使用することで、閾値で分類することを容易に行えると思われます。