zoukankan      html  css  js  c++  java
  • 动手学深度学习_2.2_autograd

    Tensor

    import torch
    
    x = torch.ones(2, 2, requires_grad=True)  # 将其属性.requires_grad设置为True,它将开始追踪(track)在其上的所有操作。完成计算后,可以调用.backward()来完成所有梯度计算
    print(x)
    print(x.grad_fn)  # 每个Tensor都有一个.grad_fn属性,该属性即创建该Tensor的Function(除非用户创建的Tensors时设置了grad_fn=None)

    # tensor([[1., 1.],
    #        [1., 1.]], requires_grad=True)
    # None 
    y = x + 2
    print(y)
    print(y.grad_fn)
    
    # tensor([[3., 3.],
    #         [3., 3.]], grad_fn=<AddBackward0>)
    # <AddBackward0 object at 0x7fecef6f5320>

    attension: x是直接创建的,所以他没有grad_fn,而y通过一个加法操作创建的,所以它有一个的grad_fn

    # x这种直接创建的称为叶⼦节点,叶⼦节点对应的 grad_fn 是 None 
    print(x.is_leaf, y.is_leaf) 
    
    # True False
    z = y * y * 3
    out = z.mean()
    print(z, out)
    
    # tensor([[27., 27.],
    #         [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
    # 通过.requires_grad_()来用in-place的方式改变requires_grad属性
    a = torch.randn(2, 2)  # 缺失情况下默认requires_grad=False
    a = ((a * 3) / (a - 1))
    print(a.requires_grad)
    
    a.requires_grad_(True)
    print(a.requires_grad)
    
    b = (a * a).sum()
    print(b.grad_fn)
    
    # False
    # True
    # <SumBackward0 object at 0x7fecef6d17b8>

    梯度

    # 因为out是一个标量,所以调用backward()时不需要指定求导变量
    out.backward()  # 等价于out.backward(torch.tensor(1.))
    print(x.grad)
    
    # tensor([[4.5000, 4.5000],
    #         [4.5000, 4.5000]])
    # 再来一次反向传播,注意 grad 是累加的
    out2 = x.sum()
    out2.backward()
    print(x.grad)
    
    out3 = x.sum()
    x.grad.data.zero_()
    out3.backward()
    print(x.grad)
    
    # tensor([[5.5000, 5.5000],
    #         [5.5000, 5.5000]])
    # tensor([[1., 1.],
    #         [1., 1.]])
    # y.backward(w) 求的不是 y 对 x 的导数,而是 l = torch.sum(y*w) 对 x 的导数。
    x = torch.tensor([1.0, 2.0, 3.0, 4.0], requires_grad=True)
    y = 2 * x
    z = y.view(2, 2)
    print(z)
    
    # tensor([[2., 4.],
    #         [6., 8.]], grad_fn=<ViewBackward>)

    现在y不是一个标量,所以在调用backward时需要传入一个和y同行的权重向量进行甲醛求和得到一个标量

    v = torch.tensor([[1.0, 0.1], [0.01, 0.001]], dtype=torch.float)
    z.backward(v)
    print(x.grad)
    
    # tensor([2.0000, 0.2000, 0.0200, 0.0020])
    # 中断梯度追踪
    x = torch.tensor(1.0, requires_grad=True)
    y1 = x ** 2
    with torch.no_grad():  # 与y2有关的梯度是不会回传的,只有与y1有关的梯度才会回传
        y2 = x ** 3
    y3 = y1 + y2
    
    print(x, x.requires_grad)
    print(y1, y1.requires_grad)
    print(y2, y2.requires_grad)  # False,所以不能调用y2.backward()
    print(y3, y3.requires_grad)
    
    
    # tensor(1., requires_grad=True) True
    # tensor(1., grad_fn=<PowBackward0>) True
    # tensor(1.) False
    # tensor(2., grad_fn=<AddBackward0>) True
    y3.backward()
    print(x.grad)
    
    # tensor(2.)

    想修改tensor的数值,但又不希望被autograd记录(即不影响反向传播),那么可对tensor.data操作

    x = torch.ones(1, requires_grad=True)
    
    print(x.data)
    print(x.data.requires_grad)
    
    y = 2 * x
    x.data *= 100
    
    y.backward()
    print(x)
    print(x.grad)
    
    # tensor([1.])
    # False
    # tensor([100.], requires_grad=True)
    # tensor([2.])
  • 相关阅读:
    论文笔记4
    论文笔记3
    论文笔记2
    论文笔记1
    论文笔记
    AFG与AWG的比较
    Linux下“有线线缆被拔出”问题的解决
    python生成excel格式座位表
    PythonTip--一马当先--bfs
    python pygame--倒计时
  • 原文地址:https://www.cnblogs.com/harbin-ho/p/11962014.html
Copyright © 2011-2022 走看看