SVRのパラメーターの調整

%matplotlib inline
%precision 3
import pandas as pd, matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.svm import SVR
from sklearn.metrics import r2_score

df = pd.read_csv("input/boston.csv")  # ボストン市の住宅価格データ一式
X, y = df[['RM', 'LSTAT']], df["MEDV"]

# トレーニングデータとテストデータに分割
X_train, X_test, y_train, y_test = (
    train_test_split(X, y, random_state=0))
# SVRで確認
svr = SVR(gamma='scale')
svr.fit(X_train, y_train)
y_pred = svr.predict(X_test)
score1 = r2_score(y_test, y_pred)
float(score1)

%precision 3とすると、出力時に小数点以下3桁で表示します。
ただし、NumPyの多次元配列の要素の場合は、この指定が有効になりません。その場合は、float(…)でfloatに変換しています。

0.545
def scatter(y_pred, y):
    plt.gca().set_aspect('equal', adjustable='box')  # 縦横比を1
    plt.ylabel('y_test')
    plt.xlabel('y_pred')
    plt.plot([y.min(), y.max()], [y.min(), y.max()])  # 斜め45度の青い線
    plt.plot(y_pred, y, '.')
# 予測データ(y_pred)と真値(y_test)を描画
scatter(y_pred, y_test)

データは、ボストン市の住宅価格データを使います。
このデータは、線形のモデルだと高価格帯が予測しづらいです。

SVRのオプション

オプションデフォルト説明
kernel‘rbf’'rbf', 'linear', 'poly'などのカーネル
degree3kernel='poly'としたときの次数
gamma'scale'kernel='rbf'としたときのパラメーター
C1ペナルティ項の係数

kernelオプションのデフォルトは、’rbf’(radial basis function kernel)です。データに対する事前情報がない場合によく用いられます。外れ値の影響も受けにくいです。

kernel=’rbf’のときに重要なオプションは、Cとgammaです。

この練習では、トレーニングデータとテストデータに分割しましたが、以降では、クロスバリデーションを使います。

グリッドサーチ

サポートベクターマシン回帰のオプションCとgammaの値を、グリッドサーチで探索します

# 前回のプログラムの読込
%run 1.ipynb
# グリッドサーチで探索
from sklearn.model_selection import GridSearchCV
gscv = GridSearchCV(SVR(), {
    'C': [50, 60, 70, 80, 90],
    'gamma': [0.04, 0.05, 0.06, 0.07, 0.08]},
    scoring='r2', cv=3)
gscv.fit(X_train, y_train)
y_pred = gscv.predict(X_test)
score2 = r2_score(y_test, y_pred)
float(score2)
0.648
# 選択されたパラメーター
gscv.best_params_
{'C': 70, 'gamma': 0.060}
# 予測データ(y_pred)と真値(y_test)を描画
scatter(y_pred, y_test)

グリッドサーチでは、与えられたオプションの組合せを全て探索します。
sklearn.model_selection.GridSearchCVを使うと、各探索の中で、クロスバリデーションで評価します。

GridSearchCVでは、ベースになるモデルと、そのモデルのオプションを辞書で指定します。

gscv = GridSearchCV(SVR(), {
    'C': [50, 60, 70, 80, 90],
    'gamma': [0.04, 0.05, 0.06, 0.07, 0.08]})

たとえば、上記のモデルを使うと、gscv.fitで、下記のように探索し、最も良いモデルを選択します。選んだパラメーターは、gscv.best_params_で確認できます。

# このコードはイメージです
for C in [50, 60, 70, 80, 90]:
    for gamma in [0.04, 0.05, 0.06, 0.07, 0.08]:
        svr = SVR(C=C, gamma=gamma)
        # クロスバリデーションでsvrを評価

問題の解説

計算時間の都合上、探索範囲は、意図的に決めています。
評価関数はscoringオプションで指定できます。r2では決定係数を使います。
クロスバリデーションの分割数は、cvオプションで設定できます。デフォルトは3です。

選択されたパラメーターを使った決定係数は、0.648となり、1問目の0.545を上回りました。散布図で見てみると、線形回帰で難しかった高価格帯もかなりフィッティングしています。

検索範囲の決定の仕方

探索範囲は、最初に大きな範囲で粗く探索して、あたりをつけると良いでしょう。
範囲が広い場合は、候補を[0.01, 0.1, 1, 10, 100]のように等比数列を使うと候補数を減らせます。
その後、あたりのつけた周辺で、細かく探すことになります。

クロスバリデーションする場合は、トレーニングデータとテストデータに分割せずに、gscv.fit(X, y)とした方がデータを有効に使えます。

しかし、今回はグリッドサーチの効果を比較しやすいように、分割して作ったトレーニングデータでグリッドサーチをしています。

コメント

タイトルとURLをコピーしました