在OpenAI Five论文中提到,“梯度在每个参数上被剪切到±5√v之间,其中v是梯度(未剪切的)二阶矩的运行估计值。”这是我希望在我的项目中实现的功能,但我既不确定理论上也不确定实践中该如何操作。
从维基百科我了解到,“二阶中心矩是方差。方差的正平方根是标准差[…]”。关于“运行估计”,我最好的猜测是它是指指数移动平均。网络的梯度可以按照这个评论中提到的方法获取。
据此,我假设√v是梯度标准差的指数运行平均值,可以通过以下方式计算:estimate = alpha * torch.std(list(param.grad for param in model.parameters())) + (1-alpha) * estimate
我的理论是否正确?有没有更好的方法?提前感谢。
编辑:在某用户的回答后修正了梯度的收集方式。
回答:
我认为你走在正确的道路上,我的猜测基本上与你相同,只是略有不同。
首先,什么是矩?
随机变量的第n阶矩定义为该变量的n次幂的期望值。更正式地说:
m — 矩,X — 随机变量
因此,第一阶矩是均值,第二阶矩是未中心化的方差(意味着我们在计算方差时不减去均值),直观上,通过其标准差相对于零的移动平均来剪切梯度是有意义的。
其次,正确的代码是什么?
list(network.parameters())
只给你参数,要获取每个参数的梯度,你需要[param.grad for param in network.parameters()]
鉴于我们已知的所有信息,正确的代码应该是(你可以尽可能尝试优化它):
grads_square = torch.FloatTensor([torch.square(param.grad) for param in network.parameters()])
estimate = alpha * torch.sqrt(torch.mean(grads_square)) + (1-alpha) * estimate