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')