此时,损失函数计算公式为:
M
S
E
L
o
s
s
(
w
)
=
∑
i
=
1
n
∣
∣
y
i
−
y
^
i
∣
∣
2
2
n
MSELoss(w)=\frac{\sum_{i=1}^n||y_i-\hat y_i||_2^2}{n}
MSELoss(w)=n∑i=1n∣∣yi−y^i∣∣22
当我们带入全部四条数据进行计算时,损失函数为:
L
o
s
s
4
(
w
)
=
(
2
−
w
)
2
+
(
5
−
3
w
)
2
+
(
4
−
6
w
)
2
+
(
3
−
8
w
)
2
4
=
110
w
2
−
100
w
+
54
4
\begin{aligned} Loss_4(w) &= \frac{(2-w)^2+(5-3w)^2+(4-6w)^2+(3-8w)^2}{4} \\ &=\frac{110w^2-100w+54}{4} \end{aligned}
Loss4(w)=4(2−w)2+(5−3w)2+(4−6w)2+(3−8w)2=4110w2−100w+54
对应的,我们通过求解该损失函数能够得到最优
w
w
w 结果,令损失函数导函数为 0 即可得
w
=
100
220
=
5
11
w=\frac{100}{220}=\frac{5}{11}
w=220100=115,最终解得模型
y
=
5
11
x
y = \frac{5}{11}x
y=115x。
而如果我们带入其中一条数据进行计算,例如带入第一条数据进行计算,则损失函数计算公式为:
L
o
s
s
1
(
w
)
=
(
2
−
w
)
2
=
w
2
−
4
w
+
4
Loss_1(w)=(2-w)^2 = w^2-4w+4
Loss1(w)=(2−w)2=w2−4w+4
此时解出最优参数结果为
w
=
2
w=2
w=2,即训练得出模型为
y
=
2
x
y=2x
y=2x。很明显,带入训练数据不同、损失函数不同、训练所得模型也不同。
从原理上讲,损失函数是指导求解全域最小值的方程,而如果多条(部分)数据规律一致,则构建出来的损失函数也将基本一致,至少是全域最小值点将保持一致,例如下述两条数据规律一致,都满足
y
=
2
x
y=2x
y=2x 这一基本规律
数据集2
Index
x
y
1
1
2
2
2
4
则围绕这两条数据分别构造损失函数,可得出如下结果:
M
S
E
L
o
s
s
(
w
)
1
=
(
2
−
w
)
2
MSELoss(w)_1 = (2-w)^2
MSELoss(w)1=(2−w)2
M
S
E
L
o
s
s
(
w
)
2
=
(
4
−
2
w
)
2
=
4
(
2
−
w
)
2
MSELoss(w)_2 = (4-2w)^2 = 4(2-w)^2
MSELoss(w)2=(4−2w)2=4(2−w)2
而这两个损失函数,尽管看起来系数差距成一定比例,但这种差异其实并不影响实际梯度下降的计算过程.
上述
M
S
E
L
o
s
s
1
MSELoss_1
MSELoss1 和
M
S
E
L
o
s
s
2
MSELoss_2
MSELoss2 的比例差距完全可以通过在迭代过程中设置负比例的学习率来确保最终参数迭代过程完全一致,例如我们可以令初始
w
w
w 取值为 0,则两个损失函数的迭代过程如下:
至此,我们再看上文中的
L
o
s
s
(
w
)
4
Loss(w)_4
Loss(w)4 和
L
o
s
s
(
w
)
1
Loss(w)_1
Loss(w)1,二者之所以会表现出差异,是因为
L
o
s
s
(
w
)
4
Loss(w)_4
Loss(w)4 背后的四条数据所表现出的整体规律和
M
S
E
L
o
s
s
(
w
)
1
MSELoss(w)_1
MSELoss(w)1 后背的一条数据所表现出的规律不一致。
L
o
s
s
4
Loss_4
Loss4 背后的数据集
Index
x
y
1
1
2
2
3
5
3
6
4
4
8
3
L
o
s
s
4
(
w
)
=
110
w
2
−
100
w
+
54
4
Loss_4(w) =\frac{110w^2-100w+54}{4}
Loss4(w)=4110w2−100w+54
L
o
s
s
1
Loss_1
Loss1 背后的数据集
Index
x
y
1
1
2
L
o
s
s
1
(
w
)
=
(
2
−
w
)
2
=
w
2
−
4
w
+
4
Loss_1(w)=(2-w)^2 = w^2-4w+4
Loss1(w)=(2−w)2=w2−4w+4
此时如果我们采用 SGD 进行参数点的更新迭代,则每次提取一条数据构造损失函数然后再进行计算,同样我们构建不带截距项的简单线性回归
y
=
w
x
y=wx
y=wx 进行建模,则第一条数据的损失函数为:
L
o
s
s
1
(
w
)
=
(
2
−
w
)
2
Loss_1(w) = (2-w)^2
Loss1(w)=(2−w)2
第二条数据的损失函数为
L
o
s
s
2
(
w
)
=
(
5
−
3
w
)
2
Loss_2(w)=(5-3w)^2
Loss2(w)=(5−3w)2
w =0
epoch =40
for j inrange(epoch):for i inrange(2):
w = w_cal(x[i], w, y[i], lr_gd, lr =0.02, itera_times =1)
# 最终参数取值
w
#1.6887966746685015
当然,我们也可以将上述过程定义成一个函数:
defsgd_cal(X, w, y, gd_cal, epoch, lr =0.02):"""
随机梯度下降计算函数
:param X: 训练数据特征
:param w: 初始参数取值
:param y: 训练数据标签
:param gd_cal:梯度计算公式
:param epoch: 遍历数据集次数
:param lr: 学习率
:return w:最终参数计算结果
"""
m = X.shape[0]
n = X.shape[1]for j inrange(epoch):for i inrange(m):
w = w_cal(X[i].reshape(1, n), w, y[i].reshape(1,1), gd_cal=gd_cal, lr=lr, itera_times =1)return w
验证函数输出结果。
w =0
sgd_cal(x, w, y, lr_gd, epoch=40, lr=0.02)#array([[1.68879667]])
那么,1.688 是否是全域最小值点呢?此时我们也可以对比梯度下降围绕上述问题计算所得结果:
# 梯度下降计算过程
w =0
w = w_cal(x, w, y, lr_gd, lr =0.02, itera_times =100)
w
#array([[1.7]])
而整体损失函数为
L
o
s
s
(
w
)
=
w
2
−
4
w
+
4
+
9
w
2
−
30
w
+
25
=
10
w
2
−
34
w
+
29
Loss(w)=w^2-4w+4+9w^2-30w+25=10w^2-34w+29
Loss(w)=w2−4w+4+9w2−30w+25=10w2−34w+29
对应梯度计算公式为
∇
w
L
o
s
s
(
w
)
=
20
w
−
34
\nabla _wLoss(w)=20w-34
∇wLoss(w)=20w−34
因此,全域最小值点应为
w
=
34
20
=
1.7
w=\frac{34}{20}=1.7
w=2034=1.7
还是回顾上述例子中参数的迭代过程,在第一轮 epoch 的第一次迭代时,参数点从 0 出发,实际上是根据第一条数据的损失函数最小值点前进的。第一条数据的损失函数及图像如下:
L
o
s
s
1
(
w
)
=
(
2
−
w
)
2
Loss_1(w) = (2-w)^2
Loss1(w)=(2−w)2
假设现在全部训练数据的损失函数为
y
=
x
⋅
c
o
s
(
π
x
)
y=x\cdot cos(\pi x)
y=x⋅cos(πx),而某条数据的损失函数为
y
=
(
x
−
0.7
)
2
y=(x-0.7)^2
y=(x−0.7)2,则当参数在 0.35 附近时,带入该条数据进行梯度下降时就能顺利跨过 0.35 局部最小值点。
# 初始参数为0,两条数据为1批,迭代1轮epoch
w =0
sgd_cal(x, w, y, lr_gd, epoch=1, batch_size=2, lr=0.02, shuffle=False)#array([[0.62]])# 初始参数为0,两条数据为1批,迭代10轮epoch
w =0
sgd_cal(x, w, y, lr_gd, epoch=10, batch_size=2, lr=0.02)#array([[0.67407761]])# 初始参数为0,两条数据为1批,迭代10轮epoch
w =0
sgd_cal(x, w, y, lr_gd, epoch=10, batch_size=2, lr=0.02)#array([[0.52203531]])# 对比梯度下降计算过程
w =0
w_cal(x, w, y, lr_gd, lr =0.02, itera_times =10)#array([[0.56363636]])
并且,如果将每一批数据的数据量设置为样本总数时,计算过程就相当于梯度下降。
w =0
sgd_cal(x, w, y, lr_gd, epoch=10, batch_size=4, lr=0.02)#array([[0.56363636]])
当然,如果将每一批数据的数据量设置为 1,其计算过程就相当于随机梯度下降。
w =0for j inrange(10):for i inrange(4):
w = w_cal(x[i], w, y[i], lr_gd, lr =0.002, itera_times =1)
w
#0.5347526106195503
w =0
w = sgd_cal(x, w, y, lr_gd, epoch=10, batch_size=1, lr=0.002, shuffle=False)
w
#array([[0.53475261]])
前言 各位读者,新年快乐,现在是2023年了,新的一年,我们的开发也会焕然一新,Android开发的工具Android Studio,也能更新到Android Studio Electric Eel | 2022.1.1 版本了,短期内我将使用此版本学…