当前位置: 首页 > news >正文

【PyTorch】入门知识

入门知识

本文档基于官网的60min入门教程
《What is PyTprch》
《PyTorch深度学习:60分钟快速入门(官网翻译)》By 黄海广
部分内容来自于《PyTorch机器学习从入门到实战》–机械工业出版社

numpy常用数值操作及特性

pytorch库中有很多操作都可以类比和借鉴numpy库中的处理,且在机器学习中numpy也是一个很重要的强大的数值处理库,建议读者先理一下numpy中的常用操作。

p.s. 以下整理了一些numpy库的思维导图,读者可以对照进行查漏,如果之前没有用过numpy的可以戳下方链接,快速入门~
《numpy教程|菜鸟教程》

在这里插入图片描述

又因为numpy库中最重要的一个数据结构就是被称作ndarray的多维数组,其很多特性和操作也可以借鉴python中的列表类型,下方对list的一些概念也进行了整理。
p.s. 整理得很简单,只能用于简单梳理。

在这里插入图片描述


什么是PyTorch

PyTorch是一个基于Python的科学计算软件包,主要针对以下两组受众:

  • 为了使用GPU的计算功能,用其替代numpy
  • 追求灵活和速度的深度学习研究平台

在这里插入图片描述


Autograd:自动求导

  1. 张量(tensor)与ndarray

tensor之于pytorch的关系可以类比ndarray基于numpy的关系,且二者在类型、声明、定义以及运算上有很大的相似性。

【相似的操作】(例举)

x = torch.empty(m,n)#构造一个未初始化的mxn的矩阵
x = torch.rand(m,n)#构造一个随机初始化的mxn的矩阵
x = torch.zeros(m,n,dtype = torch.long)#用零填充一个mxn的矩阵,且元素为long类型
x = torch.tensor([1,2,3]) #通过已知数据来构造张量

【有些许差别的操作】(例举)

x = torch.rand(m,n)
y = x.view(s,t)#将mxn的矩阵x变成sxt维度的矩阵,且是新建改变

x = torch.rand(1)
x.item() #用.item()方法使单个元素张量作为python数字来获得
  1. 张量与梯度(Gradient)
    在这里插入图片描述

上图中粉色框框中是需要额外注意的地方,以下也会对其进行一些解释。

[1]:.grad_fn这个属性就是表明了每一个tensor和与之相对应的计算function。

  • 用户自己创建的张量对象没有该属性,因为并不是由相关计算得到的
  • 根据计算的不同类型,grad_fn属性也是不同
  • 如果requires_grad属性未设置True,则得不到相应的grad_fn属性,因为你没有允许其追踪计算记录。
import torch
x = torch.ones(2,2)
y = x + 2
z = x * 3
print(x.grad_fn)
print(y.grad_fn)
print(z.grad_fn)
#None
#None
#None

x = torch.ones(2,2,requires_grad = True)
y = x + 2
z = x * 3
print(x.grad_fn)
print(y.grad_fn)
print(z.grad_fn)
#None
#<AddBackward0 object at 0x000002392660F240>
#<MulBackward0 object at 0x000002392660F2B0>

[2]:防止张量跟踪计算的历史记录和内存使用情况

  • 在初始化一个张量时,.requires_grad属性不显式地设置为True
  • 使用torch.no_grad()来包装代码块
import torch
x = torch.ones(2,2,requires_grad = True)
print(x.requires_grad)
print((x*2).requires_grad)

with torch.no_grad():
  print((x*2).requires_grad)

#True
#True
#False

神经网络

神经网络根据其深度与结构也有深度与否的区别,一个简单的含有输入层-隐含层-输出层的前馈神经网络,只需要弄明白关于前向计算、反向传播、损失函数、激活函数的知识即可。

详情可移步博文《【PyTorch】深度学习基础:神经网络》

1. 单层神经网络的PyTorch实现

下面基于上一篇博文中的一些基础知识,对只含有1层线性隐含层的神经网络进行搭建、训练,

