目录
BP学习目标
对权重w进行更新,随机梯度下降采用的是loss对w进行求导求梯度,使得w的更新来减少loss,并尽可能是loss最小。
BP计算图
这个结构就成为神经网络中的一层
完整的两层神经网络如下图。 具体的Matrix multiplication矩阵乘法可以参考 matrix cookbook。
BP的链式法则chain rule
1. 前馈网络形式,先向前计算从输入x和权重w,然后算出loss
2. Local gradient,求f关于x的导数和关于w的导数
3. 再反向将loss关于z的偏导传递
4. 反向传播,使用链式法则来求的loss关于x的偏导和关于w的偏导,从而产生新的输入内容
计算流程:
前向网络传播
反向传播过程
完整的计算图举例:
Tensor 张量,可以是标量,向量,也可以是三维的,还可以是更高阶的数据。
代码剖析:
1. 确定好张量w后,构建计算图、
因为当前张量w是一个数,所以torch.Tensor([1.0]),用中括号括起来的数值填写1.0就可以了。
默认情况下tensor不会保留计算的梯度,所以需要w.requires_grad = True 来计算获得张量的梯度。
2. 因为w是张量需要获取w的梯度,所以x*w计算后也是张量也需要获取x*w的梯度
3. 每调用一次loss函数,构建一次计算图。获得loss
4. 前馈过程,计算loss
5. 反馈过程,计算张量的梯度,在反向传播的过程中计算所有张量需要的梯度
6. 利用梯度来更新权重,因为梯度也是tensor,而进行tensor的计算需要构建计算图,但是更新权重只是数值的计算也不需要构建计算图,因此需要用tensor的data,即w.data= w.data - 0.01 * w.grad.data.
在更新权重之前可以使用张量直接计算,但是到权重更新时只能使用标量。
7. 将权重里面的梯度数据全部清零。在这里梯度不需要累加,所以需要显式地清零。不然得到的权重的梯度就是累加的结果。
8. 获取损失,继续迭代。l.item()来获取标量的损失,epoch表示迭代第几轮
练习:
练习代码:
import torch
import matplotlib.pyplot as plt
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
# create the data
x_data = [1.0, 2.0, 3.0]
y_data = [4.0, 9.0, 16.0]
# create the Tensor for grad
w1 = torch.Tensor([1.0]) # 初始权值
w1.requires_grad = True
w2 = torch.Tensor([1.0])
w2.requires_grad = True
b = torch.Tensor([1.0])
b.requires_grad = True
# define the linear model
def forward(x):
return x * x * w1 + x * w2 + b # x^2*w1 + x * w2 also is a Tensor w1=1, w2=2, b=1
def loss(x, y): # 构建计算图
y_pred = forward(x)
return (y_pred - y) ** 2
print("predict (before training)", 4, forward(4).item())
# training
epoch_list = []
loss_list = []
for epoch in range(1000):
for x, y in zip(x_data, y_data):
l = loss(x, y)
l.backward()
print('\t grad:', x, y, w1.grad.item(), w2.grad.item(), b.grad.item())
w1.data = w1.data - 0.01 * w1.grad.data #注意这里的grad是一个tensor,所以要取他的data
w2.data = w2.data - 0.01 * w2.grad.data
b.data = b.data - 0.01 * b.grad.data
w1.grad.data.zero_() #释放之前计算的梯度
w2.grad.data.zero_()
b.grad.data.zero_()
epoch_list.append(epoch)
loss_list.append(l.item())
print("progress:", epoch, l.item())
print("predict (after training)", 4, forward(4).item())
plt.plot(epoch_list, loss_list)
plt.ylabel("loss")
plt.xlabel("epoch")
plt.show()
结果:
#predict (before training) 4 21.0
#训练1000epoch
#predict (after training) 4 25.152122497558594
#训练10000epoch
#predict (after training) 4 25.000938415527344
#在修改训练集的x,y值后,训练结果接近25,
总结:
BP学习过程由信号正向传播和误差反向传播两个阶段构成。其中信号正向传播用于获得在隐含层神经元和输出层神经元的输出信号;误差反向传播用于将网络期望输出与实际输出的误差从输出层反向传播至隐含层在至输入层,并在此过程中更新各个神经元的连接权值。