qiuzitao深度学习之PyTorch实战(三)

史上最简单、实际、通俗易懂的PyTorch实战系列教程!(新手友好、小白请进、建议收藏)

一、Autograd(自动求导/微分)机制

PyTorch框架干的最厉害的一件事就是帮我们把反向传播全部计算好了

我们来看一下这个机制的简单实现过程

先随机生成一个 3*4 的矩阵,后面的参数就是自动求导=True:

x = torch.randn(3,4,requires_grad=True)
x

在这里插入图片描述
再定义一个随机的 3*4 矩阵:

b = torch.randn(3,4,requires_grad=True)

定义一个简单函数让它们相加起来:

t = x + b

再定义 y 是 t 的求和:

y = t.sum()
y

把 y 当成损失函数开始反向传播求导:

y.backward()

看一下 b 的梯度(求导)等于多少:

b.grad

在这里插入图片描述
虽然没有指定t的requires_grad,但是需要用到它,也会默认的。

x.requires_grad, b.requires_grad, t.requires_grad

在这里插入图片描述
接下来举个例子看一下:

在这里插入图片描述
图一:y = w·x ,z = y+b  图二:z对b求偏导,z对y求偏导;y对w求偏导,y对b求偏导;z对x求偏导,z对w求偏导

#计算流程
x = torch.rand(1)
b = torch.rand(1, requires_grad = True)
w = torch.rand(1, requires_grad = True)
y = w * x 
z = y + b 
x.requires_grad, b.requires_grad, w.requires_grad, y.requires_grad#注意y也是需要的

在这里插入图片描述

x.is_leaf, w.is_leaf, b.is_leaf, y.is_leaf, z.is_leaf

在这里插入图片描述

反向传播计算:(如果这里不清零,梯度每次会默认累加,会影响到当前梯度的计算)

z.backward(retain_graph=True)#如果不清空会累加起来
w.grad

在这里插入图片描述

b.grad

在这里插入图片描述

二、举个简单例子,做一个线性回归试试水

一个典型的神经网络的训练过程如下:

  • 定义具有学习参数(或权重)的神经网络
  • 迭代输入数据集
  • 根据神经网络对输入数据集进行运算
  • 计算损失(输出与真实结果的距离,损失越小说明模型越准确)
  • 将梯度反向传播给神经网络的参数
  • 更新网络的权重(或参数)。通常使用一种简单的更新规则:权重 = 权重 - 学习率 * 梯度

构造一组输入数据 x 和其对应的标签 y ,让模型学习拟合出 w 和 b。(我们这里要模拟出的线性回归函数:y = 2x + 1 ,我们 x 给的是从 0 - 10 一共11个数,对应的y就是 1 - 21 也是11个数,也就是11行1列的矩阵)

构造 x:

import numpy as np
x_values = [i for i in range(11)]
x_train = np.array(x_values, dtype=np.float32)
x_train = x_train.reshape(-1, 1)
x_train.shape

在这里插入图片描述
构造 y:

y_values = [2*i + 1 for i in x_values] # y = 2x + 1
y_train = np.array(y_values, dtype=np.float32)
y_train = y_train.reshape(-1, 1) #把数据reshape转成矩阵的格式
y_train.shape

在这里插入图片描述
定义一个线性回归模型:
(其实线性回归就是一个不加激活函数的全连接层)

import torch
import torch.nn as nn

class LinearRegressionModel(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(LinearRegressionModel, self).__init__()
        self.linear = nn.Linear(input_dim, output_dim)  

    def forward(self, x):
        out = self.linear(x)
        return out

torch.nn 只支持对批量数据的处理,不支持单个样本。

input_dim = 1  #输入数据维度 = 1
output_dim = 1 #输出数据维度 = 1

model = LinearRegressionModel(input_dim, output_dim)
model

在这里插入图片描述
指定好参数和损失函数:

epochs = 1000  #训练1000轮
learning_rate = 0.01  #学习率=0.01
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) #用SGD的优化器
criterion = nn.MSELoss()  # 用均方误差(MSE)的损失函数

一个损失函数包括两个输入(预测值和实际值),然后返回这两个值的距离。

在 nn 的 package 里面有不同的损失函数。均方误差(MSE)损失函数,它返回的是均方差,即每一个分量相减的平方累计最后除分量的个数,常被用作线性回归的损失函数。

训练模型:

for epoch in range(epochs):
    epoch += 1
    # 注意转行成tensor
    inputs = torch.from_numpy(x_train)
    labels = torch.from_numpy(y_train)

    # 梯度要清零每一次迭代
    optimizer.zero_grad() 

    # 前向传播
    outputs = model(inputs)

    # 计算损失
    loss = criterion(outputs, labels)

    # 返向传播
    loss.backward()

    # 更新权重参数
    optimizer.step()
    if epoch % 50 == 0:
        print('epoch {}, loss {}'.format(epoch, loss.item()))

在这里插入图片描述
测试模型预测结果:

predicted = model(torch.from_numpy(x_train).requires_grad_()).data.numpy()
predicted

在这里插入图片描述
结果还是很准的,我们预定的是:y = 2x+1,让模型学习模拟 w 和 b 也就是 w = 2,b = 1,现在代入0-10这11个数字去算,和我们上面预测得到的结果基本一样。
 
 
模型的保存与读取
保存:

torch.save(model.state_dict(), 'model.pkl')

读取:

model.load_state_dict(torch.load('model.pkl'))

在这里插入图片描述
使用GPU进行训练
(只需要把数据和模型传入到cuda里面就可以了)

class LinearRegressionModel(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(LinearRegressionModel, self).__init__()
        self.linear = nn.Linear(input_dim, output_dim)  
        
    def forward(self, x):
        out = self.linear(x)
        return out

input_dim = 1
output_dim = 1

model = LinearRegressionModel(input_dim, output_dim)

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)

criterion = nn.MSELoss()

learning_rate = 0.01

optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

epochs = 1000
for epoch in range(epochs):
    epoch += 1
    inputs = torch.from_numpy(x_train).to(device)
    labels = torch.from_numpy(y_train).to(device)

    optimizer.zero_grad() 

    outputs = model(inputs)

    loss = criterion(outputs, labels)

    loss.backward()

    optimizer.step()

    if epoch % 50 == 0:
        print('epoch {}, loss {}'.format(epoch, loss.item()))

在这里插入图片描述

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuzitao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值