1. pytorch入门

什么是PYTORCH?
这是一个基于Python的科学计算软件包,针对两组受众:

  • 替代NumPy以使用GPU的功能
  • 提供最大灵活性和速度的深度学习研究平台

1.1 开发环境

anaconda安装pytorch

import torch

1.2 pytorch中的tensor

Tensor是PyTorch中的基础组件,和tensorflow中的tensor类似。

tensor初始化

x = torch.empty(5, 3)
print(x)
"""
output:
tensor([[0., 0., 0.],[0., 0., 0.],[0., 0., 0.],[0., 0., 0.],[0., 0., 0.]])
"""print(x.size())
# output: torch.Size([5, 3])

tensor运算

x = torch.empty(5, 3)
y = torch.rand(5, 3)
print(x + y)
# adds x to y
y.add_(x)
print(y)
"""
output:
tensor([[ 1.4519,  0.7577,  1.4506],[ 0.3557,  0.8496,  0.1852],[ 0.6745,  0.4696,  1.6169],[-1.3345, -0.6746,  1.4474],[ 1.0803,  2.1400,  1.1899]])
"""
# 索引
print(y[:, 1])
# output: tensor([ 0.7577, 0.8496, 0.4696, -0.6746,  2.1400])# 调整大小
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8)  # the size -1 is inferred from other dimensions
print(x.size(), y.size(), z.size())
# output: torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

1.3 自动求导AUTOGRAD

我们知道,深度学习最核心的其中一个步骤,就是求导:

根据函数(linear + activation function)求weights相对于loss的导数。然后根据得出的导数,相应的修改weights,让loss最小化。

我们来看看pytorch是怎么自动求导的:
在pytorch框架中,autograd包对tensor的所有运算提供了自动求导机制。

来段代码感受下

import torcha = torch.tensor(2.0, requires_grad=True) # 如果将torch.Tensor类的属性.requires_grad赋为True,它就会跟踪该张量上的所有操作。
b = torch.tensor(3.0, requires_grad=True)
c = a + b
d = torch.tensor(4.0, requires_grad=True)
e = c * d# 当你完成了运算可以调用.backward()来自动计算所有的梯度(gradient)。该张量的梯度会累积记录于.grad属性中。
e.backward() # 执行求导a.grad  # a.grad 即导数 d(e)/d(a) 的值
tensor(4.)

这里让人感觉别扭的是,调用 e.backward() 执行求导,为什么会更新 a 对象的状态 grad ?

我们需要理解pytorch中的另一个重要的元素Function。

1.4 pytorch中的Function

在pytorch框架中,tensor和Function是两个基本组成部分,它们共同构成了pytorch的计算图。

Function 指的是在计算图中某个节点(node)所进行的运算:比如加减乘除卷积等等之类的,Function 内部有 forward() 和 backward() 两个方法,分别应用于正向、反向传播。

a = torch.tensor(2.0, requires_grad=True)
b = a.exp()
print(b)
# tensor(7.3891, grad_fn=<ExpBackward>)

在我们做正向传播的过程中,除了执行 forward() 操作之外,还会同时会为反向传播做一些准备,为反向计算图添加 Function 节点。在上边这个例子中,变量 b 在反向传播中所需要进行的操作是 ExpBackward 。

1.4 计算图(Computational Graphs)

可能大家都听说过,PyTorch 使用的是动态图(Dynamic Computational Graphs)的方式,而 TensorFlow 使用的是静态图(Static Computational Graphs)。

所以到底什么是Computational Graph?动态图和静态图又有什么区别呢?

先简单地介绍一下什么是计算图(Computational Graphs),以方便后边的讲解。

假设我们有一个复杂的神经网络模型,我们把它想象成一个错综复杂的管道结构,不同的管道之间通过节点连接起来,我们有一个注水口,一个出水口。

我们在入口注入数据的之后,数据就沿着设定好的管道路线缓缓流动到出水口,这时候我们就完成了一次正向传播。想象一下输入的 tensor 数据在管道中缓缓流动的场景,这就是为什么 TensorFlow 叫 TensorFlow 的原因!emmm,好像走错片场了,不过计算图在 PyTorch 中也是类似的。

1.5 动态图,静态图

所谓动态图,就是每次当我们搭建完一个计算图,然后在反向传播结束之后,整个计算图就在内存中被释放了。如果想再次使用的话,必须从头再搭一遍。

