0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

scikit-learn 決定木によるsin関数回帰サンプル

Posted at

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列の配列が生成され、次にようになります。

80行乱数.png

この乱数の配列を5倍して、numpyのソートをかけます。numpy.sort
ソートの対象は乱数配列,ソートの軸は配列インデックスの0。これにより昇順にソートされます。
npsort.png
次は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()

matplotlib.pyplot.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 最後に内部で描画されていたグラフを表示します。

これで以下のような画像が表示されました。

決定木.png

考察

  • 決定木の深さを深くすると外れ値を拾うようになり、オーバーフィットの傾向が出てくる

  • 決定木でsin関数の近似は難しい

決定木は連続したデータには向いておらず、非連続なデータに適していることが見て取れました。
離散的なデータに使用することで、閾値で分類することを容易に行えると思われます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?