本文主要是介绍pytorch实现straight-through estimator(STE),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
现在深度学习中一般我们学习的参数都是连续的,因为这样在反向传播的时候才可以对梯度进行更新。但是有的时候我们也会遇到参数是离>散的情况,这样就没有办法进行反向传播了,比如二值神经网络。本文中讲解了如何用pytorch对二值化的参数进行梯度更新的straight-through estimator算法。
Question:
STE核心的思想就是我们的参数初始化的时候就是float这样的连续值,当我们forward的时候就将原来的连续的参数映射到{-1, 1}带入到网络进行计算,这样就可以计算网络的输出。然后backward的时候直接对原来float的参数进行更新,而不是对二值化的参数更新。这样可以完成对整个网络的更新了。
首先我们对上面问题进行一下数学的讲解。
Example:
首先我们验证一下使用torch.sign会是参数的梯度基本上都是0:
>>> input = torch.randn(4, requires_grad = True)
>>> output = torch.sign(input)
>>> loss = output.mean()
>>> loss.backward()
>>> input
tensor([-0.8673, -0.0299, -1.1434, -0.6172], requires_grad=True)
>>> input.grad
tensor([0., 0., 0., 0.])
我们需要重写sign这个函数,就好像写一个激活函数一样。
import torchclass LBSign(torch.autograd.Function):@staticmethoddef forward(ctx, input):return torch.sign(input)@staticmethoddef backward(ctx, grad_output):return grad_output.clamp_(-1, 1)
import torch
from LBSign import LBSignif __name__ == '__main__':sign = LBSign.applyparams = torch.randn(4, requires_grad = True) output = sign(params)loss = output.mean()loss.backward()
测试梯度:
>>> params
tensor([-0.9143, 0.8993, -1.1235, -0.7928], requires_grad=True)
>>> params.grad
tensor([0.2500, 0.2500, 0.2500, 0.2500])
这篇关于pytorch实现straight-through estimator(STE)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!