# 这是一个关于 PyTorch 是动态图的例子:
a = torch.tensor([3.0, 1.0], requires_grad=True)
b = a * a
loss = b.mean()loss.backward() # 正常
loss.backward() # RuntimeError# 第二次:从头再来一遍
a = torch.tensor([3.0, 1.0], requires_grad=True)
b = a * a
loss = b.mean()
loss.backward() # 正常

而以 TensorFlow 为代表的静态图,每次都先设计好计算图,需要的时候实例化这个图,然后送入各种输入,重复使用,只有当会话结束的时候创建的图才会被释放,就像我们之前举的那个水管的例子一样,设计好水管布局之后,需要用的时候就开始搭,搭好了就往入口加水,什么时候不需要了,再把管道都给拆了。

2. 基于pytorch实现图像分类

2.1 加载训练和测试数据集

加载和标准化CIFAR10训练和测试数据集 torchvision

import torch
import torchvision
import torchvision.transforms as transformstransform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])trainset = torchvision.datasets.CIFAR10(root='./data', train=True,download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,shuffle=True, num_workers=2)testset = torchvision.datasets.CIFAR10(root='./data', train=False,download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,shuffle=False, num_workers=2)classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')

查看我们的训练集

import matplotlib.pyplot as plt
import numpy as np# functions to show an image
def imshow(img):img = img / 2 + 0.5     # unnormalizenpimg = img.numpy()plt.imshow(np.transpose(npimg, (1, 2, 0)))plt.show()# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))

2.2 定义卷积神经网络

import torch.nn as nn
import torch.nn.functional as Fclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.pool = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(6, 16, 5)self.fc1 = nn.Linear(16 * 5 * 5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 10)def forward(self, x):x = self.pool(F.relu(self.conv1(x)))x = self.pool(F.relu(self.conv2(x)))x = x.view(-1, 16 * 5 * 5)x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.fc3(x)return xnet = Net()

2.3 定义损失函数和优化器

import torch.optim as optimcriterion = nn.CrossEntropyLoss() # 损失函数
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 优化器

2.4 训练神经网络

我们只需要遍历数据迭代器,然后将输入馈送到网络并进行优化

for epoch in range(2):  # loop over the dataset multiple timesrunning_loss = 0.0for i, data in enumerate(trainloader, 0):# get the inputs; data is a list of [inputs, labels]inputs, labels = data# zero the parameter gradientsoptimizer.zero_grad()# forward + backward + optimizeoutputs = net(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()# print statisticsrunning_loss += loss.item()if i % 2000 == 1999:    # print every 2000 mini-batchesprint('[%d, %5d] loss: %.3f' %(epoch + 1, i + 1, running_loss / 2000))running_loss = 0.0print('Finished Training')

输出结果

[1,  2000] loss: 2.171
[1,  4000] loss: 1.835
[1,  6000] loss: 1.649
[1,  8000] loss: 1.569
[1, 10000] loss: 1.505
[1, 12000] loss: 1.454
[2,  2000] loss: 1.381
[2,  4000] loss: 1.347
[2,  6000] loss: 1.329
[2,  8000] loss: 1.310
[2, 10000] loss: 1.292
[2, 12000] loss: 1.284
Finished Training

保存我们训练有素的模型

PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)

2.5 在测试数据集上测试神经网络准确性

重新加载保存的模型

net = Net()
net.load_state_dict(torch.load(PATH))

运行测试集

correct = 0
total = 0
with torch.no_grad():for data in testloader:images, labels = dataoutputs = net(images) # 在测试数据上运行神经网络,得到结果_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))

输出

Accuracy of the network on the 10000 test images: 54 %

2.6 在GPU上训练

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
inputs, labels = data[0].to(device), data[1].to(device)

3. 参考

使用PyTorch进行深度学习:60分钟的闪电战 – h ttps://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html#sphx-glr-beginner-blitz-tensor-tutorial-py

PyTorch 的 Autograd – https://zhuanlan.zhihu.com/p/69294347

