梯度裁剪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)