一、过程推导——了解BP原理
![](https://i-blog.csdnimg.cn/blog_migrate/d077e17774260e35af081b5d53b4ee1f.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/c829687a9c6994601d8530b2900c5d8f.png)
二、数值计算
![](https://i-blog.csdnimg.cn/blog_migrate/c99d210f27d2820443b2cc2dd144cc50.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d36e2079a68d0b5aac23f4e1d7de889e.jpeg)
三、代码实现
使用numpy实现
import numpy as np
w1, w2, w3, w4, w5, w6, w7, w8 = 0.2, -0.4, 0.5, 0.6, 0.1, -0.5, -0.3, 0.8
x1, x2 = 0.5, 0.3
y1, y2 = 0.23, -0.07
print("输入值 x0, x1:", x1, x2)
print("输出值 y0, y1:", y1, y2)
def sigmoid(z):
a = 1 / (1 + np.exp(-z))
return a
#前向传播
def forward_propagate(x1, x2, w1, w2, w3, w4, w5, w6, w7, w8):
In_h1 = w1 * x1 + w3 * x2
h1 = sigmoid(In_h1)
In_h2 = w2 * x1 + w4 * x2
h2 = sigmoid(In_h2)
In_o1 = w5 * h1 + w7 * h2
o1 = sigmoid(In_o1)
In_o2 = w6 * h1 + w8 *h2
o2 = sigmoid(In_o2)
print("隐藏层h1=",h1,"h2=",h2)
print("预测值o1=",o1,"o2=",o2)
error = (1 / 2) * (o1 - y1) ** 2 + (1 / 2) * (o2 - y2) ** 2
print("损失函数",error)
return o1, o2, h1, h2
# 反向传播
def back_propagate(o1,o2,h1,h2):
d_w5 = (o1 - y1) * o1 * (1 - o1) * h1
d_w6 = (o2 - y2) * o2 * (1 - o2) * h1
d_w7 = (o1 - y1) * o1 * (1 - o1) * h2
d_w8 = (o2 - y2) * o2 * (1 - o2) * h2
d_w1 = ((o1 - y1) * o1 * (1 - o1) * w5 + (o2 - y2) * o2 * (1 - o2) * w6) * h1 * (1 - h1) * x1
d_w2 = ((o1 - y1) *o1 * (1 - o1) * w7 + (o2 - y2) * o2 * (1 - o2) * w8) * h2 * (1 - h2) * x1
d_w3 = ((o1 - y1) * o1 * (1 - o1) * w5 + (o2 - y2) * o2 * (1 - o2) * w6) * h1 * (1 - h1) * x2
d_w4 = ((o1 - y1) * o1 * (1 - o1) * w7 + (o2 - y2) * o2 * (1 - o2) * w8) * h2 * (1 - h2) * x2
print("w的梯度:d_w1=",d_w1,"d_w2=",d_w2, "d_w3=",d_w3, "d_w4=",d_w4, "d_w5=",d_w5, "d_w6=",d_w6, "d_w7=",d_w7, "d_w8=",d_w8)
return d_w1, d_w2, d_w3, d_w4, d_w5, d_w6, d_w7, d_w8
def update_w(w1, w2, w3, w4, w5, w6, w7, w8):
# 步长
step = 1
w1 = w1 - step * d_w1
w2 = w2 - step * d_w2
w3 = w3 - step * d_w3
w4 = w4 - step * d_w4
w5 = w5 - step * d_w5
w6 = w6 - step * d_w6
w7 = w7 - step * d_w7
w8 = w8 - step * d_w8
return w1, w2, w3, w4, w5, w6, w7, w8
if __name__ == "__main__":
print("权值w1=",w1,"w2=",w2, "w3=",w3, "w4=",w4, "w5=",w5, "w6=",w6, "w7=",w7, "w8=",w8)
for i in range(5):
print("=====第" + str(i+1) + "轮=====")
o1, o2, h1, h2 = forward_propagate(x1, x2, w1, w2, w3, w4, w5, w6, w7, w8)
d_w1, d_w2, d_w3, d_w4, d_w5, d_w6, d_w7, d_w8 = back_propagate(o1, o2, h1, h2)
w1, w2, w3, w4, w5, w6, w7, w8 = update_w(w1, w2, w3, w4, w5, w6, w7, w8)
print("更新后的权值w1=",w1,"w2=",w2, "w3=",w3, "w4=",w4, "w5=",w5, "w6=",w6, "w7=",w7, "w8=",w8)
运行结果:
输入值 x0, x1: 0.5 0.3
输出值 y0, y1: 0.23 -0.07
权值w1= 0.2 w2= -0.4 w3= 0.5 w4= 0.6 w5= 0.1 w6= -0.5 w7= -0.3 w8= 0.8
=====第1轮=====
隐藏层h1= 0.5621765008857981 h2= 0.4950001666600003
预测值o1= 0.47694575860699684 o2= 0.5286964002912302
损失函数 0.2097097937078311
w的梯度:d_w1= -0.00842148046150221 d_w2= 0.012606653078458003 d_w3= -0.005052888276901326 d_w4= 0.007563991847074802 d_w5= 0.03463298928683772 d_w6= 0.08386609953820857 d_w7= 0.030494578556568334 d_w8= 0.07384466121071578
=====第2轮=====
隐藏层h1= 0.5635855084341747 h2= 0.4928573549015371
预测值o1= 0.46852995880225773 o2= 0.507207632428805
损失函数 0.19503259609013654
w的梯度:d_w1= -0.009881677937258563 d_w2= 0.010639538997404809 d_w3= -0.005929006762355137 d_w4= 0.006383723398442885 d_w5= 0.03347487045416149 d_w6= 0.08130956462065898 d_w7= 0.029273882775210872 d_w8= 0.07110547795750169
=====第3轮=====
隐藏层h1= 0.5652375137331292 h2= 0.4910491037080464
预测值o1= 0.46042362622378474 o2= 0.48642319040048887
损失函数 0.18135090716878854
w的梯度:d_w1= -0.011136617562339305 d_w2= 0.008804565414065013 d_w3= -0.006681970537403583 d_w4= 0.005282739248439008 d_w5= 0.03235701948492444 d_w6= 0.07856984139649568 d_w7= 0.028110104214062664 d_w8= 0.06825741260769976
=====第4轮=====
隐藏层h1= 0.5670975811306548 h2= 0.4895528919170278
预测值o1= 0.452605043776973 o2= 0.46642302621027565
损失函数 0.16865133428176904
w的梯度:d_w1= -0.012190984188369213 d_w2= 0.007115066380253227 d_w3= -0.007314590513021527 d_w4= 0.004269039828151936 d_w5= 0.03127612758065861 d_w6= 0.07570808633484445 d_w7= 0.02699944280233093 d_w8= 0.06535579385267748
=====第5轮=====
隐藏层h1= 0.5691315837214361 h2= 0.488343922155006
预测值o1= 0.4450557845148802 o2= 0.4472627559010082
损失函数 0.15690487454780833
w的梯度:d_w1= -0.01305497284092114 d_w2= 0.005577424919062039 d_w3= -0.007832983704552684 d_w4= 0.0033464549514372233 d_w5= 0.030229265485068435 d_w6= 0.07277887882948983 d_w7= 0.025938251351850346 d_w8= 0.062447989453055464
更新后的权值w1= 0.25468573299039043 w2= -0.4447432487892431 w3= 0.5328114397942342 w4= 0.5731540507264541 w5= -0.061970272291650697 w6= -0.8922324707196976 w7= -0.44081625970002314 w8= 0.45898866491834983
Process finished with exit code 0
使用pytorch实现
import torch
x = [0.5, 0.3]
y = [0.23, -0.07]
w = [torch.Tensor([0.2]), torch.Tensor([-0.4]), torch.Tensor([0.5]), torch.Tensor(
[0.6]), torch.Tensor([0.1]), torch.Tensor([-0.5]), torch.Tensor([-0.3]), torch.Tensor([0.8])] # 权重初始值
for i in range(0, 8):
w[i].requires_grad = True
for i in range(0, 8):
print(w[i].data, end=" ")
def forward_propagate(x): # 计算图
In_h1 = w[0] * x[0] + w[2] * x[1]
h1 = torch.sigmoid(In_h1)
In_h2 = w[1] * x[0] + w[3] * x[1]
h2 = torch.sigmoid(In_h2)
In_o1 = w[4] * h1 + w[6] * h2
o1 = torch.sigmoid(In_o1)
In_o2 = w[5] * h1 + w[7] * h2
o2 = torch.sigmoid(In_o2)
print("正向计算,隐藏层h1 ,h2:", end="")
print(h1.data, h2.data)
print("正向计算,预测值o1 ,o2:", end="")
print(o1.data, o2.data)
return o1, o2
def error(x, y): # 损失函数
y_pre = forward_propagate(x) # 前向传播
error = (1 / 2) * (y_pre[0] - y[0]) ** 2 + (1 / 2) * (y_pre[1] - y[1]) ** 2 # 考虑 : t.nn.MSELoss()
print("损失函数:", error.item())
return error
if __name__ == "__main__":
for k in range(5):
print("\n=====第" + str(k+1) + "轮=====")
l = error(x, y) # 前向传播,求 Loss,构建计算图
l.backward() # 反向传播,求出计算图中所有梯度存入w中. 自动求梯度,不需要人工编程实现。
print("w的梯度: \n", end=" ")
for i in range(0, 8):
print(round(w[i].grad.item(), 2), end=" ") # 查看梯度
step = 1 # 步长
for i in range(0, 8):
w[i].data = w[i].data - step * w[i].grad.data # 更新权值
w[i].grad.data.zero_() # 注意:将w中所有梯度清零
print("\n更新后的权值w:")
for i in range(0, 8):
print(w[i].data, end=" ")
运行结果:
=====第1轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5622]) tensor([0.4950])
正向计算,预测值o1 ,o2:tensor([0.4769]) tensor([0.5287])
损失函数: 0.2097097933292389
w的梯度:
-0.01 0.01 -0.01 0.01 0.03 0.08 0.03 0.07
更新后的权值w:
tensor([0.2084]) tensor([-0.4126]) tensor([0.5051]) tensor([0.5924]) tensor([0.0654]) tensor([-0.5839]) tensor([-0.3305]) tensor([0.7262])
=====第2轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5636]) tensor([0.4929])
正向计算,预测值o1 ,o2:tensor([0.4685]) tensor([0.5072])
损失函数: 0.19503259658813477
w的梯度:
-0.01 0.01 -0.01 0.01 0.03 0.08 0.03 0.07
更新后的权值w:
tensor([0.2183]) tensor([-0.4232]) tensor([0.5110]) tensor([0.5861]) tensor([0.0319]) tensor([-0.6652]) tensor([-0.3598]) tensor([0.6550])
=====第3轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5652]) tensor([0.4910])
正向计算,预测值o1 ,o2:tensor([0.4604]) tensor([0.4864])
损失函数: 0.1813509315252304
w的梯度:
-0.01 0.01 -0.01 0.01 0.03 0.08 0.03 0.07
更新后的权值w:
tensor([0.2294]) tensor([-0.4321]) tensor([0.5177]) tensor([0.5808]) tensor([-0.0005]) tensor([-0.7437]) tensor([-0.3879]) tensor([0.5868])
=====第4轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5671]) tensor([0.4896])
正向计算,预测值o1 ,o2:tensor([0.4526]) tensor([0.4664])
损失函数: 0.16865134239196777
w的梯度:
-0.01 0.01 -0.01 0.0 0.03 0.08 0.03 0.07
更新后的权值w:
tensor([0.2416]) tensor([-0.4392]) tensor([0.5250]) tensor([0.5765]) tensor([-0.0317]) tensor([-0.8195]) tensor([-0.4149]) tensor([0.5214])
=====第5轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5691]) tensor([0.4883])
正向计算,预测值o1 ,o2:tensor([0.4451]) tensor([0.4473])
损失函数: 0.15690487623214722
w的梯度:
-0.01 0.01 -0.01 0.0 0.03 0.07 0.03 0.06
更新后的权值w:
tensor([0.2547]) tensor([-0.4447]) tensor([0.5328]) tensor([0.5732]) tensor([-0.0620]) tensor([-0.8922]) tensor([-0.4408]) tensor([0.4590])
Process finished with exit code 0
四、问题
1.对比【numpy】和【pytorch】程序,总结并陈述。
【numpy】需要的函数,反向传播都要自己手写定义,相对来说代码繁琐。【torch】可以调用backward()直接得到与函数相关的参数的梯度,进而进行梯度下降计算,不仅代码写的简单,也保证了正确性。通过结果对比发现,两种结果基本相同。
2.激活函数Sigmoid用PyTorch自带函数torch.sigmoid(),观察、总结并陈述。
Sigmoid函数:
torch.sigmoid()
函数将输入的张量(tensor)映射到值域范围为 (0,1) 的区间上。
有观察得,使用Sigmoid函数和使用Pytorch自带函数torch.sigmoid()没较为明显的差距。
3.激活函数Sigmoid改变为Relu,观察、总结并陈述。
Relu函数:
def forward_propagate(x): # 计算图
In_h1 = w[0] * x[0] + w[2] * x[1]
h1 = torch.relu(In_h1)
In_h2 = w[1] * x[0] + w[3] * x[1]
h2 = torch.relu(In_h2)
In_o1 = w[4] * h1 + w[6] * h2
o1 = torch.relu(In_o1)
In_o2 = w[5] * h1 + w[7] * h2
o2 = torch.relu(In_o2)
print("正向计算,隐藏层h1 ,h2:", end="")
print(h1.data, h2.data)
print("正向计算,预测值o1 ,o2:", end="")
print(o1.data, o2.data)
return o1, o2
运行结果:
=====第1轮=====
正向计算,隐藏层h1 ,h2:tensor([0.2500]) tensor([0.])
正向计算,预测值o1 ,o2:tensor([0.0250]) tensor([0.])
损失函数: 0.023462500423192978
w的梯度:
-0.01 0.0 -0.01 0.0 -0.05 0.0 -0.0 0.0
更新后的权值w:
tensor([0.2103]) tensor([-0.4000]) tensor([0.5062]) tensor([0.6000]) tensor([0.1513]) tensor([-0.5000]) tensor([-0.3000]) tensor([0.8000])
=====第2轮=====
正向计算,隐藏层h1 ,h2:tensor([0.2570]) tensor([0.])
正向计算,预测值o1 ,o2:tensor([0.0389]) tensor([0.])
损失函数: 0.020715968683362007
w的梯度:
-0.01 0.0 -0.01 0.0 -0.05 0.0 0.0 0.0
更新后的权值w:
tensor([0.2247]) tensor([-0.4000]) tensor([0.5148]) tensor([0.6000]) tensor([0.2004]) tensor([-0.5000]) tensor([-0.3000]) tensor([0.8000])
=====第3轮=====
正向计算,隐藏层h1 ,h2:tensor([0.2668]) tensor([0.])
正向计算,预测值o1 ,o2:tensor([0.0535]) tensor([0.])
损失函数: 0.01803365722298622
w的梯度:
-0.02 0.0 -0.01 0.0 -0.05 0.0 0.0 0.0
更新后的权值w:
tensor([0.2424]) tensor([-0.4000]) tensor([0.5254]) tensor([0.6000]) tensor([0.2475]) tensor([-0.5000]) tensor([-0.3000]) tensor([0.8000])
=====第4轮=====
正向计算,隐藏层h1 ,h2:tensor([0.2788]) tensor([0.])
正向计算,预测值o1 ,o2:tensor([0.0690]) tensor([0.])
损失函数: 0.015410471707582474
w的梯度:
-0.02 0.0 -0.01 0.0 -0.04 0.0 0.0 0.0
更新后的权值w:
tensor([0.2623]) tensor([-0.4000]) tensor([0.5374]) tensor([0.6000]) tensor([0.2924]) tensor([-0.5000]) tensor([-0.3000]) tensor([0.8000])
=====第5轮=====
正向计算,隐藏层h1 ,h2:tensor([0.2924]) tensor([0.])
正向计算,预测值o1 ,o2:tensor([0.0855]) tensor([0.])
损失函数: 0.012893404811620712
w的梯度:
-0.02 0.0 -0.01 0.0 -0.04 0.0 0.0 0.0
更新后的权值w:
tensor([0.2834]) tensor([-0.4000]) tensor([0.5501]) tensor([0.6000]) tensor([0.3346]) tensor([-0.5000]) tensor([-0.3000]) tensor([0.8000])
Process finished with exit code 0
对比可得,Relu激活函数收敛速度要优于使用sigmoid激活函数
ReLU的一个主要缺点是它可能会导致所谓的"dead ReLU"问题。如果网络的某部分的所有激活值都为0(可能由于随机初始化或者其他因素),那么在这一部分就不会有梯度,这可能导致这一部分的权重无法更新。
4.损失函数MSE用PyTorch自带函数t.nn.MSELoss()替代,观察、总结并陈述。
def error(x1, x2, y1, y2): # 损失函数
y1_pred, y2_pred = forward_propagate(x1, x2, w) # 前向传播
# loss = (1 / 2) * (y1_pred - y1) ** 2 + (1 / 2) * (y2_pred - y2) ** 2 # 考虑 : t.nn.MSELoss()
loss_func = torch.nn.MSELoss() # 创建损失函数
y_pred = torch.cat((y1_pred, y2_pred), dim=0) # 将y1_pred, y2_pred合并成一个向量
y = torch.cat((y1, y2), dim=0) # 将y1, y2合并成一个向量
error= loss_func(y_pred, y) # 计算损失
print("损失函数:", error.item())
return error
对比可得,结果基本相同。
5.损失函数MSE改变为交叉嫡,观察、总结并陈述。
def error(x1, x2, y1, y2): # 损失函数
y1_pred, y2_pred = forward_propagate(x1, x2,w)
loss_func = torch.nn.CrossEntropyLoss() # 创建交叉熵损失函数
y_pred = torch.stack([y1_pred, y2_pred], dim=1)
y = torch.stack([y1, y2], dim=1)
error = loss_func(y_pred, y) # 计算
print("损失函数(交叉熵损失):", error.item())
return error
运行结果:
=====第1轮=====
隐藏层h1= tensor([0.5622], grad_fn=<MulBackward0>) h2= tensor([0.4950], grad_fn=<MulBackward0>)
预测值o1= tensor([0.4769], grad_fn=<MulBackward0>) o2= tensor([0.5287], grad_fn=<MulBackward0>)
损失函数(交叉熵损失): 0.11871970444917679
w的梯度:
-0.0 更新后的权值w 0 : tensor([0.2000])
0.01 更新后的权值w 1 : tensor([-0.4000])
-0.0 更新后的权值w 2 : tensor([0.5000])
0.0 更新后的权值w 3 : tensor([0.6000])
-0.02 更新后的权值w 4 : tensor([0.1000])
0.02 更新后的权值w 5 : tensor([-0.5000])
-0.02 更新后的权值w 6 : tensor([-0.3000])
0.02 更新后的权值w 7 : tensor([0.8000])
=====第2轮=====
隐藏层h1= tensor([0.5622], grad_fn=<MulBackward0>) h2= tensor([0.4950], grad_fn=<MulBackward0>)
预测值o1= tensor([0.4769], grad_fn=<MulBackward0>) o2= tensor([0.5287], grad_fn=<MulBackward0>)
损失函数(交叉熵损失): 0.11871970444917679
w的梯度:
-0.0 更新后的权值w 0 : tensor([0.2000])
0.01 更新后的权值w 1 : tensor([-0.4000])
-0.0 更新后的权值w 2 : tensor([0.5000])
0.0 更新后的权值w 3 : tensor([0.6000])
-0.02 更新后的权值w 4 : tensor([0.1000])
0.02 更新后的权值w 5 : tensor([-0.5000])
-0.02 更新后的权值w 6 : tensor([-0.3000])
0.02 更新后的权值w 7 : tensor([0.8000])
=====第3轮=====
隐藏层h1= tensor([0.5622], grad_fn=<MulBackward0>) h2= tensor([0.4950], grad_fn=<MulBackward0>)
预测值o1= tensor([0.4769], grad_fn=<MulBackward0>) o2= tensor([0.5287], grad_fn=<MulBackward0>)
损失函数(交叉熵损失): 0.11871970444917679
w的梯度:
-0.0 更新后的权值w 0 : tensor([0.2000])
0.01 更新后的权值w 1 : tensor([-0.4000])
-0.0 更新后的权值w 2 : tensor([0.5000])
0.0 更新后的权值w 3 : tensor([0.6000])
-0.02 更新后的权值w 4 : tensor([0.1000])
0.02 更新后的权值w 5 : tensor([-0.5000])
-0.02 更新后的权值w 6 : tensor([-0.3000])
0.02 更新后的权值w 7 : tensor([0.8000])
=====第4轮=====
隐藏层h1= tensor([0.5622], grad_fn=<MulBackward0>) h2= tensor([0.4950], grad_fn=<MulBackward0>)
预测值o1= tensor([0.4769], grad_fn=<MulBackward0>) o2= tensor([0.5287], grad_fn=<MulBackward0>)
损失函数(交叉熵损失): 0.11871970444917679
w的梯度:
-0.0 更新后的权值w 0 : tensor([0.2000])
0.01 更新后的权值w 1 : tensor([-0.4000])
-0.0 更新后的权值w 2 : tensor([0.5000])
0.0 更新后的权值w 3 : tensor([0.6000])
-0.02 更新后的权值w 4 : tensor([0.1000])
0.02 更新后的权值w 5 : tensor([-0.5000])
-0.02 更新后的权值w 6 : tensor([-0.3000])
0.02 更新后的权值w 7 : tensor([0.8000])
=====第5轮=====
隐藏层h1= tensor([0.5622], grad_fn=<MulBackward0>) h2= tensor([0.4950], grad_fn=<MulBackward0>)
预测值o1= tensor([0.4769], grad_fn=<MulBackward0>) o2= tensor([0.5287], grad_fn=<MulBackward0>)
损失函数(交叉熵损失): 0.11871970444917679
w的梯度:
-0.0 更新后的权值w 0 : tensor([0.2000])
0.01 更新后的权值w 1 : tensor([-0.4000])
-0.0 更新后的权值w 2 : tensor([0.5000])
0.0 更新后的权值w 3 : tensor([0.6000])
-0.02 更新后的权值w 4 : tensor([0.1000])
0.02 更新后的权值w 5 : tensor([-0.5000])
-0.02 更新后的权值w 6 : tensor([-0.3000])
0.02 更新后的权值w 7 : tensor([0.8000])
Process finished with exit code 0
有结果可得,改为交叉熵后,结果出现了更多的负值。
6.改变步长,训练次数,观察、总结并陈述。
运行结果:
步长=1,训练次数=5
=====第5轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5691]) tensor([0.4883])
正向计算,预测值o1 ,o2:tensor([0.4451]) tensor([0.4473])
损失函数: 0.15690487623214722
w的梯度:
-0.01 0.01 -0.01 0.0 0.03 0.07 0.03 0.06
更新后的权值w:
tensor([0.2547]) tensor([-0.4447]) tensor([0.5328]) tensor([0.5732]) tensor([-0.0620]) tensor([-0.8922]) tensor([-0.4408]) tensor([0.4590])
步长=1,训练次数=50
=====第50轮=====
正向计算,隐藏层h1 ,h2:tensor([0.6517]) tensor([0.5092])
正向计算,预测值o1 ,o2:tensor([0.2758]) tensor([0.1304])
损失函数: 0.02112446539103985
w的梯度:
-0.01 -0.0 -0.0 -0.0 0.01 0.01 0.0 0.01
更新后的权值w:
tensor([0.7606]) tensor([-0.3133]) tensor([0.8363]) tensor([0.6520]) tensor([-0.7251]) tensor([-2.3611]) tensor([-0.9798]) tensor([-0.7355])
步长=0.1,训练次数=20
=====第20轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5653]) tensor([0.4915])
正向计算,预测值o1 ,o2:tensor([0.4615]) tensor([0.4891])
损失函数: 0.18305820226669312
w的梯度:
-0.01 0.01 -0.01 0.01 0.03 0.08 0.03 0.07
更新后的权值w:
tensor([0.2195]) tensor([-0.4216]) tensor([0.5117]) tensor([0.5871]) tensor([0.0329]) tensor([-0.6629]) tensor([-0.3587]) tensor([0.6574])
步长=10,训练次数=50
=====第50轮=====
正向计算,隐藏层h1 ,h2:tensor([0.7442]) tensor([0.5580])
正向计算,预测值o1 ,o2:tensor([0.2291]) tensor([0.0185])
损失函数: 0.003917161840945482
w的梯度:
-0.0 -0.0 -0.0 -0.0 -0.0 0.0 -0.0 0.0
更新后的权值w:
tensor([1.4089]) tensor([-0.0244]) tensor([1.2253]) tensor([0.8253]) tensor([-0.8268]) tensor([-3.9060]) tensor([-1.0695]) tensor([-1.9318])
0
步长一定的情况下,随着训练次数从10到50,均方误差下降速度也在逐渐降低,收敛速度也就下降了。
7.权值w1-w8初始值换为随机数,对比"“指定权值"的结果,观察、总结并陈述。
w = [torch.randn(1, 1), torch.randn(1, 1), torch.randn(1, 1), torch.randn(1, 1), torch.randn(1, 1), torch.randn(1, 1), torch.randn(1, 1), torch.randn(1, 1) ]
运行结果:
指定
=====第5轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5691]) tensor([0.4883])
正向计算,预测值o1 ,o2:tensor([0.4451]) tensor([0.4473])
损失函数: 0.15690487623214722
w的梯度:
-0.01 0.01 -0.01 0.0 0.03 0.07 0.03 0.06
更新后的权值w:
tensor([0.2547]) tensor([-0.4447]) tensor([0.5328]) tensor([0.5732]) tensor([-0.0620]) tensor([-0.8922]) tensor([-0.4408]) tensor([0.4590])
随机
=====第5轮=====
正向计算,隐藏层h1 ,h2:tensor([[0.7221]]) tensor([[0.3530]])
正向计算,预测值o1 ,o2:tensor([[0.5512]]) tensor([[0.3206]])
损失函数: 0.12786653637886047
w的梯度:
-0.01 -0.0 -0.0 -0.0 0.06 0.06 0.03 0.03
更新后的权值w:
tensor([[1.2782]]) tensor([[-0.5359]]) tensor([[1.0667]]) tensor([[-1.1233]]) tensor([[0.2030]]) tensor([[-1.0091]]) tensor([[0.0210]]) tensor([[-0.2186]])
权重的初始化不会影响收敛的结果,均方误差的下降速度与指定权值时相比有所降低,收敛速度小于指定权值。
8.权值w1-w8初始值换为0,观察、总结并陈述。
运行结果:
=====第5轮=====
正向计算,隐藏层h1 ,h2:tensor([0.5014]) tensor([0.5014])
正向计算,预测值o1 ,o2:tensor([0.4678]) tensor([0.4325])
损失函数: 0.15450814366340637
w的梯度:
-0.01 -0.01 -0.0 -0.0 0.03 0.06 0.03 0.06
更新后的权值w:
tensor([0.0136]) tensor([0.0136]) tensor([0.0081]) tensor([0.0081]) tensor([-0.1584]) tensor([-0.3328]) tensor([-0.1584]) tensor([-0.3328])
权重初始值只影响收敛速度,并不会影响收敛结果。
9.全面总结反向传播原理和编码实现,认真写心得体会。
通过对反向传播的手动求导,加深了对公式的理解。通过修改代码中激活函数、损失函数、步长、训练次数、权重的值,运行观察了一下对收敛速度、结果的影响。大部分就是影响了一下收敛的速度,但它们的结果都大致相同。反向传播算法的思想和前向传播是一样的,只是一个反向的过程,推导过程中注意链式法则,一层扣一环即可求得结果。