えんじにあのじゆうちょう

勉強したことを中心にアウトプットしていきます。

線形回帰をコンピュータによる数値計算、機械学習で解いてみる

はじめに

t.marufeuille.dev

前回のエントリの実装編です。
あえて直接的な既存ライブラリは用いず、numpyくらいで実装してみます。

解説

問題設定

  • irisデータセットを使って、ガク片の長さからガク片の幅を予測します。
  • 全てのコードはgithubにありますので、参考にしてください。このエントリでは概要だけ摘んで解説します。

github.com

  • また、本エントリでは最小二乗法を行列計算で解いたものと二乗和誤差について解説しますが、コード例には行列計算ではなく普通に最小二乗法を解いたバージョンも載せていますので、併せて参考にしてください。

計算用関数

f(x) = \omega_0+\omega_1xを計算する関数fを用意します。
パラメータ\omegaxを受け取ることで計算結果を返すようにしています。

def f(w, x):
    return  w[0] + w[1] * x

最小二乗法の行列計算

パラメータである\omega\omega = (X^TX)^{-1}X^TYで求められるのでした。コードサンプルは以下のようになります。

w = np.dot(
    np.dot(
        np.linalg.inv(
            np.dot(
                x.T,
                x
            )
        ),
        x.T
    ),
    y
)

np.linalg.invは逆行列を求める関数、np.dotは内積計算を行う関数です。
直接的に\omegaを求めるため、データが同じであれば必ず同じ結果になります。

二乗和誤差を用いた \omegaの獲得

二乗和誤差を用いる場合、まずは適当な\omegaを設定して、それを少しずつ更新していきます。

eta = 0.001
w = np.random.rand(2)
max_iter = 100

for i in range(0, max_iter):
    y_hat = f(w, x[:,1])
    grad = np.dot((y - y_hat), x[:,1]) / len(x[:,1])
    w = w + eta * grad

ここでは\omegaは初期値としてnp.random.randで与えています。
etaは学習率で、この学習率分だけ\omegaを更新していきます。
その後、予測値を得る、二乗和誤差の傾きを利用して\omegaを更新という流れをmax_iter回(デフォルト100回)繰り返すことで\omegaが確定します。

このような求め方をするため、\omegaの初期値によって求められる結果はやや変化する点に注目してください。

まとめ

このエントリでは線形回帰の問題をコンピュータによる数値計算の例として最小二乗法と、機械学習のアプローチ的に誤差関数を二乗和誤差を使った、2つの方法で解いてみました。
統計学の方は\omega = (X^TX)^{-1}X^TYという数式を解くだけで一発で計算を行うことができました。
機械学習の方は真の値と予測値の誤差を見ながら、少しずつパラメータを調整しながら最適値に少しずつ近づけていくと言う処理をしています。

どちらも同じようなテクニックを使っていますが、どちらも目の付け所が異なり、片方はデータとの関連性、片方は結果のみをみていることがよくわかります。

機械学習について、今回は二乗和誤差という関数を利用しましたが、クロスエントロピー誤差という方法もよく利用されます。
また別の回で、誤差関数についてもう少し詳しく見ていこうと思います。