美文网首页
2. Autograd tutorials in PyTorch

2. Autograd tutorials in PyTorch

作者: CurryCoder | 来源:发表于2019-02-26 10:40 被阅读0次
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @Date    : 2019-02-25 21:31:00
    # @Author  : cdl (1217096231@qq.com)
    # @Link    : https://github.com/cdlwhm1217096231/python3_spider
    # @Version : $Id$
    
    import torch
    import numpy as np
    import matplotlib.pyplot as plt
    
    # 自动求导机制
    """
    pytorch中所有的神经网络的核心是autograd包,autograd包为张量上的所有操作提供了自动求导功能。
    """
    
    # 一、张量Tensor
    """
    1.torch.Tensor是这个包的核心类,如果设置require_grad=True,那么将会追踪所有对于该张量的操作。当完成计算后通过调用
    backward(),自动计算所有的梯度,这个张量的所有梯度将会自动积累的grad属性上。
    2.要阻止张量跟踪历史记录,可以调用detach()方法将其与计算历史记录分离,并禁止跟踪它将来的计算记录。
    3.为了防止跟踪历史记录,可以将代码块包装在with torch.no_grad()中,在评估模型时特别有用,因为模型可能具有requires_grad=True的可训练参数,但我们不需要梯度计算。
    4.在自动梯度计算中还有另一个重要的类Function
    5.Tensor和Function互相连接并生成一个非循环图,它表示和存储了完整的计算历史。每个张量都有一个grad_fn属性,这个属性引用一个创建了Tensor的Functions(除非这个张量是用户手动创建的,即这个张量的grad_fn=None)
    6.如果需要计算导数,可以在Tensor上调用backward()。如果Tensor是一个标量(即是一个单一的数字),则不需要为backward()指定任何参数,但是如果它由更多的元素,需要指定一个gradient参数来匹配张量的形状。
    """
    # 注意:以前是将tensor包裹到Variable中提供自动梯度计算,Variable这个在0.4.1版本中已经被标注为过期了,现在可以直接使用Tensor
    print("Pytorch版本:", torch.__version__)
    
    # 创建一个张量并设置requires_grad=True
    x = torch.ones(2, 2, requires_grad=True)
    print("x: \n", x)
    # 对张量进行操作
    y = x + 2
    print("y: \n", y)  # 结果y被计算出来了,grad_fn已经被自动生成了
    print("y张量的属性: \n", y.grad_fn)
    
    z = 3 * y * y
    out = z.mean()
    print("z: \n", z)
    print("张量z的属性: \n", z.grad_fn)
    print("out: \n", out)
    print("张量out的属性: \n", out.grad_fn)
    
    # requires_grad_(...)可以改变现有张量的requires_grad的属性,如果没能指定的话,默认输入的是requires_grad=False
    a = torch.randn(2, 2)
    a = ((a * 3) / (a - 1))
    print("默认的requires_grad的属性值:", a.requires_grad)
    a.requires_grad_(True)  # 使用替换操作in place来设置requires_grad的属性值
    print("修改后的requires_grad值:", a.requires_grad)
    b = (a * a).sum()
    print(b.grad_fn)
    
    # 二. 梯度(gradient)
    """
    反向传播是因为out是一个标量,out.backward()等价与out.backward(torch.tensor(1))
    """
    out.backward()
    print("x在1处的梯度是: \n", x.grad)  # d(out)/dx
    
    # 更多的梯度操作
    x = torch.randn(3, requires_grad=True)
    y = x * 2
    while y.data.norm() < 1000:
        y = y * 2
    print("y =", y)
    
    gradient = torch.tensor([0.1, 1.0, 0.001], dtype=torch.float)
    y.backward(gradient)
    print(x.grad)
    
    # 如果requires_grad=True,但是又不希望进行autograd的计算,那么可以将变量包裹在with torch.no_grad()中:
    print(x.requires_grad)
    print((x ** 2).requires_grad)
    
    with torch.no_grad():
        print((x ** 2).requires_grad)
    print("--------------------------------------完美的分隔线-------------------------------")
    
    """
    1.深度学习的实质是反向传播求导数,在pytorch中的autograd模块则实现了这个功能。在Tensor上的所有操作,autograd都能为它自动计算微分,避免手动计算微分。
    2.从0.4版本开始,Variable正式合并入Tensor,Variable本来实现的自动微分功能,Tensor就能支持。还是可以使用
    Variable(Tensor),但这个操作其实什么都没做。
    3.要使得Tensor有自动求导的功能,需要将属性tensor.requires_grad=True
    """
    
    
    # 在创建张量时,通过设置requires_grad=True来告诉Pytorch需要对该张量进行自动的求导,pytorch会记录该张量的每一步操作历史并自动计算。
    
    x = torch.randn(5, 5, requires_grad=True)
    print("x: \n", x)
    
    y = torch.randn(5, 5, requires_grad=True)
    print("y:\n", y)
    
    z = torch.sum(x + y)
    print("z: \n", z)
    
    # 简单的自动求导
    z.backward()
    print("x和y的梯度是: \n", x.grad, "\n", y.grad)
    
    # 复杂的求导
    z = x ** 2 + y**3
    print(z)
    # 返回值不是一个scalar,所以需要输入一个大小相同的张量作为参数,这里我们用ones_like函数根据x生成一个张量
    z.backward(torch.ones_like(x))
    print(x.grad, '\n', y.grad)
    
    # 使用with torch.no_grad():禁止已经设置requires_grad=True的向量进行自动求导,这个方法在测试集上测试准确率的时候回经常用到!!!!
    with torch.no_grad():
        print((x + y * 2).requires_grad)
    
    

    相关文章

      网友评论

          本文标题:2. Autograd tutorials in PyTorch

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