神经网络训练的步骤:

  • 数据准备

数据准备——将我们所要使用的数据转换成PyTorch能够处理的格式:对数据集的封装,把结构数据划分成batch。
①提供torch.utils.data.Dataset对数据进行封装
该类别是所有需要加载数据集的父类,在定义子类时需要重载_len__getitem_两个函数,前者返回数据集的大小,后者实现数据集的下标索引。

②使用torch.utils.data.DataLoader对数据进行加载、采样和迭代器的生成

class torch.utils.data.DataLoader(dataset,batch_size = 1,shuffle = False, sampler = None,batch_sampler = None,num_workers = 0,collate_fn = <function default_collate>, pin_memory = False,drop_last = False)

  • datasetDataset的类型,指出要加载的数据集
  • batch_size指出每个batch需要加载多少样本,默认值为1
  • shuffle指出是否在每个epoch都需要对数据进行打乱
  • sampler从数据集中采样样本的策略
  • batch_sampler与sampler相似,只不过一次会返回一批指标
  • num_workers加载数据时所使用的子进程数目。默认值为0,表示在主进程中加载数据
  • collate_fn定义合并样本列表以形成一个mini_batch
  • pin_memory若设置为true,则数据加载器会将张量复制到CUDA固定内存中,然后返回它们。
  • drop_last若设置为true,最后一个不完整的batch将会被丢弃。
  • 构建网络结构,初始化权重
  • 确定激活函数
  • 进行前向计算
  • 确定损失函数,计算损失值
  • 反向传播并更新参数
    重复上述前向计算与反向传播的过程,直到收敛或达到终止条件。
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
from sklearn.datasets import load_iris
from torch.autograd import Variable
from torch.optim import SGD

#动态判断GPU是否可用,方便在不同类型的处理器上进行迁移
use_cuda = torch.cuda.is_available()
print("use_cuda: ",use_cuda)

#加载数据集,因为是模块里封装好的数据集,只需加载即可使用
iris = load_iris()
print(iris.keys())

#数据预处理,从数据集中将输入输出的信息分离出来并封装成Variable形式
x=iris['data']
y = iris['target']
x = torch.FloatTensor(x)
y = torch.LongTensor(y)

x,y = Variable(x),Variable(y)

#定义神经网络模型
'''
PyTorch中自定义的模型都需要继承Module,并重写forward方法完成前向计算
'''
class Net(torch.nn.Module):
    #初始化函数接受自定义额输入特征维数、隐含层特征维数和输出层的特征维数
    def __init__(self,n_feature,n_hidden,n_output):
        super(Net,self).__init__()
        self.hidden = torch.nn.Linear(n_feature,n_hidden)#线性隐含层
        self.predict = torch.nn.Linear(n_hidden,n_output)#线性输出层
        
    #重写前向传播过程
    def forward(self,x):
        x = F.sigmoid(self.hidden(x))
        x = self.predict(x)
        out = F.log_softmax(x,dim = 1)
        return out
    
#网络实例化并打印查看网络结构
net = Net(n_feature = 4,n_hidden = 5,n_output = 4)
print(net)
#根据iris数据集,输入特征必须是4维的,其余两层的特征维数可以自行选择
    
#判断GPU是否可用,可以灵活调整数据计算
if use_cuda:
    x = x.cuda()
    y = y.cuda()
    net = net.cuda()
        
#定义神经网络训练的优化器,并设置学习率为0.5
optimizer = SGD(net.parameters(),lr = 0.5)
    
#进行训练
px,py = [],[]#用于记录要绘制的数据
for i in range(1000):
    #数据传入网络并进行前向计算
     prediction = net(x)
        
    #计算loss
     loss = F.nll_loss(prediction,y)
        
    #清除网络状态
     optimizer.zero_grad()
        
    #loss反向传播
     loss.backward()
        
    #更新参数
     optimizer.step()
        
    #在训练过程中打印每次迭代的损失情况
     print(i," loss: ",loss.data.item())
     px.append(i)
     py.append(loss.data.item())
        
    #每10次迭代绘制训练动态
        
     if i % 10 == 0:
        plt.cla()
        plt.plot(px,py,'r-',lw = 1)
        plt.text(0,0,'Loss = %.4f' % loss.data.item(),fontdict = {'size':20,'color':'red'})
        plt.pause(0.1)
    

