勾配降下法
Published:
By nobCategory: Posts
P.102 例題 関数 \(z=x^2+y^2\) について、その最小値を与える \(x, y\) の値を勾配降下法で求めましょう。
$$
勾配 \left(\frac{\partial z}{\partial x}, \frac{\partial z}{\partial y}\right) = (2x, 2y)
$$
初期位置: \((x, y) = (2, 4)\)
学習係数: \(\eta = 0.1\)
\(i = 0 ... 29\)
def gradient(x, y):
return 2 * x, 2 * y
learning_rate = 0.1
epochs = 30
x, y = 2, 4
learning_history = []
for i in range(epochs):
learning_history.append((x, y))
gx, gy = gradient(x, y)
dx, dy = -1 * learning_rate * gx, -1 * learning_rate * gy
x, y = x + dx, y + dy
z = x**2 + y**2
print("{} {} {} {} {}".format(i, (x, y), (gx, gy), (dx, dy), z))
if z < 0.001:
break
0 (1.6, 3.2) (4, 8) (-0.4, -0.8) 12.800000000000002
1 (1.28, 2.56) (3.2, 6.4) (-0.32000000000000006, -0.6400000000000001) 8.192
2 (1.024, 2.048) (2.56, 5.12) (-0.256, -0.512) 5.2428799999999995
3 (0.8192, 1.6384) (2.048, 4.096) (-0.2048, -0.4096) 3.3554432
4 (0.65536, 1.31072) (1.6384, 3.2768) (-0.16384, -0.32768) 2.1474836480000006
5 (0.5242880000000001, 1.0485760000000002) (1.31072, 2.62144) (-0.13107200000000002, -0.26214400000000004) 1.3743895347200006
6 (0.4194304000000001, 0.8388608000000002) (1.0485760000000002, 2.0971520000000003) (-0.10485760000000002, -0.20971520000000005) 0.8796093022208005
7 (0.33554432000000006, 0.6710886400000001) (0.8388608000000002, 1.6777216000000004) (-0.08388608000000003, -0.16777216000000006) 0.5629499534213122
8 (0.26843545600000007, 0.5368709120000001) (0.6710886400000001, 1.3421772800000003) (-0.06710886400000002, -0.13421772800000004) 0.3602879701896399
9 (0.21474836480000006, 0.4294967296000001) (0.5368709120000001, 1.0737418240000003) (-0.053687091200000016, -0.10737418240000003) 0.23058430092136953
10 (0.17179869184000005, 0.3435973836800001) (0.4294967296000001, 0.8589934592000003) (-0.04294967296000002, -0.08589934592000004) 0.14757395258967648
11 (0.13743895347200002, 0.27487790694400005) (0.3435973836800001, 0.6871947673600002) (-0.03435973836800001, -0.06871947673600003) 0.09444732965739293
12 (0.10995116277760002, 0.21990232555520003) (0.27487790694400005, 0.5497558138880001) (-0.027487790694400008, -0.054975581388800016) 0.06044629098073148
13 (0.08796093022208001, 0.17592186044416003) (0.21990232555520003, 0.43980465111040007) (-0.021990232555520003, -0.04398046511104001) 0.03868562622766815
14 (0.070368744177664, 0.140737488355328) (0.17592186044416003, 0.35184372088832006) (-0.017592186044416005, -0.03518437208883201) 0.024758800785707608
15 (0.056294995342131206, 0.11258999068426241) (0.140737488355328, 0.281474976710656) (-0.014073748835532801, -0.028147497671065603) 0.01584563250285287
16 (0.04503599627370496, 0.09007199254740993) (0.11258999068426241, 0.22517998136852482) (-0.011258999068426243, -0.022517998136852485) 0.010141204801825836
17 (0.03602879701896397, 0.07205759403792794) (0.09007199254740993, 0.18014398509481985) (-0.009007199254740993, -0.018014398509481985) 0.0064903710731685355
18 (0.028823037615171177, 0.057646075230342354) (0.07205759403792794, 0.14411518807585588) (-0.007205759403792794, -0.014411518807585589) 0.004153837486827863
19 (0.02305843009213694, 0.04611686018427388) (0.057646075230342354, 0.11529215046068471) (-0.005764607523034235, -0.01152921504606847) 0.002658455991569832
20 (0.018446744073709553, 0.03689348814741911) (0.04611686018427388, 0.09223372036854777) (-0.004611686018427388, -0.009223372036854777) 0.0017014118346046925
21 (0.014757395258967642, 0.029514790517935284) (0.03689348814741911, 0.07378697629483821) (-0.003689348814741911, -0.007378697629483822) 0.0010889035741470032
22 (0.011805916207174114, 0.02361183241434823) (0.029514790517935284, 0.05902958103587057) (-0.0029514790517935286, -0.005902958103587057) 0.0006968982874540821
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
fig.canvas.header_visible = False
ax = fig.add_subplot(projection="3d")
x = np.arange(-5, 5, 0.1)
y = np.arange(-5, 5, 0.1)
x, y = np.meshgrid(x, y)
z = x**2 + y**2
ax.set_title(r"$z = x^2 + y^2$")
ax.plot_surface(x, y, z, alpha=0.2)
history = np.array(learning_history)
_x = history[:, 0]
_y = history[:, 1]
_z = _x**2 + _y**2
ax.plot(_x, _y, _z, marker="o", markersize=4)
ax.set(xlabel="x", ylabel="y", zlabel="z")
plt.show()