1.向前计算

对于pytorch中的一个tensor,如果设置它的属性.requires_gradTrue,那么它将会追踪对于该张量的所有操作,或者可以理解为,这个tensor是一个参数,后续会被计算梯度,更新该参数。

1.1计算过程

假设有一下条件(1/4表示平均值,Xi中有4个数),使用torch完成其向前计算的过程

如果x为参数,需要对其进行梯度的计算和更新。那么,在最开始随机设置x的值的过程中,需要设置它的requires_grad属性值为True,其默认值为False

从上述代码可以看出:

  1. x的requires_grad属性为True
  2. 之后的每次计算都会修改其grad_fn属性,用来记录做过的操作
    1. 通过这个函数和grad_fn能够组合才能一个和前一小节类似的计算图

1.2requires_grad和grad_fn


注意:
为了防止跟踪历史记录(和使用内存),可以将代码块包装在with torch.no_grad():中(其中的操作不会被追踪,看上图,并且其requires_grad也会被修改)。在评估模型时特别有用,因为模型可能具有requires_grad = True的可训练参数,但是我们不需要在此过程中对他们进行梯度计算。

1.3梯度计算

反向传播:output.backward()
获取梯度:x.gard
对于1.1中的out而言,我们可以使用backward方法来进行反向传播,计算梯度out.backward()out.backward()out.backward(),此时便能够求出倒数dout/dxdout/dxdout/dx,调用x.gradx.gradx.grad能够获取导数值。

注意:在输出是一个标量的情况下,我们可以调用输出tensortensortensor的backward()backward()backward()方法,但是在数据是一个向量的时候,调用backward()backward()backward()的时候还需要传入其他参数。
loss.backward()就是根据损失函数,对参数requires_grad=True去计算它的梯度,并且把它累加保存到x.gard此时还并未更新其梯度。所以,每次反向传播之前需要先把梯度置为0之后再计算。

2.线性回归实现

下面会用torch实现一个简单的线性回归
假设基础模型是y=wx+by=wx+by=wx+b,其中w和b均为参数,我们使用y=3x+0.8y=3x+0.8y=3x+0.8来构造数据x和y。主要步骤如下:

  1. 准备数据
  2. 计算预测值
  3. 计算损失,把参数的梯度置为0,进行反向传播
  4. 更新参数
import torch
import matplotlib.pyplot as pltlearning_rate = 0.01
# 1. 准备数据
# y = 3x+0.8
x = torch.rand([500,1])
y_true = 3*x + 0.8# 2. 通过模型计算y_predict
w = torch.rand([1,1],requires_grad=True)
# 只有浮点型的tensor才可以使用requires_grad=True属性,所以需要指定dtype=torch.float32
b = torch.tensor(0,requires_grad=True,dtype=torch.float32)# 4. 通过循环,反向传播,更新参数
for i in range(3000):# 3. 计算loss# matmul计算矩阵乘积y_predict = torch.matmul(x,w) + b# 取均值方差当做损失函数loss = (y_true-y_predict).pow(2).mean()if w.grad is not None:w.grad.data.zero_()if b.grad is not None:b.grad.data.zero_()loss.backward() # 反向传播w.data = w.data - learning_rate*w.gradb.data = b.data - learning_rate*b.gradif i %50 == 0:print("w:{}, b:{}, loss:{}".format(w.item(),b.item(),loss.item()))plt.figure(figsize=[20,8])
plt.scatter(x.numpy().reshape(-1),y_true.numpy().reshape(-1))
y_predict = torch.matmul(x,w) + b
plt.plot(x.numpy().reshape(-1),y_predict.detach().numpy().reshape(-1))
plt.show()

模型训练上3000次后得到w和b接近相等

3.Pytorch完成模型常用API

在上面部分,我们实现了通过torch完成反向传播和参数更新,当参数较多时,使用上面方法有点复杂。下面了解以下常用的API

3.1 nn.Module

nn.Moduletorch.nn提供的一个类,是pytorch中我们自定义网络的一个基类。当我们自定义网络的时候,有两个方法需要注意:

  1. __init__需要调用super方法,继承父类的属性和方法。
  2. forward方法必须实现,用来定义我们的网络的向前计算的过程。
    用前面的y=wx+by=wx+by=wx+b的模型举例如下:
class lr(nn.Module):def __init__(self):super(lr,self).__init__()       # 继承父类init的参数self.linear = nn.Linear(1,1)def forward(self, x):out = self.linear(x)return out

注意:

  1. nn.Linear为torch预定义好的线性模型,也称为全连接层,传入的参数为输入的数量,输出的数量(in_features,out_features),其中不算batch_sizer的列数
    2.nn.Module定义了__call__方法,实现的就是调用forward方法 ,能够直接被传入单数调用,实际上调用的就是forward方法并传入参数。
 # 实例化模型model = lr()# 传入数据,计算结果predict = model(x)

3.2优化器类