2. PyTorch中神经网络的调用机制
在这里插入图片描述
3. PyTorch构建神经网络分类器

有关损失函数、目标函数与优化器的细节可参考下面这篇博文
《【PyTorch】深度神经网络及训练》

利用PyTorch搭建一个由一层输入层、一层全连接的隐层和一层输出层构成的神经网络,对MNIST数据集进行分类。

读者可以借助以下代码对神经网络的特征与参数配置进行熟悉

(1)配置参数

'''
配置库和配置参数
'''
import torch
import torch.nn as nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.autograd import Variable

#配置超参数
torch.manual_seed(1)#设置随机数种子,确保结果可能会重复
input_size = 784
hidden_size = 500
num_classes = 10
num_epochs = 5#训练次数
batch_size = 100#批处理大小
learning_rate = 0.001

(2)加载数据集

'''
加载MINST数据集
'''
train_dataset = dsets.MNIST(root= './data',train = True,transform = transforms.ToTensor(),download = True)
#将数据集下载(download)作为训练集(train),其中指定数据保持的位置(root),并且将取值范围从[0,255]转换成[0,1.0](transform)
test_dataset = dsets.MNIST(root = './data',train = False,transform = transforms.ToTensor())
#另保存一份测试集,同样需要进行数值转换

(3)批处理设置

'''
数据批处理设置
'''
#DataLoader(Input Pipeline)
#在训练集中,shuffle必须设置为True,表示次序是随机的
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,batch_size = batch_size,shuffle = True)
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,batch_size = batch_size,shuffle = False)

(4)构建DNN模型

'''
创建DNN模型
'''
class Net(nn.Module):
    def __init__(self,input_size,hidden_size,num_classes):
        super(Net,self).__init__()
        self.fc1 = nn.Linear(input_size,hidden_size)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_size,num_classes)
    
    def forward(self,x):
        out = self.fc1(x)
        out = self.relu(out)
        out = self.fc2(out)
        return out
net = Net(input_size,hidden_size,num_classes)
#打印模型,呈现网络结构
print(net)    

【输出结果】
Net(
(fc1): Linear(in_features=784, out_features=500, bias=True)
(relu): ReLU()
(fc2): Linear(in_features=500, out_features=10, bias=True)
)

(5)模型训练

'''
模型训练,将图像和标签都用Variable类进行包装,然后放入模型中进行输出
'''
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(),lr = learning_rate)

