美文网首页
pytorch官方教程

pytorch官方教程

作者: 云彩修建站站长 | 来源:发表于2020-02-01 10:28 被阅读0次

疑问

  1. 官方说pytorch的高级功能:GPU加速的张量计算;自动求导系统(反向求导技术)。其实是相对于普通CPU网络说的,对于深度网络来说,这些东西可以忽略。
  2. pytorch是动态图,可以任意改变网络的行为,而且速度快。动态图和静态图有什么区别还是不清楚
    补充:1. 在预测的阶段,把output = output[:, -1, :].squeeze(dim=1)改为了output = output[:, -1, :].squeeze(),结果完全一致。
  3. 在autograd一节中,介绍了标量函数的求导方式,但是对于向量形式的求导,目前还不清楚如何设置求导参数如何设置。

记录

1. 什么是PyTorch

  1. torch是和Numpy类似的科学计算包,但是因为是小众语言Lua写的,所以不太流行。Pytorch是在torch基础上做的工作,然后最上层使用python封装了,所以叫pytroch。因此,pytorch可以作为numpy的替代品,而且支持GPU加速。同时,它也支持深度学习。当然,我们更重视后者。
  2. pytorch最核心的是autograd包,它为张量的所有操作提供了自动求导机制。
  3. Module里面定义的是各种layers,都包含可学习的参数;forword()函数定义的是整个网络完整的结构。

2. features相关

  1. 0.4版本之前Tensor是包装在Variable里面进行,

pytroch api

torch

  • 创建tensor
  • tensor的dtype

torch.randn(shape) 产生一个shape形状的tensor,其中的值是正太分布。

pytorch 60min入门

1. pytorch入门

创建tensor
import torch
torch.empty(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False)
torch.rand(5, 3)
x = torch.zeros(5, 3, dtype=torch.long)
x = torch.randn(*size) # randn指的是随机产生正态分布的数据,均值为0,方差为1
x = torch.tensor([5.5, 3]) # 会根据入参自动推断,如果是[1,2]则,dtype是torch.int64;正常dtype是torch.float32
x = x.new_ones(5, 3, dtype=torch.double)   
x = torch.randn_like(x, dtype=torch.float)   

里面的requires_grad参数默认都是False,在网络中,只有parameters是需要grad的。
tensor.tensor(input)会根据input的数据类型,来判断输出的类型;tensor.Tensor()其实是tensor.FloatTensor(),底层调用的是tensor.tensor()

tensor自带方法
x = torch.tensor([1,2])
x.size() # 返回torch.Size([2])
x.numpy() # 获取numpy,底层numpy和tensor共享数据
## 可以自带一些操作
x.squeeze()
x.view()
x.mm(y)  # 矩阵的乘法
operations

同一个操作有很多种方式。

  • torch.add(x, y)
  • x.add_(y) # 把y加到x上面
  • x.view() # 相当于tf的reshape,不过第一个参数还是*args 可变参数

pytorch接口
可以看出torch和numpy的接口基本一致,而且两者共享底部数据

import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)
  • torch.max(input, dim, keepdim=False, out=None) -> (Tensor, LongTensor) # 获取最大值
  • torch.argmax()
  • torch.clamp(input, min, max, out=None) 将input向量夹紧到[min, max]中
>>> x = torch.zeros(2, 1, 2, 1, 2)
>>> x.size()
torch.Size([2, 1, 2, 1, 2])
>>> y = torch.squeeze(x)
>>> y.size()
torch.Size([2, 2, 2])
>>> y = torch.squeeze(x, 0)
>>> y.size()
torch.Size([2, 1, 2, 1, 2])
>>> y = torch.squeeze(x, 1)
>>> y.size()
torch.Size([2, 2, 1, 2])
cuda tensor

不知道不同device上的数据相加,是如何处理的

if torch.cuda.is_available():
    device = torch.device("cuda")          # a CUDA device object,不进行编译,有没有cuda也可以执行,但是tensor.to(device)会失败
    y = torch.ones_like(x, device=device)  # directly create a tensor on GPU
    x = x.to(device)                       # or just use strings ``.to("cuda")``
    z = x + y
    print(z)
    print(z.to("cpu", torch.double))

输出如下:
tensor([0.5480], device='cuda:0')
tensor([0.5480], dtype=torch.float64)

2. AUTOGRAD

构建可求导tensor

torch.tensor(requires_grad=True)

创建了tensor,之后所有的operation产生的tensor,都会自带一个Function。
对tensor求grad,只需要调用out.backword(grad_variables)就可以了,但是grad_variables参数非常古怪,现在也不知道设置多少才合适?

