四、反向传播 back propagation
一、原理
1.1 计算图
在简单的线性模型中,我们可以通过数学推导求出梯度公式。
在复杂网络中,因为太复杂,无法直接数学计算梯度公式。
考虑将这样的复杂网络看成是图,我们在图上传播梯度,最后根据链式求导求出梯度(反向传播)。
计算图(一个简单的二层神经网络)
由于可以线性展开,这样就等于一个网络,中间计算的权重就没有意义。所以我们要加上一个非线性的东西,增加模型的复杂度。
1.2 反向传播
反向传播的过程:(先是蓝色箭头,然后红色)
Example:y = w * x
二、PyTorch实现
PyTorch :
Tenso(张量):PyTorch中存储数据的基本元素。
Tensor两个重要的成员,data和grad。(grad也是个张量)
#pytorch,线性模型
import torch
#数据样本x,y
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
#设置权重w 初值1.0 ,注意中括号[]
w = torch.Tensor([1.0])
w.requires_grad = True #w需要计算梯度
# y = x * w
def forward(x):
return x * w #由于w是Tensor类型,这里x会自动类型转换为Tensor
#损失函数
def loss(x, y):
y_pred = forward(x)
return (y_pred - y) ** 2
print("predict (before training) x={x},y={y}".format(x=4,y=forward(4).item()))
for epoch in range(100):
for x, y in zip(x_data, y_data):
l = loss(x, y) #Forward, compute loss。
l.backward() #Backward, 反向传播后就得到梯度
print('\tgrad:',x, y, w.grad.item())
w.data = w.data - 0.01 * w.grad.data #更新w
w.grad.data.zero_()#默认w的梯度累加,但这里需要清零。所以要显式清零。
print("progress: epoch={epoch}, loss = {l}".format(epoch=epoch, l =l.item()))
print("predict (after training) x={x},y={y}".format(x=4,y=forward(4).item()))