数学とPythonのメモ帳

僕のメモ帳です。同じ疑問を感じた方の参考になれば良いです。

最小二乗法をPythonで実装

最小二乗法では、重みはこうなります。

\begin{align}
w\bf = (X^TX)^{-1}X^Ty\bf
\end{align}

#適当な6点のx,y座標
px = np.array([0,1,2,3,4,5])
py = np.array([1,5,6,8,9,9])

e = np.array([1,1,1,1,1,1]) #成分が全て1のベクトル
X = np.array([px, e]).T #6点のx成分と1を縦に並べた行列(最小二乗法に必要)

#最小二乗法による重みの解
w = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(py)

#点を全てプロット
plt.scatter(px, py)

#-3から7まで0.1刻みでnumpy配列で用意
x = np.arange(-3, 7, 0.1)

#得られた重みを用いて、直線の式を作る
y = w[0]*x + w[1]

#得られた直線を引く
plt.plot(x, y)
plt.show()

f:id:keitainoue157:20181214002132p:plain

ちなみに、Windrow-Hoffアルゴリズムという最小二乗法を解く手法も紹介する

#適当な6点のx,y座標
px = np.array([0,1,2,3,4,5])
py = np.array([1,5,6,8,9,9])

#重みは0で初期化
w = np.array([0, 0])

#学習率 適当に小さく
eta = 0.001

#Widrow-Hoffアルゴリズムで最小二乗法を解く
for _ in range(1000):
    for i in range(6):
        w = w - eta*(w[0]*px[i] + w[1] - py[i])*np.array([px[i], 1])

#点を全てプロット
plt.scatter(px, py)

#-3から7まで0.1刻みでnumpy配列で用意
x = np.arange(-3, 7, 0.1)

#得られた重みを用いて、直線の式を作る
y = w[0]*x + w[1]

#得られた直線を引く
plt.plot(x, y)
plt.show()

f:id:keitainoue157:20181214003948p:plain

点に沿ったいい感じの直線が引けてて気持ちいいね!