优化器(optimizer),可以理解为torch为我们封装的用来进行更新参数的方法,比如常见的随机梯度下降。
优化器都是由torch.optim提供的,例如:
1.torch.optim.SGD(参数,学习率)
2. torch.optim.Adam(参数,学习率)
注意:

  • 参数可以使用model.parameters()来获取,获取模型中所有requires_grad=True的参数
  • 优化类的使用方法
    * 实例化
    * 将所有参数的梯度值设为0
    * 反向传播计算梯度
    * 更新参数值
optimizer = optim.SGD(model.parameters(),lr = 1e-3)# 1.实例化
# 因为PyTorch默认会对梯度进行累加,不想先前的梯度影响到当前梯度的计算时需要手动清零
optimizer.zero_grad()# 2.梯度置为0
loss.backward()# 3.计算梯度
optimizer.step()# 4. 更新参数的值

3.3损失函数

torch中的损失函数:

  1. 均方误差:nn.MSELoss(),常用于分类问题
  2. 交叉熵损失:nn.CrossEntropyLoss(),常用于逻辑回归
    使用方法:
model = lt()# 1.实例化模型
criterion = nn.MSELoss()# 2.实例化损失函数
optimizer = optim.SGD(model.parameters(),lr = 1e-3)# 3.实例化优化器类
for i in range(100):y_predict = model(x_true)# 4.向前计算预测值loss = criterion(y_true,y_predict)# 5. 调用损失函数传入真实值和预测值,得到损失结果optimizer.zero_grad()# 5.当前循环参数梯度置为0loss.backward()# 6.计算梯度optimizer.step()# 7.更新参数的值

pytorch实现线性回归完整代码:

import torch
from torch import optim
from torch import nn
import matplotlib.pyplot as plt# 1. 定义数据
x = torch.rand([50,1])
y = x*3 + 0.8# 2. 定义lr模型
class lr(nn.Module):def __init__(self):super(lr,self).__init__()       # 继承父类init的参数self.linear = nn.Linear(1,1)def forward(self, x):out = self.linear(x)return outdef main():# 2. 实例化模型,loss和优化器model = lr()criterion = nn.MSELoss()optimizer = optim.SGD(model.parameters(),1e-3)# 3. 训练模型for i in range(3000):out = model(x)  # 获取预测值loss = criterion(y,out)     # 计算损失optimizer.zero_grad() # 梯度置0loss.backward()     # 计算梯度optimizer.step()    # 更新梯度if i%20 == 0:# 可以通过model.parameters()来说输出参数变化 params = list(model.parameters())print(params[0].item(),params[1].item())print("loss:%6f"%loss.data)print('Epoch[{}/{}],loss:{:.6f}'.format(i,3000,loss.data))# 4. 模型评估model.eval()predict = model(x)predict = predict.data.numpy()plt.scatter(x.data.numpy(),y.data.numpy(),c='r')plt.plot(x.data.numpy(),predict)plt.show()
if __name__ == '__main__':main()

model.eval()表示设置模型为评估模式,即预测模式
model.train(mode=True)表示设置模型为训练模式
在当前的线性回归中,上述并无区别。
但是在其他的一些模型中,训练的参数和预测的参数会不相同,到时候就需要具体分清楚是在进行训练还是预测,比如模型中存在Dropout,BatchNorm的时候。

3.4 使用GPU训练

当模型太大或者参数太多的时候,可以使用GPU来加快训练速度。

  1. 判断GPU是否可用torch.cuda.is_avaiable(),如果可用创建GPU的device;
device = torch.device("cuda" if torch.cuda.is_avaiable() else "cpu")
  1. 把模型参数和input数据转化为cuda 的支持类型;
model.to(device)
x_true.to(device)
  1. 在GPU上计算结果也为cuda数据类型,需要转化为numpy或者torch的cpu的tensor类型;
predict = predict.cpu().detach().numpy()

detach()的效果和data的相似,但是detach()是深拷贝,data是取值,是浅拷贝。
修改之后的代码为:

import torch
from torch import optim
from torch import nn
import matplotlib.pyplot as pltdevice = torch.device("cuda" if torch.cuda.is_avaiable() else "cpu")# 1. 定义数据
x = torch.rand([50,1]).to(device) # 修改为GPU的tensor
y = x*3 + 0.8# 2. 定义lr模型
class lr(nn.Module):def __init__(self):super(lr,self).__init__()       # 继承父类init的参数self.linear = nn.Linear(1,1)def forward(self, x):out = self.linear(x)return outdef main():# 2. 实例化模型,loss和优化器model = lr().to(device)  # 修改为GPU的模型criterion = nn.MSELoss()optimizer = optim.SGD(model.parameters(),1e-3)# 3. 训练模型for i in range(3000):out = model(x)  # 获取预测值loss = criterion(y,out)     # 计算损失optimizer.zero_grad() # 梯度置0loss.backward()     # 计算梯度optimizer.step()    # 更新梯度if i%20 == 0:print("loss:%6f"%loss.data)print('Epoch[{}/{}],loss:{:.6f}'.format(i,3000,loss.data))# 4. 模型评估model.eval()predict = model(x)predict = predict.data.numpy()plt.scatter(x.data.numpy(),y.data.numpy(),c='r')plt.plot(x.data.numpy(),predict)plt.show()if __name__ == '__main__':main()

