梯度裁剪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} ight]^{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} ight|^{p}+left|x_{2} ight|^{p}+cdots+left|x_{n} ight|^{p} ight)^{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} ight|+left|x_{2} ight|+ldots+left|x_{n} ight| ∥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} ight|^{2}+left|mathrm{x}_{2} ight|^{2}+ldots+left|mathrm{x}_{mathrm{n}} ight|^{2} ight) ^{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} ight|,left|mathrm{x}_{2} ight|, ldots, quadleft|mathrm{x}_{mathrm{n}} ight| ight) ∥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)
经验分享 程序员 微信小程序 职场和发展