はじめに
前回の続きです。
yaju3d.hatenablog.jp
前回の計算が本当に合っているのか、Pythonを使って実証してみたいと思います。
プログラム
重みの更新
①現在の重みで推測値を求める
import numpy as np
a = np.array([10, 20])
b = np.array([[1,3,5],[3,1,7]])
print(np.dot(a,b))
[ 70, 50, 190]
全体の誤差を求める。
二乗誤差は、mean_squared_error の名前です。
def mean_squared_error(y, t):
return 0.5 * np.sum((y - t)**2)
y = np.array([70, 50, 190])
t = np.array([190, 330, 660])
print(mean_squared_error(y, t))
156850.0
②勾配を計算する
勾配は、gradient の名前です。転置は x.T とTを付けるだけなんですね。
def gradient(y, t, x):
return np.dot((y - t),x.T)
t = np.array([190, 330, 660])
y = np.array([70, 50, 190])
x = np.array([[1,3,5],[3,1,7]])
print(gradient(y, t, x))
[-3310 -3930]
③重みを更新する
②で求めた勾配 を用いて、現在の重み を更新します。学習係数 は 0.02 としています。
def weight(w, lr, gd):
return w - lr * gd
t = np.array([190, 330, 660])
y = np.array([70, 50, 190])
x = np.array([[1,3,5],[3,1,7]])
w = np.array([10, 20])
print(weight(w, 0.02, gradient(y, t, x)))
[ 76.2 98.6]
2回目の①現在の重みで推測値を求める
a = weight(w, 0.02, gradient(y, t, x))
b = np.array([[1,3,5],[3,1,7]])
print(np.dot(a,b))
[ 372. 327.2 1071.2]
全体の誤差を求める。
二乗誤差は、mean_squared_error の名前です。
y = np.dot(a,b)
t = np.array([190, 330, 660])
print(mean_squared_error(y, t))
101108.64
というのを繰り返す。
import numpy as np
def mean_squared_error(y, t):
return 0.5 * np.sum((y - t)**2)
def gradient(y, t, x):
return np.dot((y - t),x.T)
def weight(w, lr, gd):
return w - lr * gd
t = np.array([190, 330, 660])
w = np.array([10, 20])
x = np.array([[1,3,5],[3,1,7]])
y = None
for i in range(100):
if y is not None:
grad = gradient(y, t, x)
w = weight(w, 0.02, grad)
y = np.dot(w, x)
l = mean_squared_error(y, t)
if (i + 1) % 10 == 0:
print("step=%3d, a1=%6.2f, a2=%6.2f, loss=%.2f" % (i + 1, w[0], w[1], l))
print("Estimated: a1=%6.2f, a2=%6.2f" % (w[0], w[1]))
step= 10, a1= 78.84, a2= 48.86, loss=4531.39
step= 20, a1= 89.41, a2= 32.85, loss=564.82
step= 30, a1= 94.92, a2= 27.91, loss=264.21
step= 40, a1= 97.30, a2= 26.05, loss=217.63
step= 50, a1= 98.28, a2= 25.30, loss=209.89
step= 60, a1= 98.68, a2= 25.00, loss=208.59
step= 70, a1= 98.84, a2= 24.88, loss=208.38
step= 80, a1= 98.91, a2= 24.83, loss=208.34
step= 90, a1= 98.94, a2= 24.81, loss=208.33
step=100, a1= 98.95, a2= 24.80, loss=208.33
Estimated: a1= 98.95, a2= 24.80
実行結果
リンゴ 98.95 ≒ 99、ミカン 24.80 ≒ 25 → 99 x 2 + 25 x 4 ≒ 297
以前、TensorFlowで組んだ際の結果とほぼ同じになったのでこれでいいかな。
リンゴ 98.81 ≒ 99、ミカン 24.90 ≒ 25 → 99 x 2 + 25 x 4 ≒ 297
yaju3d.hatenablog.jp
上記サイトでTensorFlowで組んだのに近付けるために、train_x と train_y を縦ベクトル に変更してみました。
import numpy as np
def mean_squared_error(y, t):
return 0.5 * np.sum((y - t)**2)
def gradient(y, t, x):
return np.dot((y.T - t.T), x)
def weight(w, lr, gd):
return w - lr * gd
train_x = np.array([[1., 3.], [3., 1.], [5., 7.]])
train_y = np.array([190, 330, 660]).reshape(3, 1)
y = None
for i in range(100):
if y is not None:
grad = gradient(y, train_y, train_x)
w = weight(w, 0.02, grad).reshape(-1,)
else:
w = np.array([10, 20])
y = np.dot(w, train_x.T)
l = mean_squared_error(y, train_y)
if (i + 1) % 10 == 0:
print("step=%3d, a1=%6.2f, a2=%6.2f, loss=%.2f" % (i + 1, w[0], w[1], l))
print("Estimated: a1=%6.2f, a2=%6.2f" % (w[0], w[1]))