在GPU上执行程序需要注意:

  • 自定义的参数和数据需要转化为cuda支持的tensor
  • model需要转化为cuda支持的model
  • 执行的结果需要和cpu的tensor计算的时候,tensor.cpu()可以把cuda的tensor转化为cpu的tensor。

Pytorch完成线性回归相关推荐

  1. pytorch:一维线性回归(二)

    首先,这是对上一篇文章(pytorch:一维线性回归(一))的改进. 其次,为什么想要改进上一篇文章嘞? 答案:我使用这个写好的模型后,想着既然参数已经训练出来了,那么预测的时候,就只需要直接根据参数 ...

  2. (pytorch-深度学习系列)pytorch实现线性回归

    pytorch实现线性回归 1. 实现线性回归前的准备 线性回归输出是一个连续值,因此适用于回归问题.回归问题在实际中很常见,如预测房屋价格.气温.销售额等连续值的问题. 与回归问题不同,分类问题中模 ...

  3. 使用Tensorflow2和Pytorch实现线性回归

    使用Tensorflow2和Pytorch实现线性回归 步骤 Tensorflow2代码 效果 Pytorch代码 效果 步骤 准备步骤: 1. 创建数据集 2. 设置超参数 3. 创建模型(函数) ...

  4. 深度学习day05 用Pytorch实现线性回归

    深度学习day05 用Pytorch实现线性回归 代码模板 四个主要流程 代码中的一些重点 其他的优化器 代码模板 import torch# 步骤一:Prepare dataset # x,y是矩阵 ...

  5. L05_用pytorch实现线性回归

    用pytorch实现线性回归 0.导入所需要的库 import torch 1.准备数据 x_data = torch.Tensor([[1],[2],[3]]) y_data = torch.Ten ...

  6. 深度学习练手项目(二)-----利用PyTorch进行线性回归

    前言 深度学习并没有想象的那么难,甚至比有些传统的机器学习更简单.所用到的数学知识也不需要特别的高深.这篇文章将利用PyTorch来实现线性回归这个经典的模型. 一.线性回归理论 线性回归时利用数理统 ...

  7. 从零开始学Pytorch之线性回归

    线性回归 主要内容包括: 线性回归的基本要素 线性回归模型从零开始的实现 线性回归模型使用pytorch的简洁实现 线性回归的基本要素 模型 为了简单起见,这里我们假设价格只取决于房屋状况的两个因素, ...

  8. pytorch 实现线性回归

    实现线性回归 线性回归是机器学习入门知识,应用十分广泛.线性回归利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的,其表达形式为 y = w x + b + e y = wx+b+ ...

  9. PyTorch基础-线性回归以及非线性回归-02

    线性回归 import torch import numpy as np import matplotlib.pyplot as plt %matplotlib inline from torch i ...

  10. pytorch:一维线性回归(一)

    # -- coding:utf-8 -- import torch import numpy as np from torch import nn, optim import matplotlib.p ...

最新文章

  1. php实现姓名按首字母排序的类与方法
  2. NET问答: 如何在 ASP.NET Core Web API 的 Response 中添加自定义的 Header ?
  3. USACO-Section2.2 Party Lamps
  4. 两位小数乘两位小数竖式_冀教版五年级数学上册2.4小数乘小数微课视频 | 练习...
  5. 快速搭建博客:美化主题
  6. Win10系统下使用Setuna截图自动放大解决办法
  7. 充电头PD协议和QC协议的理解
  8. 用两种while循环求2的n次方,n是传入的值。
  9. Linux的PS1美化
  10. Onetab快速删除所有历史网页
  11. C语言实现wav文件的读写
  12. 最全面的Python重点知识汇总,建议码住
  13. 软件测试面试,一定要准备的7个高频面试题(附答案,建议收藏)
  14. 在html文件中url称之为什么,html+css网页设计复习题
  15. java序列化指的是什么,java的序列化是什么
  16. 泡泡机器人原创专栏-Cartographer】Cartographer理论及实现浅析
  17. 超好用的图片压缩网站
  18. 毕业设计-基于微信小程序的“安心乘车”服务系统
  19. java限制手机号码,更严格的手机号码正则表达式写法 --java
  20. 比尔·盖茨2015荐书

热门文章

  1. 1. 路过面了个试就拿到2个offer。是运气吗?
  2. vb.net学习笔记
  3. CS20Chapter2
  4. Vs2010中水晶报表引用及打包
  5. freeRADIUS下EAP测试
  6. EMNLP 2020 可解释性推理
  7. 教育部建议采纳:给予导师决定硕博士能否毕业的自主权!
  8. 【实践】BiLSTM上的CRF,用命名实体识别任务来解释CRF(1)
  9. 【实践】BiLSTM上的CRF,用命名实体识别任务来解释CRF(2)损失函数
  10. 【Linux】用户必须知道的常用终端快捷键