簡単な線形回帰を実装してみる
前置き
機械学習挫折中です(涙
先日、本を買ってすこし勉強+実装してみました。
今回は回帰の実装。
2次元のサンプルデータを元に、関数を予測するもの
大まかな流れ
学習データ取得
データの標準化
予測関数と目的関数を設定
予測関数はa+bxのパラメータ2つ(パラメータは事前に初期化しておく)
目的関数は今回は最小二乗法を仕様
6.目的関数を微分した式を元に、パラメータ更新の式を作成(a,bそれぞれに関して)
7.パラメータの更新前後で目的関数を比べ、差が一定以下になるまでひたすら更新していく
8.最終的なパラメータを元に、予測関数を決定、グラフに表示 (今回は評価はしない)
書いたコード
import numpy as np import matplotlib.pyplot as plt #パラメータ初期化 theta0 = np.random.rand() theta1 = np.random.rand() #予想関数 def predict_f(x,theta0,theta1): return theta0+theta1*x #目的関数 def E(x,y,theta0,theta1): return 0.5*(np.sum(y-predict_f(x,theta0,theta1))**2) #標準化 def zscore(x): mu = x.mean() sigma = x.std() return (x - mu)/sigma def predict_theta(train_z,train_y,theta0,theta1): #誤差の計算 error = E(train_z,train_y,theta0,theta1) #パラメータ設定 ETA = 1e-3 #学習率 diff = 1 #誤差の差分の初期値 count = 0 #更新回数初期化 while diff > 1e-3: #更新パラメータを求める tmp0 = theta0 - ETA*(np.sum(predict_f(train_z,theta0,theta1)-train_y)) tmp1 = theta1 - ETA*(np.sum((predict_f(train_z,theta0,theta1)-train_y)*train_z)) #パラメータの更新 theta0 = tmp0 theta1 = tmp1 #更新後の誤差を求める current_error = E(train_z,train_y,theta0,theta1) #誤差がどれだけ変わったか diff = error - current_error error = current_error count += 1 return theta0, theta1 #学習データ読み込み train = np.loadtxt("click.csv",delimiter=',',skiprows=1)#delimiter区切り文字指定,skiprows n行目まで飛ばす train_x = train[:,0] train_y = train[:,1] #データの正規化 train_z = zscore(train_x) theta0,theta1 = predict_theta(train_z,train_y,theta0,theta1) print (theta0) print (theta1) x = np.linspace(-3,3,100) print (predict_f(x,theta0,theta1)) #plot # plt.plot(train_x,train_y,'o') plt.plot(train_z,train_y,'o') plt.plot(x,predict_f(x,theta0,theta1),'o') plt.show()
まとめ
結果はこんな感じでちゃんと予測できている
更新回数(diff)よりも学習率ETAが大きく結果に影響していると、触ってみてわかった。
今後は重回帰のようもやっていきたい