多次元の最小二乗法
多次元の最小二乗法(least squares method)についてまとめます。最小二乗法とは、観測データとの誤差が最小となるような、最も確からしい関係式を求める方法を指します。
また最後にこれらのpythonでの実装方法について記しておきます。
i) 一次関数の場合
一次関数の最小二乗法について。
ここで観測データをもとに、最も誤差が小さくなるa, bの値を導く。
二乗和誤差を
であるから、aとbについてそれぞれを偏微分し、その最小となる値を求めればよい。
aについての偏微分
bを固定し、aについて微分する。
bについての偏微分
以下同様。
(*)
の右辺はaについて見ればaの二次関数であり、また
つまりEの最小値は(1), (2)の導関数が0のときとなる。よって下記の連立方程式を解いてやれば良い。
これを解いてやれば最終的に以下のような値になる。
ii) 行列・ベクトルの場合
多項式の場合の重みベクトルの二乗和誤差を考える。
例えば、m種類の果物が売られていてそれぞれの単価は
購入した個数と合計金額のデータから、最小二乗法を用いて果物の値段wの近似値を求める。
合計金額を多項式で表すと下記になる。
次にxを変数ベクトル、wを係数ベクトルとして表現すると、
と表すことができる。
これを用いると、合計金額yはxの転置行列とwの積であり
と書くことができる。
ここで目標値を
さて、ここでn人の購入データ(観測データ)があるとする。
つまり、上記のベクトルは行列
よって下記の式が成りたつ。
このときの二乗和誤差は、下記のようにノルムの2乗で書くことができる(
ここで
であるので、(3)は式変形して
となる。
i)一次関数で計算したように、wに関してE(w)を微分し、その導関数が0になるwを求めればよい。
先にベクトルの微分の定義を書いておく。
であるから、E(w)の微分は
と式変形することができる。
であるときに、E(w)は誤差が最小となる。
Pythonの実装
ii)の最小二乗法をpythonで実装すると、下記のように書ける。
import numpy as np
def predict_simple_lstsq(X, t):
"""simple least square solution"""
w = np.linalg.inv(X.T @ X) @ (X.T @ t)
return w
def main():
"""
t: 目標値
w: 重み
X: 入力データ
"""
t = np.array([660, 1000, 1670, 770, 890])
X = np.array([[3, 1, 4, 1, 5],
[9, 2, 6, 5, 3],
[5, 8, 9, 7, 9],
[3, 2, 3, 8, 4],
[6, 2, 6, 4, 3]])
w_estimated = predict_simple_lstsq(X, t)
print(w_estimated) # [27.76613348 38.3563155 64.69387755 26.70159956 50.57363486]
if __name__ == '__main__':
main()
補足
pythonにはlinalg.lstsq()
を用いた最小二乗法の解法がある。
def predict_lstsq(X, t):
"""least square solution"""
w = np.linalg.lstsq(X, t, rcond=None)[0]
return w
また、重みが負の実数にならないようなNon-Negative Least Squares (NNLS)も用意されている。例えば上記の果物の例では、商品の値段が負の実数であることはあり得ないため、上述の単純な最小二乗法を用いることはできない。
from scipy.optimize import nnls
def predict_nnls(X, t):
"""non-negative least square solution"""
w = nnls(X, t)[0]
return w
これらについては別記事でまとめる。
Discussion