PyTorch学习-反向传播

backpropagation
反向传播
链式法则,计算梯度(导数)。计算Loss对参数(权重)的偏导,便于利用梯度下降算法,更新权重和偏置的值,使得损失函数的值最小。

PyTorch的Tensor
基本数据类型成员:Tensor,可以是标量,向量,矩阵。
包含两个数据成员:

  • data:权重本身的值
  • grad:损失函数对权重的导数

构建模型就是构建计算图

代码

import numpy as np
import torch
import matplotlib.pyplot as plt

x_data = [1.0, 2.0, 3.0] # 数据集
y_data = [2.0, 4.0, 6.0]

w = torch.Tensor([1.0]) # 选择权重,w 为张量,要用中括号
w.requires_grad = True # 需要计算梯度,默认不计算

def forward(x): # 非常简单的模型
    return x * w  # w是Tensor,x自动转换成Tensor,重载*

def loss(x, y): # 损失函数
    y_pred = forward(x)
    return (y_pred - y) ** 2

epoch_list = []
loss_list = []

print("predict (before training)", 4, forward(4).item())

for epoch in range(100):
    for x, y in zip(x_data, y_data): # 随机梯度下降
        l = loss(x, y) # 构建计算图,直接使用张量
        # 计算梯度,反向传播,将计算结果存到 w 里面,计算图被释放,下次计算创建新的计算图。
        l.backward() 
        print("\t grad: ", x, y, w.grad.item()) # 获得计算的梯度,
        w.data -= 0.01 * w.grad.data # 不要用w.grad进行操作,因为w.grad也是Tensor,使用w.grad会建立一个计算图
        
        w.grad.data.zero_() # w 清零,不清零会出现:dL/dw1+dL/dw2 +...+dL/dwn
    
    epoch_list.append(epoch)
    loss_list.append(l)
    print("progress: ", epoch, l.item())

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

输出:

predict (before training) 4 4.0
grad: 1.0 2.0 -2.0
grad: 2.0 4.0 -7.840000152587891
grad: 3.0 6.0 -16.228801727294922
progress: 0 7.315943717956543
grad: 1.0 2.0 -1.478623867034912
grad: 2.0 4.0 -5.796205520629883
grad: 3.0 6.0 -11.998146057128906
progress: 1 3.9987640380859375
grad: 1.0 2.0 -1.0931644439697266
grad: 2.0 4.0 -4.285204887390137
grad: 3.0 6.0 -8.87037277221679

progress: 97 9.094947017729282e-13
grad: 1.0 2.0 -7.152557373046875e-07
grad: 2.0 4.0 -2.86102294921875e-06
grad: 3.0 6.0 -5.7220458984375e-06
progress: 98 9.094947017729282e-13
grad: 1.0 2.0 -7.152557373046875e-07
grad: 2.0 4.0 -2.86102294921875e-06
grad: 3.0 6.0 -5.7220458984375e-06
progress: 99 9.094947017729282e-13
predict (after training) 4 7.999998569488525

画图:

plt.plot(epoch_list, loss_list)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.show()

图像:
backpic
作业
对于更复杂的模型:二次模型 y ′ = w 1 x 2 + w 2 x + b y'=w_1x^2+w_2x+b y=w1x2+w2x+b,对三个参数进行反向传播,更新权值。
不过最后结果好像有点过拟合。。。
作业代码

import numpy as np
import torch
import matplotlib.pyplot as plt

x_data = [1.0, 2.0, 3.0] # 数据集
y_data = [2.0, 4.0, 6.0]

w1 = torch.Tensor([1.0]) # 选择权重,w 为张量,要用中括号
w2 = torch.Tensor([1.0])
b = torch.Tensor([1.0])
w1.requires_grad = True # 需要计算梯度,默认不计算
w2.requires_grad = True
b.requires_grad = True

def forward(x): # 非常简单的模型
    return w1 * x * x +w2 * x + b   # w是Tensor,x自动转换成Tensor,重载*

def loss(x, y): # 损失函数
    y_pred = forward(x)
    return (y_pred - y) ** 2
   
epoch_list = []
loss_list = []

print("predict (before training)", 4, forward(4).item())

for epoch in range(100):
    for x, y in zip(x_data, y_data): # 随机梯度下降
        l = loss(x, y) # 构建计算图,直接使用张量
        # 计算梯度,反向传播,将计算结果存到 w1,w2,b 里面,计算图被释放,下次计算创建新的计算图。
        l.backward() 
        print("\t grad: ", x, y, w1.grad.item(), w2.grad.item(), b.grad.item()) # 获得计算的梯度,
        w1.data -= 0.01 * w1.grad.data # 不要用w.grad进行操作,因为w.grad也是Tensor,使用w.grad会建立一个计算图
        w2.data -= 0.01 * w2.grad.data
        b.data -= 0.01 * b.grad.data
        
        w1.grad.data.zero_()
        w2.grad.data.zero_() # w 清零,不清零会出现:dL/dw1+dL/dw2 +...+dL/dwn
        b.grad.data.zero_()
        
    epoch_list.append(epoch)
    loss_list.append(l)
    print("progress: ", epoch, l.item())

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

输出结果:

predict (before training) 4 21.0
grad: 1.0 2.0 2.0 2.0 2.0
grad: 2.0 4.0 22.880001068115234 11.440000534057617 5.720000267028809
grad: 3.0 6.0 77.04720306396484 25.682401657104492 8.560800552368164
progress: 0 18.321826934814453
grad: 1.0 2.0 -1.1466078758239746 -1.1466078758239746 -1.1466078758239746
grad: 2.0 4.0 -15.536651611328125 -7.7683258056640625 -3.8841629028320312
grad: 3.0 6.0 -30.432214736938477 -10.144071578979492 -3.381357192993164
progress: 1 2.858394145965576
grad: 1.0 2.0 0.3451242446899414 0.3451242446899414 0.3451242446899414
grad: 2.0 4.0 2.4273414611816406 1.2136707305908203 0.6068353652954102
grad: 3.0 6.0 19.449920654296875 6.483306884765625 2.161102294921875
… …
progress: 97 0.006365625653415918
grad: 1.0 2.0 0.3163886070251465 0.3163886070251465 0.3163886070251465
grad: 2.0 4.0 -1.7319869995117188 -0.8659934997558594 -0.4329967498779297
grad: 3.0 6.0 1.4334239959716797 0.47780799865722656 0.1592693328857422
progress: 98 0.0063416799530386925
grad: 1.0 2.0 0.31661510467529297 0.31661510467529297 0.31661510467529297
grad: 2.0 4.0 -1.7297420501708984 -0.8648710250854492 -0.4324355125427246
grad: 3.0 6.0 1.4307546615600586 0.47691822052001953 0.15897274017333984
progress: 99 0.00631808303296566
predict (after training) 4 8.544172286987305

画图:

plt.plot(epoch_list, loss_list)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.show()

图像:
作业backpr

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值