基于pytorch实现图像分类——理解自动求导、计算图、静态图、动态图、pytorch入门相关推荐

  1. PyTorch定义新的自动求导(Autograd) 函数

    PyTorch定义新的自动求导(Autograd) 函数 pytorch官网提供了定义新的求导函数的方法(链接放在文章末尾了),官网举的例子,可能我比较笨,愣是反应了好一会儿才理解.这篇博客主要讲 P ...

  2. 【PyTorch学习(三)】Aurograd自动求导机制总结

    ​Aurograd自动求导机制总结 PyTorch中,所有神经网络的核心是 autograd 包.autograd 包为tensor上的所有操作提供了自动求导机制.它是一个在运行时定义(define- ...

  3. pytorch如何计算导数_Pytorch的自动求导机制与使用方法(一)

    本文以线性模型为例,讲解线性模型的求解的pytorch梯度实现方法. 要注意几个问题:在PyTorch 0.4.0版本之后,Variable类已经被禁用了,所有的torch.Tensor与torch. ...

  4. 【深度学习】pytorch自动求导机制的理解 | tensor.backward() 反向传播 | tensor.detach()梯度截断函数 | with torch.no_grad()函数

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.pytorch里自动求导的基础概念 1.1.自动求导 requires_grad=True 1.2.求导 requ ...

  5. PyTorch基础(二)-----自动求导Autograd

    一.前言 上一篇文章中提到PyTorch提供了两个重要的高级功能,分别是: 具有强大的GPU加速的张量计算(如NumPy) 包含自动求导系统的的深度神经网络 第一个特性我们会在之后的学习中用到,这里暂 ...

  6. [pytorch]计算图:对神经网络的图式描述:自动求导的数学基础

    学长让学pytorch库,说是可以让程序在GPU上跑起来. 刚开始看的doc 没什么耐心和线索,失败 又去b站看了看网课,还不太准确,失败 直接上了web感觉还不太行 又去蓝桥上找了个lab lab ...

  7. Pytorch学习(一)—— 自动求导机制

    现在对 CNN 有了一定的了解,同时在 GitHub 上找了几个 examples 来学习,对网络的搭建有了笼统地认识,但是发现有好多基础 pytorch 的知识需要补习,所以慢慢从官网 API 进行 ...

  8. 深度学习PyTorch笔记(9):自动求导

    深度学习PyTorch笔记(9):自动求导 4. 自动求导 4.1 理解 4.2 梯度 4.3 .requires_grad与.grad_fn 4.4 调用.backward()反向传播来完成所有梯度 ...

  9. PyTorch 笔记Ⅱ——PyTorch 自动求导机制

    文章目录 Autograd: 自动求导机制 张量(Tensor) 梯度 使用PyTorch计算梯度数值 Autograd 简单的自动求导 复杂的自动求导 Autograd 过程解析 扩展Autogra ...

最新文章

  1. C++友元与输出运算符重载
  2. 收藏!40 个 CSS 布局技巧
  3. vue父组件异步获取动态数据传递给子组件获取不到值
  4. 2015workshop-age 的txt 生成过程
  5. 解决CentOS出现“No package redis available“提示问题
  6. 【报告分享】5G网络切片分级白皮书.pdf(附下载链接)
  7. Multimedia框架
  8. 生如夏花之绚烂,Lisp风格的Lialang诞生了!
  9. 2018年大数据的发展趋势,小白学前必备
  10. 关于locale的设定
  11. Linux--信号signal、父子进程、SIGCHLD信号相关命令
  12. Windows驱动的彻底删除
  13. SCI回复审稿意见的模板
  14. 如何用html5制作抽奖游戏,原生js实现抽奖小游戏
  15. 【kmp】似乎在梦中见过的样子
  16. 王者荣耀(王者农药)小程序版加符文模拟器我来了
  17. UPC 2020年夏混合个人训练第七十五场
  18. 反激式开关电源设计方案,12V6A输出,有完整原理图
  19. 商业搜索引擎大行其道 未来规模将超越ERP
  20. 摄像头码流怎么设置_【干货】一个无线网桥可以带多少个摄像头?

热门文章

  1. matlab 均值滤波_数字图像处理基础 — 高斯滤波
  2. 人类一败涂地电脑版_iOS账号分享 |人类一败涂地 我们继续相爱相杀,PC大火游戏移植!...
  3. 面对系统的稳定性、我们如何做好系统稳定性建设?
  4. java sessionid长度_设置TOMCAT SESSIONID 字符长度和生成算法
  5. python模拟百度搜索点击链接_python采集百度搜索结果带有特定URL的链接代码实例...
  6. vs 下如何调试js
  7. OpenHarmony3.0 编译烧录
  8. DevEco Studio的下载
  9. vimpython配色_超漂亮 vim 配置:space-vim
  10. linux文件夹做链接,linux为什么不能给目录做硬链接