《PyTorch深度学习实践》刘二大人课程4反向传播学习笔记

反向传播

两层的神经网络会有什么问题呢,如下图可以看到,两层的神经网络如果只进行线性操作的话,最后的表达式还是wx+b没有太大的变化,模型的复杂度还是很低
在这里插入图片描述
所以我们可以在每一层网络后边加非线性激活函数提高模型复杂度,这样得到的y就不是简单的线性堆叠了
在这里插入图片描述复合函数链式法则可以从如下图中理解,可以看出层层嵌套,由外到里
在这里插入图片描述
反向传播例子,我们有个映射f=xw,输入x,w的值后,我们先对f关于x和w求偏导数得到他们的值,计算出预测的z值,再通过z值求损失L关于z的偏导数,再反向传播分别和f对x和f对w的偏导相乘即的损失L关于x和w的偏导,即可进行梯度下降
在这里插入图片描述
线性模型的计算图,反向传播是有个计算图的,如下图,依次去求偏导,可以看出只要包含参数w的值都需要求偏导
在这里插入图片描述
作业1:
在这里插入图片描述
作业2:
在这里插入图片描述
pytorch中的tensor张量,张量再pytorch动态图中是一个重要的成分元素,它包含了datagrad两个部分,如下图,data是个张量,grad是导数但是还包含动态图,因此梯度反向传播时要用w.grad.data值来更新梯度
在这里插入图片描述
来实际实操下载pytorch中进行反向传播;
首先定义张量w以及设置其需要反向传播计算梯度,也就是定义它为一个参数
在这里插入图片描述
然后,定义前馈传播和损失函数,这里w是张量,x会自动转化为张量形式,这样就会构建了一个计算图,如下图只要包含参数w的都需要计算梯度,计算图如下:
在这里插入图片描述
然后进行不同epoch的迭代参数更新找损失的最小值,下面用的是随机梯度下降方法,对每个样本进行梯度计算和损失计算不求平均。这里需要注意的是
1.首先梯度要进行反向传播也就是最后一个值,这里是损失函数值进行反向传播,利用.backward()函数即可
2.对于一个参数w来言,他有自己的输入值和梯度值,分别用w.data和w.grad.data来存储,w.grad存储的是计算图,不能用这个来进行梯度更新
3.最后要将每一次反向传播保存的梯度值进行清零,方便下一次运算重新开始不受影响
在这里插入图片描述
在这里插入图片描述

反向传播实践代码:

import torch
x_data = [1.0,2.0,3.0]
y_data = [2.0,4.0,6.0]

#定义张量w
w = torch.tensor([1.0])
#定义张量w需要计算梯度
w.requires_grad = True

def forward(x):
    return x*w

def loss(x,y):
    y_pred = forward(x)
    return (y_pred - y)**2

print('predict before training',4,forward(4).item())   #这里要加item()是因为前向传播出来的是张量,这个就变成标量

for epoch in range(100):
    for x,y in zip(x_data,y_data):
        l = loss(x,y)               #计算损失l,也是张量
        l.backward()                #l进行反向传播
        print('\tgrad:',x,y,w.grad.item())   #注意grad包含计算图要想取梯度值需要用.data或者.item取一下
        w.data = w.data -0.01 * w.grad.data  #w.data也是张量

        w.grad.data.zero_()          #把刚才存储的梯度的值都变为0,方便下一次梯度更新
    print('progress:',epoch,l.item())

print('predict after training',4,forward(4).item())

作业代码:

#作业
import numpy as np
import matplotlib.pyplot as plt
import torch

#先构建数据集
x_data = [0.0,1.0,2.0,3.0]
y_data = [4.0,9.0,18.0,31.0]

#创建空列表来存储损失w1,w2,b的值
w1_list = []
w2_list = []
b_list = []
epoch_list = np.arange(0,2000,1)
loss_list = []
epoch = 1

#定义初始的w1,w2,b的张量值
w1 = torch.tensor([10.0])
w2 = torch.tensor([10.0])
b = torch.tensor([10.0])

#定义其为参数可以进行梯度计算
w1.requires_grad = True
w2.requires_grad = True
b.requires_grad = True

#定义前向传播函数
def forward(x):
    return w1*x**2+w2*x+b

#定义损失计算函数
def loss(y_pred,y):
    return (y_pred-y)**2

#多次迭代前向传播
for epoch in range(500):
    for x,y in zip(x_data,y_data):
        y_pred = forward(x)
        #构建图
        l = loss(y_pred,y)
        #反向传播l
        l.backward()
        #梯度更新
        w1.data = w1.data - 0.01 * w1.grad.data
        w2.data = w2.data - 0.01 * w2.grad.data
        b.data = b.data - 0.01 * b.grad.data

        #加到列表中
        w1_list.append(w1.data.item())
        w2_list.append(w2.data.item())
        b_list.append(b.data.item())
        #epoch_list.append(epoch)
        loss_list.append(l.item())

        print('epoch:\t',epoch,'w1:\t',w1.data.item(),'w2:\t',w2.data.item(),'b:\t',b.data.item(),'loss\t',l.item())

        #梯度清零
        w1.grad.data.zero_()
        w2.grad.data.zero_()
        b.grad.data.zero_()
plt.plot(epoch_list,w1_list,'r',label='w1')
plt.plot(epoch_list,w2_list,'g',label='w2')
plt.plot(epoch_list,b_list,'y',label='b')
plt.xlabel('Epoch')
plt.show()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值