■ はじめに
https://dk521123.hatenablog.com/entry/2020/03/02/233902
https://dk521123.hatenablog.com/entry/2020/03/08/113356
https://dk521123.hatenablog.com/entry/2020/04/04/021413
https://dk521123.hatenablog.com/entry/2020/07/04/000000
の続き。 今回は、リッジ回帰について扱う。 scikit-learn を使えば、簡単に実装できる。
目次
【1】リッジ回帰 (Ridge Regression; RR) 補足:関連用語 a) 正則化 (Regularization) b) 線形回帰(Linear Regression) c) 単回帰分析 / 重回帰分析 【2】サンプル 例1:Hello world 例2:株価予測
【1】リッジ回帰 (Ridge Regression; RR)
* 線形回帰のコスト関数に学習した重みの二乗(L2正則化項)を加えたもの => 他にも「ラッソ回帰(Lasso Regression)」や 「エラスティックネット(Elastic Net)」などがある 詳細は、以下の関連記事を参照のこと。
https://dk521123.hatenablog.com/entry/2020/11/29/193247
特徴
* 最小二乗法による線形回帰(※補足)よりもノイズの影響を受けにくい * リッジ回帰の正規化を強くし過ぎると平均値になる
補足:関連用語
a) 正則化 (Regularization)
* 過学習(Over-fitting)を防ぐために、モデルが複雑になりすぎないように制約する ⇒ モデルに対して、ノイズが過度に影響しないようにするためのパラメータ * L2正則化項による正則化では、0にはならない性質がある
b) 線形回帰(Linear Regression)
* ある変数 x (説明変数と呼ぶ)が与えられた時、 相関のある y (目的変数と呼ぶ)を予測すること * 教師あり学習 * Schoo の以下から勉強できる
c) 単回帰分析 / 重回帰分析
* 説明変数 x が1つ(1次元)の場合、 「単回帰分析(Simple linear regression analysis)」、 説明変数 x が複数の場合、 「重回帰分析(Multiple-linear regression analysis)」 => 単回帰分析: y=ax+b、重回帰分析: y=w1x1+w2x2+w3x3+w0
モデル | 予測モデル式 | パラメータ | 特徴量 |
---|---|---|---|
単回帰 | y = θ0 + θ1*X1 | 線形 | 線形 |
重回帰 | y = θ0 + θ1X1 + θ2X2 + ... + θn*Xn | 線形 | 線形 |
多項式回帰 | y = θ0 + θ1X + θ2X2 + ... + θn*Xn | 線形 | 非線形 |
【2】サンプル
例1:Hello world
from sklearn import linear_model import matplotlib.pyplot as plt x = [[1], [3], [2], [4], [5], [7], [6], [8], [10]] y = [3, 2, 4, 5, 7, 6, 8, 10, 9] # リッジ回帰インスタンス作成 # alpha(α)は、ハイパーパラメータで大きいと正則化が強くなる ridge_model = linear_model.Ridge(alpha=0, fit_intercept=True) ridge_model.fit(x, y) predicted_y = ridge_model.predict(x) plt.plot(x, predicted_y) plt.plot(x, y, 'o') print("傾き = {}".format(ridge_model.coef_)) print("切片 = {}".format(ridge_model.intercept_)) ridge_model.set_params(alpha=100) predicted_y = ridge_model.predict(x) plt.plot(x, predicted_y) plt.plot(x, y, 'o') print("傾き = {}".format(ridge_model.coef_)) print("切片 = {}".format(ridge_model.intercept_)) ridge_model.set_params(alpha=10000) predicted_y = ridge_model.predict(x) plt.plot(x, predicted_y) plt.plot(x, y, 'o') print("傾き = {}".format(ridge_model.coef_)) print("切片 = {}".format(ridge_model.intercept_)) plt.show()
出力結果
傾き = [0.81290323] 切片 = 1.845161290322582 傾き = [0.33157895] 切片 = 4.305263157894737 傾き = [0.00556169] <= 傾きがほとんどなくなる(0に近づく) 切片 = 5.9715736040609135
例2:株価予測
株価の過去データ(今回は、10日分)を使い、 1日先のデータを予測するプログラムを作成する。
データについて
* セントルイス連邦準備銀行のFRED(Federal Reserve Economic Data)の NSDAQ の株価データを使って、リッジ回帰を行う。
https://fred.stlouisfed.org/
事前準備
conda install pandas-datareader
プログラム
import numpy as np import matplotlib.pyplot as plt import pandas_datareader.data as web from sklearn.metrics import mean_squared_error from sklearn import linear_model def reshape(data_frame, input_day, period): x = [] y = [] for i in range(input_day, len(data_frame) - period): x.append(data_frame[i-input_day: i]) y.append(data_frame[i+period][-1]) x = (np.array(x)).reshape(len(x), input_day) y = np.array(y) return x, y # リッジ回帰でモデルを作り予測する def get_predicted_y_by_ridge(x, y, input_day, alpha=1): ridge_model = linear_model.Ridge( alpha=alpha, fit_intercept=True) predicted_y = [] for i in range(input_day + 1, len(x)): input_x = x[:i-input_day] input_y = y[:i-input_day] temp_x = x[i] ridge_model.fit(input_x, input_y) predict = ridge_model.predict([temp_x])[0] predicted_y.append(predict) return np.array(predicted_y) # NASDAQデータダウンロード data_frame = web.DataReader( "NASDAQCOM", "fred", "1971/1/1", "2020/4/1").dropna() # data_frame.columns = ['Close'] # data_frame.plot() clone_data_frame = np.log(data_frame).values.copy() # 予想に使うデータの日数 input_day = 10 # 予測の期間 period = 1 x, y = reshape(clone_data_frame, input_day, period) predict_y = get_predicted_y_by_ridge(x, y, input_day) # 実際の実測値をグラフ化 plt.plot(y[1:], label="Close") # リッジ回帰のモデルで予測した値をグラフ化 plt.plot(predict_y[1:], label="Prediction") plt.legend() # 予測にどれくらい誤差があるのかを計算する prediction_error = mean_squared_error( y[input_day+1:], predict_y) benchmark = mean_squared_error( y[period:], y[:-period]) print( "予測誤差", prediction_error, "ベンチマーク", benchmark) # グラフに表示 plt.show()
出力結果
予想誤差 0.00039215988425432406 ベンチマーク 0.0001556225921818145
関連記事
scikit-learn ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/03/02/233902
scikit-learn ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2020/03/08/113356
scikit-learn ~ 線形回帰 ~
https://dk521123.hatenablog.com/entry/2020/07/04/000000
scikit-learn ~ 重回帰 / ロッソ回帰・エラスティックネット ~
https://dk521123.hatenablog.com/entry/2020/11/29/193247
scikit-learn ~ 決定木 / ランダムフォレスト ~
https://dk521123.hatenablog.com/entry/2020/04/04/021413
Matplotlib ~ グラフ描画ライブラリ ~
https://dk521123.hatenablog.com/entry/2020/03/01/000000
パターン認識について
https://dk521123.hatenablog.com/entry/2013/12/16/225948
機械学習を勉強する際のデータセットについて
https://dk521123.hatenablog.com/entry/2020/03/28/131839