#开始训练
for epoch in range(num_epochs):
    for i,(images,labels) in enumerate(train_loader):#进行批处理
        #将tensor类型转换成Variable类型
        images = Variable(images.view(-1,28*28))
        Labels = Variable(labels)
        
        #前向计算+反向传播+使用优化器
        optimizer.zero_grad()#梯度清零
        
        outputs = net(images)
        loss = criterion(outputs,labels)
        loss.backward()#后向传播,计算梯度
        optimizer.step()#梯度更新
        
        if(i+1)%100 == 0:
            print('Epoch [%d/%d],Step[%d/%d],Loss: %.4f'%(epoch+1,num_epochs,i+1,len(train_dataset)//batch_size,loss.data.item()))

【输出结果】
Epoch [1/5],Step[100/600],Loss: 0.1175
Epoch [1/5],Step[200/600],Loss: 0.1390
Epoch [1/5],Step[300/600],Loss: 0.2715
Epoch [1/5],Step[400/600],Loss: 0.1825
Epoch [1/5],Step[500/600],Loss: 0.1173
Epoch [1/5],Step[600/600],Loss: 0.1280
Epoch [2/5],Step[100/600],Loss: 0.1060
Epoch [2/5],Step[200/600],Loss: 0.0543
Epoch [2/5],Step[300/600],Loss: 0.1447
Epoch [2/5],Step[400/600],Loss: 0.1715
Epoch [2/5],Step[500/600],Loss: 0.0646
Epoch [2/5],Step[600/600],Loss: 0.0643
Epoch [3/5],Step[100/600],Loss: 0.1027
Epoch [3/5],Step[200/600],Loss: 0.0191
Epoch [3/5],Step[300/600],Loss: 0.0442
Epoch [3/5],Step[400/600],Loss: 0.0599
Epoch [3/5],Step[500/600],Loss: 0.0470
Epoch [3/5],Step[600/600],Loss: 0.0422
Epoch [4/5],Step[100/600],Loss: 0.0448
Epoch [4/5],Step[200/600],Loss: 0.1024
Epoch [4/5],Step[300/600],Loss: 0.0436
Epoch [4/5],Step[400/600],Loss: 0.0686
Epoch [4/5],Step[500/600],Loss: 0.0393
Epoch [4/5],Step[600/600],Loss: 0.0179
Epoch [5/5],Step[100/600],Loss: 0.0292
Epoch [5/5],Step[200/600],Loss: 0.0473
Epoch [5/5],Step[300/600],Loss: 0.0563
Epoch [5/5],Step[400/600],Loss: 0.0552
Epoch [5/5],Step[500/600],Loss: 0.0352
Epoch [5/5],Step[600/600],Loss: 0.0244

(6)测试集上验证

'''
在测试集测试识别率
'''
correct = 0
total = 0
for images,labels in test_loader:
    images = Variable(images.view(-1,28*28))
    outputs = net(images)
    _,predicted = torch.max(outputs.data,1)#得到预测结果
    total += labels.size(0)#正确结果
    correct += (predicted == labels).sum()#正确结果总数
print('Accuracy of the network on the 10000 test images: %d %%' % (100*correct // total))

【输出结果】
Accuracy of the network on the 10000 test images: 97 %

相关文章:

  • 【矩阵论】范数和矩阵函数(2)
  • 【矩阵论】矩阵的广义逆
  • 【吴恩达CNN】week1:卷积与池化
  • 【最优化】最优化理论的基本概念
  • 【最优化】最优化的相关条件
  • 【最优化】一维搜索技术
  • 【最优化】无约束梯度算法
  • 【信号与系统|吴大正】1:信号与系统概述
  • 【最优化】二阶收敛算法
  • 【最优化】拉格朗日乘子法
  • 【PyTorch】卷积神经网络
  • 【最优化】数值优化算法
  • 【信号与系统|吴大正】2:连续系统的时域分析
  • 【MIT算法导论】哈希表、全域哈希
  • 【吴恩达CNN】week2:深度卷积网络
  • 网络传输文件的问题
  • Angular 2 DI - IoC DI - 1
  • CentOS7简单部署NFS
  • CSS 专业技巧
  • Docker下部署自己的LNMP工作环境
  • express + mock 让前后台并行开发
  • JavaScript异步流程控制的前世今生
  • markdown编辑器简评
  • maven工程打包jar以及java jar命令的classpath使用
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 彻底搞懂浏览器Event-loop
  • 翻译--Thinking in React
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 简单数学运算程序(不定期更新)
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 前端之React实战:创建跨平台的项目架构
  • 一些css基础学习笔记
  • 你对linux中grep命令知道多少?
  • 阿里云ACE认证之理解CDN技术
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #define与typedef区别
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (2)MFC+openGL单文档框架glFrame
  • (31)对象的克隆
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (二)丶RabbitMQ的六大核心
  • (附源码)springboot太原学院贫困生申请管理系统 毕业设计 101517
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (论文阅读11/100)Fast R-CNN
  • (全部习题答案)研究生英语读写教程基础级教师用书PDF|| 研究生英语读写教程提高级教师用书PDF
  • (十) 初识 Docker file
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)大型网站架构演变和知识体系
  • .bat批处理出现中文乱码的情况
  • .htaccess配置常用技巧
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析