C/C++教程

梯度裁剪torch.nn.utils.clip_grad_norm_

本文主要是介绍梯度裁剪torch.nn.utils.clip_grad_norm_,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1. 作用

防止梯度爆炸,即设置一个梯度大小的上限,当梯度的范数大于上限时,将该参数的范数设置为上限。

补充:范数
最常用的是p-范数,若向量 x = [ x 1 , x 2 , ⋯   , x n ] T x=\left[x_{1}, x_{2}, \cdots, x_{n}\right]^{\mathrm{T}} x=[x1​,x2​,⋯,xn​]T,则p范数定义如下
∥ x ∥ p = ( ∣ x 1 ∣ p + ∣ x 2 ∣ p + ⋯ + ∣ x n ∣ p ) 1 p \|x\|_{p}=\left(\left|x_{1}\right|^{p}+\left|x_{2}\right|^{p}+\cdots+\left|x_{n}\right|^{p}\right)^{\frac{1}{p}} ∥x∥p​=(∣x1​∣p+∣x2​∣p+⋯+∣xn​∣p)p1​
L1范数: ∥ x ∥ 1 = ∣ x 1 ∣ + ∣ x 2 ∣ + … + ∣ x n ∣ \|x\| _1=\left|x_{1}\right|+\left|x_{2}\right|+\ldots+\left|x_{n}\right| ∥x∥1​=∣x1​∣+∣x2​∣+…+∣xn​∣
L2范数: ∥ x ∥ 2 = ( ∣ x 1 ∣ 2 + ∣ x 2 ∣ 2 + … + ∣ x n ∣ 2 ) 1 / 2 \|\mathrm{x}\| _2=\left(\left|\mathrm{x}_{1}\right|^{2}+\left|\mathrm{x}_{2}\right|^{2}+\ldots+\left|\mathrm{x}_{\mathrm{n}}\right|^{2}\right) ^{1 / 2} ∥x∥2​=(∣x1​∣2+∣x2​∣2+…+∣xn​∣2)1/2
无穷范数: ∥ x ∥ ∞ = max ⁡ ( ∣ x 1 ∣ , ∣ x 2 ∣ , … , ∣ x n ∣ ) \|\mathrm{x}\| _\infty=\max \left(\left|\mathrm{x}_{1}\right|,\left|\mathrm{x}_{2}\right|, \ldots, \quad\left|\mathrm{x}_{\mathrm{n}}\right|\right) ∥x∥∞​=max(∣x1​∣,∣x2​∣,…,∣xn​∣)
参考 如何通俗易懂地解释「范数」?

2. 使用

 torch.nn.utils.clipgrad_norm(parameters, max_norm, norm_type=2)

parameter 希望实施梯度裁剪的可迭代网络参数
max_norm 该组网络参数梯度的范数上限
norm_type 范数类型 [ 0, 1, 2…, inf ]

torch.nn.utils.clipgrad_norm()的使用应该在loss.backward()之后,optimizer.step()之前

3. 实验

loss, logits = model(input_ids=input_ids, mc_token_ids=mc_ids, labels=label)
loss.backward()
train_loss += loss.item()
for p in model.parameters():
    print(p.grad.norm())
    torch.nn.utils.clip_grad_norm_(p, 1)
    print(p.grad.norm())
optimizer.step()
optimizer.zero_grad()

执行一个循环后输出:

tensor(15.3762, device='cuda:1')
tensor(1.0000, device='cuda:1')

当范数小于1时输出

tensor(0.8803, device='cuda:1')
tensor(0.8803, device='cuda:1')
这篇关于梯度裁剪torch.nn.utils.clip_grad_norm_的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!