何为梯度 grad
记录loss对参数的偏导,用于更新参数,模型训练的时候,默认为参数创建,可以使用tensor.requires_grad查询张量是否带梯度
1 | import torch |
grad有什么用
可以利用torch的自动求导特性,得到loss关于次参数的导数,并利用此导数进行参数更新
具体而言,模型的一个epoch有这么五步
如果模型的设计是,参数是每个
step更新,那每个step都有这么几步
向前传播,
forward,即使用模型,传入feature,得到模型输出pred1
pred = model(feature)
计算
loss,这里的loss_func为自己定义的函数,比如常见的L1 loss1
loss = loss_func(pred, target)
向后传播,
backward,即对模型各个参数计算对应的grad1
loss.backward()
更新模型参数,根据自己定义的优化器
optimizer策略,进行参数更新1
optimizer.step()
将模型所有参数的
grad重置为01
optimizer.zero_grad()
清空单个张量的grad
当张量被初始化时,是没有梯度,是不用清空的,此时grad为None
1 | import torch |
一旦基于此tensor的计算的值进行了backward,也就是依据计算图计算了各个参数的grad,此tensor附带的grad就不是None了
1 | import torch |
梯度在每次backward是不会被覆盖的,而是累计,所以需要手动清空,这里的清空是指将梯度设置为0;需要注意的是如果grad是None,是不能被清空的
1 | if tensor_demo.grad is not None: |
将grad 转为 feature importance
对feature添加grad,进行backward后,基于grad计算feature importance
读取模型参数,使用模型预测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import torch
model = DailyNet.load_from_checkpoint(
Path("epoch04.ckpt"),
)
# 如果模型中有dropout等层,需要进行处理,否则后续操作有随机性
model._gru_block._gru.dropout = 0.0
# 可以将参数的梯度去掉, 并不影响featuer的grad计算
# for param in model.parameters():
# param.detach_()
# NOTE 需要给feature添加grad
input_feature = input_feature.requires_grad_(True)
preds = model(input_feature).cpu()计算
loss,并backwardloss_func为自定义的损失函数,target为真实值1
2
3
4
5
6
7
8
9if input_feature.requires_grad:
if input_feature.grad is not None:
input_feature.grad.zero_()
else:
raise KeyError("input_feature requires grad")
loss = loss_func(preds, target)
loss.backward()根据
grad计算feature importance1
2grad = input_feature.grad
grad.abs().sum(axis=(0, 1)) / grad.abs().sum()