Experimental content
Experiment One: coding the gradient descent algorithm with the following example
Experiment Three: coding the gradient descent algorithm with the following example
Experimental results
实验一:
代码实现:
# -*- coding: utf-8 -*-
# @Author : sido
# @Software: PyCharm
'''
f(x) = w^2
the derivative of f(x): f`(x) = 2*w
Initilize w = 1, a = 0.4
'''
import matplotlib.pyplot as plt
import numpy as np
# -------------超参数-----------
k = 4
w = [1]
a = 0.9
# ----------梯度下降,更新w-----------
for i in range(k):
w.append(w[-1] - a * 2 * w[-1])
# -------------绘制图像------------
plt.ion() # 打开交互模式
x = np.linspace(-1, 1, 30)
plt.plot(x, np.square(x))
for i in range(0, len(w)-1):
plt.plot(w[i:i+2], np.square(w[i:i+2]), 'r-o')
print(w[i], '---->', w[i+1])
plt.pause(2)
plt.ioff() # 关闭交互模式
print("绘制图像完成!")
plt.waitforbuttonpress() # 等待键盘输入退出
绘制梯度图像:
学习率 a = 0.9:
学习率 a = 0.1:
实验二:
代码实现:
# -*- coding: utf-8 -*-
# @Author : sido
# @Software: PyCharm
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
'''
f(W) = w1^2 + w2^2
W = (1, 3)
a = 0.1
'''
# --------------------------------------------------超参数---------------------------------------------------------
w = np.array([[1, 3]])
a = 0.1
k = 20
# -------------------------------------------------梯度下降,更新参数-------------------------------------------------
for i in range(k):
w = np.concatenate((w, np.array([[w[-1][0] - a * 2 * w[-1][0], w[-1][1] - a * 2 * w[-1][1]]])), axis=0)
# -------------------------------------------------绘制图像---------------------------------------------------------
w1 = np.linspace(-3, 3, 20)
w2 = np.linspace(-3, 3, 20)
plt.ion()
x, y = np.meshgrid(w1, w2) # 生成网格点坐标矩阵
fig = plt.figure()
ax = plt.gca(projection='3d')
ax.set_zlabel('Z', fontdict={'size': 15, 'color': 'red'})
ax.set_ylabel('Y', fontdict={'size': 15, 'color': 'blue'})
ax.set_xlabel('X', fontdict={'size': 15, 'color': 'green'})
ax.plot_surface(x, y, np.square(x)+np.square(y), alpha = 0.5)
print(w)
for i in range(len(w) - 10):
ax.plot(w[i:i+2, 0], w[i:i+2, 1], [sum(np.square(w[i])), sum(np.square(w[i+1]))], 'r-o')
print('x: ', w[i:i+2, 0], ' ---> y: ', w[i:i+2, 1],' ----> z: ', [sum(np.square(w[i])), sum(np.square(w[i+1]))])
plt.pause(0.5)
plt.ioff()
def press(event): # 监控键盘输入
if event.key == "escape":
plt.close()
fig.canvas.mpl_connect('key_press_event', press)
# plt.waitforbuttonpress() # 只要接受到键盘或者鼠标输入就退出
plt.show()
绘制梯度图像:
学习率 a = 0.9:
学习率 a = 0.1:
Experimental analysis
首先本实验选择的损失函数是凸函数,只有一个最低点。那么影响找到全局最小的损失的因素主要是学习率,训练次数以及参数的初始化。
经过修改学习率,我发现当学习率较大时会导致损失可能变大,当学习率过小时,会导致学习的过程十分缓慢。
训练次数也会影响训练的效果,当训练次数较少时,得不到好的训练效果,当训练次数较大时,训练时间长。
最后就是参数的初始化,初始点没选好,可能会导致初始损失大,需要训练较长的训练时间才能得到较好的效果。
Conclusions
基本实现的实验的要求,实现了梯度下降的同时实现了梯度下降的可视化,对梯度下降有了基本的了解,同时也锻炼个人代码能力。在实现的过程中尽量的让自己使用numpy库以及矩阵运算,遇到了一些在没动手前没遇到过的问题,如矩阵形状误判导致的矩阵运算错误;在第二个实验中也因为对梯度下降的不熟悉,利用计算出的梯度和来更新两个参数,得到的结果也是没有收敛到最低点(其实是不可以将梯度求和,应当分别对两个参数进行更新)
错误:
w
=
n
p
.
c
o
n
c
a
t
e
n
a
t
e
(
(
w
,
n
p
.
a
r
r
a
y
(
[
[
w
[
−
1
]
[
0
]
−
a
∗
2
∗
s
u
m
(
w
[
−
1
]
)
,
w
[
−
1
]
[
1
]
−
a
∗
2
∗
s
u
m
(
w
[
−
1
]
)
]
]
)
)
,
a
x
i
s
=
0
)
w = np.concatenate((w, np.array([[w[-1][0] - a * 2 * sum(w[-1]), w[-1][1] - a * 2 * sum(w[-1])]])), axis=0)
w=np.concatenate((w,np.array([[w[−1][0]−a∗2∗sum(w[−1]),w[−1][1]−a∗2∗sum(w[−1])]])),axis=0)
正确:
w
=
n
p
.
c
o
n
c
a
t
e
n
a
t
e
(
(
w
,
n
p
.
a
r
r
a
y
(
[
[
w
[
−
1
]
[
0
]
−
a
∗
2
∗
w
[
−
1
]
[
0
]
,
w
[
−
1
]
[
1
]
−
a
∗
2
∗
w
[
−
1
]
[
1
]
]
]
)
)
,
a
x
i
s
=
0
)
w = np.concatenate((w, np.array([[w[-1][0] - a * 2 * w[-1][0], w[-1][1] - a * 2 * w[-1][1]]])), axis=0)
w=np.concatenate((w,np.array([[w[−1][0]−a∗2∗w[−1][0],w[−1][1]−a∗2∗w[−1][1]]])),axis=0)
当然实验也有缺陷,可以不用记录训练过程中的所有损失,每次记录两个点,也可以可视化出过程,代码也可以封装起来等