detach求grad

两种方案:

  1. with torch.no_grad():
  2. x.detach()
  3. requires_grad_(False)

3. NEURAL NETWORKS

如何训练一个神经网络,下面的流程可以说是很清晰了:

  1. Define the neural network that has some learnable parameters (or weights)
    第一种方式就是定义一个类,继承nn.Module;另一种就是直接使用nn.Sequential()。直观感受,第一种方式定制化能力更强一些。
    第一种方式:
class Net(nn.Module):
  def __init__(self):
    # define layers
  
  def forword(input):
    # define network

第二种方式:

model = nn.Sequential(
    nn.Linear(D_in, H),
    nn.ReLU(),
    nn.Linear(H, D_out),
)
  1. Iterate over a dataset of inputs
  2. Process input through the network
net = Net()
output = net(input)
  1. Compute the loss (how far is the output from being correct)
    所有的loss也都存放在了torch.nn包里面,接收一个(output, target)pair,产生一个loss tensor
criterion = nn.MSELoss()
loss = criterion(output, target)
  1. Propagate gradients back into the network’s parameters
loss.backward()
  1. Update the weights of the network, typically using a simple update rule: weight = weight - learning_rate * gradient
optimizer = optim.SGD(net.parameters(), lr=0.01)
optimizer.zero_grad()   # zero the gradient buffers
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()    # Does the update

tips

  • nn.Module. 神经网络模型,直接作为定义神经网络的父类。
  • torch.optim 这个包包含了所有的optim函数
  • net.parameters() 返回的是Parameter对象,如果想获取值,需要使用list(Parameters)

4. TRAINING A CLASSIFIER

前面定义网络,定义loss和optim的阶段省略了,只记录下面计算loss和更新参数的部分:

for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs; data is a list of [inputs, labels]
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

其中loss和optim的定义如下:

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

可以看出,loss不依赖参数;optim是参数以来的,它的目的是更新所有的parameter。

save model & load model

torch.save(net.state_dict(), PATH)

state_dict 是一个python的字典格式,以字典的格式存储,然后以字典的格式被加载,而且只加载key匹配的项

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

我们在加载的时候,可以只加载我们需要的层,不需要的层不加载。

https://www.jianshu.com/p/6287a2c85e57

predict

在进行predict的时候,需要把predict的代码放到with torch.no_grad():里面

training on GPU

不知道为什么,默认不是GPU,需要把两类数据送到目标device中:

  1. Net的parameters
  2. 数据集的data

优化器的基类

class torch.optim.Optimizer(params, defaults)
包含的方法:
1、load_state_dict(state_dict)
optimizer的状态。是一个调用state_dict()所返回的对象。和state_dict()配合使用,先保存吗, 再加载。
2、state_dict()
以dict返回optimizer的状态。和model的state_dict相似,一般在保存模型参数的时候可以把优化器的参数一起保存。
3、step(closure)
单步优化
4、zero_grad()
清空所有被优化过的Variable的梯度. 在写的时候也可以用model.zero_grad()

极好的例子

https://www.jianshu.com/p/d8926a2b9e76

optimizer.zero_grad() # 来清空model参数的grad
loss.backward() # 进行反向传播
optimizer.step() # 进行梯度更新

torch.nn与torch.nn.functional之间的区别和联系

所有需要参数的实现都是nn.Module(),torch.nn.Module的底层实现也是nn.functioncal。
有些nn的实现需要参数,比如 nn.functioncal的入参需要传入这些模型参数,让用户去定义会比较麻烦,所以构建了torch.nn.Module,在init里面构建了这些参数,就不用用户自己定义了。
同时有保留了nn.functional的接口,保留这种灵活性。
但是不需要参数的layer就可以直接使用nn.functional()
【但是也有例外,比如nn.Softmax() 这个明明没有参数,但是还是构建了Module】

1. Numpy

https://blog.csdn.net/u012300744/article/details/80423135
点乘:

  • m * n
  • np.multiply(m, n)

矩阵乘法:

  • np.matmul(b, a)
  • np.dot(a,a)
  • a.dot(a)

pytorch和tensorflow的区别

个人感觉,pytorch比tensorflow好用多了,优势如下:

  1. 包的定义非常清晰
  2. 动态图的方式,非常适合调试
  3. nn.Module 的定义非常好,相当于一个小的规范,模型定义更清晰
  4. 动态图编辑

相关文章

网友评论

      本文标题:pytorch官方教程

      本文链接:https://www.haomeiwen.com/subject/ybjjnctx.html