pytorch求hessian

打印 上一主题 下一主题

主题 1899|帖子 1899|积分 5697

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
起首有个
网络界说

随意界说了,根据自己的情况
  1. class ANN(nn.Module):
  2.     def __init__(self):
  3.         super(ANN, self).__init__()
  4.         self.fc1 = nn.Linear(10000, 1)
  5.         # self.fc1.bias.data.fill_(0)
  6.         
  7.     def forward(self, data):
  8.         x = self.fc1(data)
  9.         return x
复制代码
求hessian

autograd这个方法求梯度的时候分子是scalar ,分母是vector的时候,也即scalar对vector求导,得到的梯度向量和vector一样,而对于vector对vector求导,autograd没法求,只能求scalar对vector求导,以是需要循环。
  1. def getHessian(grads, model, loss_fn, dat, tar ,device):
  2.     loss = loss_fn(model(dat), tar)
  3.     grads_fn = torch.autograd.grad(loss, model.parameters(), retain_graph=True, create_graph=True) # 记录一阶梯度的grad_fn
  4.        
  5.         # 这部分是更新一阶梯度的值,因为其实我要计算的一阶梯度的值是grads
  6.     for source, target in zip(grads, grads_fn):
  7.         target.data.copy_(source)
  8.     hessian_params = []
  9.     #第k个梯度
  10.     for k in range(len(grads_fn)):
  11.         # 第i个参数
  12.         for param in model.parameters():
  13.             hess_params = []
  14.             # 第k个梯度的地i行参数
  15.             for i in range(grads_fn[k].size(0)):
  16.                 # 判断是w还是b
  17.                 if len(grads_fn[k].size()) == 2:
  18.                     # w
  19.                     for j in range(grads_fn[k].size(1)):  
  20.                         hess = torch.autograd.grad(grads_fn[k][i][j], param, retain_graph=True, allow_unused= True)
  21.                         hess_params.append(hess[0].cpu().detach().numpy() if hess[0] is not None else None)
  22.                 else:
  23.                     # b
  24.                     hess = torch.autograd.grad(grads_fn[k][i], param, retain_graph=True, allow_unused=True)
  25.                     hess_params.append(hess[0].cpu().detach().numpy() if hess[0] is not None else None)
  26.             hessian_params.append(np.array(hess_params))
  27.     return hessian_params
复制代码
关于backward和autograd

autograd只计算梯度不反向传播更新model的参数,由于这部分是torch中的优化器举行的,backward()也计算梯度,但获得具体一门路度信息需要用这个命令
   grad_list = [p.grad.clone() for p in net.parameters()]
  而这样得到的一门路度是不含grad_fn的,再举行求导的时候报错,虽然我也尝试loss.backward(retain_graph=True)用了这里的参数,但仍然无法解决问题,以是照旧用了autograd。但在模型更新的时候两者利用并不冲突
  1. net = ANN()
  2. opt = optim.SGD(net.parameters(), lr=1e-4)
  3. net.load_state_dict(model_state_dict)
  4. net.to(device)
  5. opt.load_state_dict(optimizer_state_dict)
  6. opt.zero_grad()
  7. pred = net(inputs)
  8. loss = loss_fn(pred, targets)
  9. grads = torch.autograd.grad(loss, net.parameters(), retain_graph=True, create_graph=True) # 计算一阶梯度
  10. loss.backward(retain_graph=True)
  11. opt.step()
  12.   
  13.   ·········
  14.   ······
  15.   #之后进行hessian矩阵的计算就可以
复制代码
参考

[1] 参考这个博客举行pytorch 求hessian
[2] 【矩阵的导数运算】标量向量方程对向量求导_分母布局_分子布局 此系列三个视频
[3] 常用矩阵微分公式_老子今晚不加班的博客-CSDN博客 这里提到的链接,内里也有提到[4]的链接
[4] Matrix calculus - Wikipedia这内里总结的很好

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

花瓣小跑

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表