LemonteaのUnity部屋

C#とかのお話です~

機械学習 D次元線形回帰モデル

こんにちは。レモンティーです。

前回、入力が1次元の時の直線モデルの解析解を求めました。
sawalemounity.hatenablog.com

今回は、入力がD次元の場合に一般化してみます。
つまり、就寝時間以外にも
天候、気温、使用した枕との相性…などなど
D個の要素を考慮して起床時間を求める場合のことですね。

この場合でも、
{\displaystyle
y(x) = w_0x_0 + w_1x_1 + … + w_{D-1}x_{D-1} + w_D 
}
と置いてyとtの2乗平均誤差Jが最小になるwを求めることで
モデルを作ることができます。

ですがまずは簡単にするために
{\displaystyle
y(x) = w_0x_0 + w_1x_1 + … + w_{D-1}x_{D-1} 
}
について考えていきます。
以下
{\displaystyle
w = \begin{pmatrix}
w_0 \\ w_1 \\ … \\ w_{D-1}
\end{pmatrix}
}

{\displaystyle
X = \begin{pmatrix}
x_{0,0} & x_{0,1} & … & x_{0,D-1} \\ x_{1,0} & x_{1,1} & … & x_{1,D-1} \\ … & … & … & … \\ x_{N-1,0} & x_{N-1,1} & … & x_{N-1,D-1}
\end{pmatrix}
}

{\displaystyle
Xから番号nが同じ入力を取り出した行列をx_n \\
Xから次元Dが同じ入力を取り出した行列をx_D \\
とします。この二つは少し紛らわしいことがあるかもしれません。
}

{\displaystyle
また、x_Dの行列 \\
x = \begin{pmatrix}
x_0 \\ x_1 \\ … \\ x_{D-1}
\end{pmatrix} \\
とします。
}

そうすると
{\displaystyle
y(x) = w^Tx
}
と表されるので

{\displaystyle
\ J = \frac{1}{N} \sum_{n=0}^{N-1}  (w^Tx_n-t_n)^2 \
}

よって
{\displaystyle
\frac{\partial J}{\partial w_i} = \frac{2}{N} \sum_{n=0}^{N-1}  (w^Tx_n-t_n)x_{n,i} \
}

Jが最小となるwでは傾きが0なので 0 <= i <= D-1 で
{\displaystyle
\frac{\partial J}{\partial w_i} = 0 \
}
だから0 <= i <= D-1 で
{\displaystyle
\frac{2}{N} \sum_{n=0}^{N-1}  (w^Tx_n-t_n)x_{n,i} = 0  \
}
{\displaystyle
 \sum_{n=0}^{N-1}  (w^Tx_n-t_n)x_{n,i} = 0  \
}

つまり
{\displaystyle
 \sum_{n=0}^{N-1}  (w^Tx_n-t_n) \begin{bmatrix} x_{n,0} , x_{n,1} , … , x_{n,D-1} \end{bmatrix} = \begin{bmatrix} 0 , 0 , … , 0 \end{bmatrix} \
}
{\displaystyle
 \sum_{n=0}^{N-1}  (w^Tx_n-t_n)x^{T}_{n}= \begin{bmatrix} 0 , 0 , … , 0 \end{bmatrix} \
}
{\displaystyle
 w^T  \sum_{n=0}^{N-1} x_n x^{T}_{n} - \sum_{n=0}^{N-1} t_nx^{T}_{n} = \begin{bmatrix} 0 , 0 , … , 0 \end{bmatrix} 
}

ここで
{\displaystyle
 \sum_{n=0}^{N-1} x_n x^{T}_{n} = X^TX
}
{\displaystyle
\sum_{n=0}^{N-1} t_nx^{T}_{n} = t^TX
}
より
{\displaystyle
w^TX^TX - t^TX =  \begin{bmatrix} 0 , 0 , … , 0 \end{bmatrix} \
}
{\displaystyle
w(X^TX) - tX^T =  \begin{bmatrix} 0 , 0 , … , 0 \end{bmatrix}^T \
}
{\displaystyle
w = (X^TX)^{-1}X^Tt\
}

これで入力がD次元のとき
Jが最小になるwがもとまりました。

しかしこれは
{\displaystyle
y(x) = w_0x_0 + w_1x_1 + … + w_{D-1}x_{D-1} 
}
の場合の話でしたよね。
元の
{\displaystyle
y(x) = w_0x_0 + w_1x_1 + … + w_{D-1}x_{D-1} + w_D 
}
の時はどうするかというと
D+1次元目のxとして、常に1をとる入力x_Dを追加して
{\displaystyle
y(x) = w_0x_0 + w_1x_1 + … + w_{D-1}x_{D-1} + x_Dw_D 
}
としてから
{\displaystyle
w = (X^TX)^{-1}X^Tt\
}
にあてはめればOKです。
なんか強引ですが確かに実質
{\displaystyle
y(x) = w_0x_0 + w_1x_1 + … + w_{D-1}x_{D-1} + w_D 
}
と同じになりますね。

せっかくなので、前回解析解を求めた一次元の場合に
この公式で解を求めてみます。
あと、numpyの処理的な都合でX_tが先に求まったのでそのままにしてます。
行列の知識が抜けてるのでそのまま素直に計算してます。
もしかしたら計算は楽できるのかもしれません。

addD = np.ones(10)
X_t = np.array([X,addD])
X2 = X_t.T
XXt= np.dot(X_t,X2)
iXXt = np.linalg.inv(XXt)
iXXtXt = np.dot(iXXt,X_t) 
w = np.dot(iXXtXt,T)

f:id:sawalemontea:20180316220445p:plain

前回求めた解析解は
w0=0.889,w1=-11.617
だったので、確かに一致していますね
公式はすばらしいです
{\displaystyle
w = (X^TX)^{-1}X^Tt\
}

今回はこれでおしまいです。
sawalemounity.hatenablog.com