クッキーもぐもぐ

PC関係とか映画とかゲームとかの

簡単な線形回帰を実装してみる

前置き

機械学習挫折中です(涙

先日、本を買ってすこし勉強+実装してみました。

今回は回帰の実装。

2次元のサンプルデータを元に、関数を予測するもの

大まかな流れ

  1. 学習データ取得

  2. データの標準化

  3. 予測関数と目的関数を設定

  4. 予測関数はa+bxのパラメータ2つ(パラメータは事前に初期化しておく)

  5. 目的関数は今回は最小二乗法を仕様

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()

まとめ

結果はこんな感じでちゃんと予測できている f:id:christmas-cookies:20180819223942p:plain

更新回数(diff)よりも学習率ETAが大きく結果に影響していると、触ってみてわかった。

今後は重回帰のようもやっていきたい