• pytorch函数zero_grad(),step()作用


    pytorch函数zero_grad(),step()作用

    假定现在有损失函数

    \[\begin{equation*} z=x^2+y^2 \end{equation*} \]

    先用手写梯度下降算法求该损失函数的极小值.这只是一个例子,其实能直接观察出来在(0,0)邻域内的极小值是0.但是为
    了说明问题,还是要假装不知道极小值,手写梯度下降算法来算.

    # coding: utf-8
    
    
    def f_value(x, y):
        return x * x + y * y
    
    
    def grad(x, y):
        return 2 * x, 2 * y
    
    
    if __name__ == '__main__':
        x = 5
        y = 10
        rate = 0.1
        for i in range(10):
            grad_value = grad(x, y)
            print("x={:.4f},y={:.4f},value={:.4f}".format(x, y, f_value(x, y)))
            print("x.grad={:.4f},y.grad={:.4f}".format(grad_value[0], grad_value[1]))
            x -= grad_value[0] * rate
            y -= grad_value[1] * rate
    
    

    若不熟悉这个代码原理,可以查阅参考资料.这就是一个最简单的梯度下降算法的实现.中间打印了梯度以及损失
    函数的值.运行结果如下:

    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=4.0000,y=8.0000,value=80.0000
    x.grad=8.0000,y.grad=16.0000
    x=3.2000,y=6.4000,value=51.2000
    x.grad=6.4000,y.grad=12.8000
    x=2.5600,y=5.1200,value=32.7680
    x.grad=5.1200,y.grad=10.2400
    x=2.0480,y=4.0960,value=20.9715
    x.grad=4.0960,y.grad=8.1920
    x=1.6384,y=3.2768,value=13.4218
    x.grad=3.2768,y.grad=6.5536
    x=1.3107,y=2.6214,value=8.5899
    x.grad=2.6214,y.grad=5.2429
    x=1.0486,y=2.0972,value=5.4976
    x.grad=2.0972,y.grad=4.1943
    x=0.8389,y=1.6777,value=3.5184
    x.grad=1.6777,y.grad=3.3554
    x=0.6711,y=1.3422,value=2.2518
    x.grad=1.3422,y.grad=2.6844
    

    下面代码是用pytorch实现

    # coding: utf-8
    import torch
    import torch.optim as optim
    
    
    def run(x, y):
        x = torch.tensor([x], requires_grad=True)
        y = torch.tensor([y], requires_grad=True)
        optimizer = optim.SGD([x, y], lr=0.1)
        for i in range(10):
            optimizer.zero_grad()
            f_value = x * x + y * y
            print("x={:.4f},y={:.4f},value={:.4f}".format(x.item(), y.item(), f_value.item()))
            f_value.backward()
            print("x.grad={:.4f},y.grad={:.4f}".format(x.grad.item(), y.grad.item()))
            optimizer.step()
    
    
    if __name__ == '__main__':
        run(5.0, 10.0)
    

    2个代码的运行结果一样.第2段代码pytorch的backward()函数帮我们求了梯度.不用再手算.要注意2点.

    1. optimizer.zero_grad()函数有什么用?
      不讲什么高深的理论和猜测.直接把optimizer.zero_grad()注释了再运行.得到如下结果:
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=4.0000,y=8.0000,value=80.0000
    x.grad=18.0000,y.grad=36.0000
    x=2.2000,y=4.4000,value=24.2000
    x.grad=22.4000,y.grad=44.8000
    x=-0.0400,y=-0.0800,value=0.0080
    x.grad=22.3200,y.grad=44.6400
    x=-2.2720,y=-4.5440,value=25.8099
    x.grad=17.7760,y.grad=35.5520
    x=-4.0496,y=-8.0992,value=81.9963
    x.grad=9.6768,y.grad=19.3536
    x=-5.0173,y=-10.0346,value=125.8655
    x.grad=-0.3578,y.grad=-0.7155
    x=-4.9815,y=-9.9630,value=124.0769
    x.grad=-10.3208,y.grad=-20.6415
    x=-3.9494,y=-7.8989,value=77.9899
    x.grad=-18.2196,y.grad=-36.4392
    x=-2.1275,y=-4.2549,value=22.6305
    x.grad=-22.4746,y.grad=-44.9491
    

    对比有optimizer.zero_grad()与没有optimizer.zero_grad()的结果,可以发现,如果不执行optimizer.zero_grad函数.
    每次求梯度的值是当前梯度再加上之前的梯度.pytorch为什么要这样设计api?梯度相加有什么实际使用场景?真没有遇到过.但目前可以
    得到的结论是执行optimizer.zero_grad()求得的梯度是当前梯度,不执行optimizer.zero_grad()求得的梯度是当前梯度加上之
    前的梯度.
    2. optimizer.step()函数有什么用?
    还按之前的思路,直接把optimizer.step()注释了,再运行代码,得到如下结果:

    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    x=5.0000,y=10.0000,value=125.0000
    x.grad=10.0000,y.grad=20.0000
    

    这就很清楚了,不执行optimizer.step()梯度没有变,也就是不会执行反向传播算法,损失函数也不会变.

    参考资料

    深度学习初级入门基础教程

  • 相关阅读:
    iView
    JS
    JS
    JS
    Java
    Java
    Java
    Java
    Java
    Java
  • 原文地址:https://www.cnblogs.com/zhouyang209117/p/16048331.html
Copyright © 2020-2023  润新知