美文网首页
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