共轭梯度法已经在前文中给出介绍:

python版本的“共轭梯度法”算法代码

共轭梯度法用来求解方程A*x=b,且A为正定矩阵。

在机器学习领域很多优化模型的求解最终可以写为A*x=b的形式,且A为正定矩阵或A为近似矩阵。在凸优化问题中A为正定矩阵是比较好满足的,在神经网络这类非线性问题中一般常用近似的技术方法来获得近似正定矩阵的A,相关见:https://www.zhihu.com/question/268719846/answer/351360155

而很多时候A*x=b中的A为Hession矩阵,即函数 f 对向量 w 的二次求导,如果w的size比较大,比如为1000000,那么这个Hession矩阵A的维度为1000000*1000000,然而这个大小的A矩阵是难以存储在内存中的。但是通过对共轭梯度法具体步骤的了解可以知道,在共轭梯度法的具体求解过程中我们其实并不是直接需要这个矩阵A进行参与计算的,我们需要直接参与计算的是A*p,由于A为Hession矩阵,因此我们有两种近似的方法来计算A*p,一种叫做“Pearlmutter trick”,一种叫做“有限差分法”。

利用“Pearlmutter trick”或“有限差分法”  近似的共轭梯度法又被称作Hession-free的共轭梯度法。

=======================================

使用共轭梯度法时,如果系数矩阵为Hessian矩阵,那么我们可以使用Pearlmutter trick技术或“有限差分法”来减少计算过程中的内存消耗,加速计算。

使用Pearlmutter trick和“有限差分法”的共轭梯度解法可以参考论文:

Fast Exact Multiplication by the Hessian

论文地址:

https://www.bcl.hamilton.ie/~barak/papers/nc-hessian.pdf

由于原论文中内容较多,所以我们介绍Pearlmutter trick技术和“有限差分法”的共轭梯度解法建议看的资料为其他网文blog:

https://justindomke.wordpress.com/2009/01/17/hessian-vector-products/

=======================================

 

1. 利用Pearlmutter trick的共轭梯度法

H(x)*p = ∂(g(x)*p)/∂x

=======================================

 
 
 

2. 利用有限差分法的共轭梯度法

 
 

依照上面内容解释一下:

Hession 矩阵 H(x) 为 f(x) 的二阶导数矩阵,因此有:

我们可以将  g(x)  按照泰勒公式展开为一阶导形式:

v 为一个向量vector,根据上面的公式我们可以得到:

其中 γ 为标量系数,该系数极小,因此γv可以看做为Δx

因此我们可以得到下面形式的公式:

=======================================

 

3. Pearlmutter trick技术和“有限差分法”的共轭梯度解法的 H(x)*p部分代码:

因为 H(x) 必然为正定对称矩阵,因此我们对  H(x) * y = b 形式的求解式可以使用共轭梯度法,而共轭梯度法在计算过程中需要重复的计算  H(x)*p, 其中 p 为计算过程中的迭代向量,p是在迭代过程中不断变化的,而H(x) 是系数矩阵在迭代过程中是不变的。

Pearlmutter trick 这个技术给出的是近似解,这里知道这个技术即可,实际感觉好像用处也不多,有可能是自己理解的不深。关于H(x)*b与共轭梯度的结合代码这里就省略掉了。

import torch

# 计算目标为: H*b,   H为函数s关于变量w的hessian矩阵
# 变量w
w = torch.randn(4, requires_grad=True) # 关于变量w的函数s
data = torch.randn(1000*4).reshape((-1, 4))
label = torch.randn(1000)
s = torch.mean( torch.square(label - torch.matmul(data, w)) ) # 计算目标中的b
b = torch.randn(4) # s对w的一阶导
first_grad = torch.autograd.grad(s, w, create_graph=True)[0] # 使用标准公式计算 H*b
second_grad = []
for grad in first_grad:
second_grad.append(torch.autograd.grad(grad, w, retain_graph=True)[0][None, :])
H = torch.concatenate(second_grad, axis=0)
print("Hessian method:")
print(torch.matmul(H, b)) # 在目标函数s进行一阶导后点乘向量b, 然后再对w进行一次求导, 也就是 dot(first_grad, b)后再次求导
# 这样计算可以减少内存占用,因为该种计算方式不会在内存中对整个hessian矩阵进行展开
# 如果要重复计算 H*b,而b又每次迭代都变化的情况,此种方式的缺点是每次都需要再次求导,但是总计算量应该变化不大
tmp = torch.dot(first_grad, b)
print(torch.autograd.grad(tmp, w)[0]) # paper, Pearlmutter trick, 没太感觉出优势, 或许理解的不对
r = 0.0001
new_w = w+r*b
new_s = torch.mean( torch.square(label - torch.matmul(data, new_w)) ) new_first_grad = torch.autograd.grad(new_s, w)[0]
print( (new_first_grad - first_grad)/r )

注意:

这个代码一共输出三行,第一行是真实的 H(x)*b ,第二行是 Pearlmutter trick 技术计算的 H(x)*b,第三行是有限差分法计算的 H(x)*b 。

系数矩阵为Hessian矩阵时使用“Pearlmutter trick”或“有限差分法”近似的共轭梯度解法 —— Hession-free的共轭梯度法的更多相关文章

  1. Hessian矩阵【转】

    http://blog.sina.com.cn/s/blog_7e1ecaf30100wgfw.html 在数学中,海塞矩阵是一个自变量为向量的实值函数的二阶偏导数组成的方块矩阵,一元函数就是二阶导, ...

  2. Hessian矩阵与多元函数极值

    Hessian矩阵与多元函数极值 海塞矩阵(Hessian Matrix),又译作海森矩阵,是一个多元函数的二阶偏导数构成的方阵.虽然它是一个具有悠久历史的数学成果.可是在机器学习和图像处理(比如SI ...

  3. 三维重建面试4:Jacobian矩阵和Hessian矩阵

    在使用BA平差之前,对每一个观测方程,得到一个代价函数.对多个路标,会产生一个多个代价函数的和的形式,对这个和进行最小二乘法进行求解,使用优化方法.相当于同时对相机位姿和路标进行调整,这就是所谓的BA ...

  4. 【机器学习】梯度、Hessian矩阵、平面方程的法线以及函数导数的含义

    想必单独论及" 梯度.Hessian矩阵.平面方程的法线以及函数导数"等四个基本概念的时候,绝大部分人都能够很容易地谈个一二三,基本没有问题. 其实在应用的时候,这几个概念经常被混 ...

  5. 梯度、Hessian矩阵、平面方程的法线以及函数导数的含义

    本文转载自: Xianling Mao的专栏 =========================================================================== 想 ...

  6. 梯度vs Jacobian矩阵vs Hessian矩阵

    梯度向量 定义: 目标函数f为单变量,是关于自变量向量x=(x1,x2,-,xn)T的函数, 单变量函数f对向量x求梯度,结果为一个与向量x同维度的向量,称之为梯度向量: 1. Jacobian 在向 ...

  7. C#处理医学图像(二):基于Hessian矩阵的医学图像增强与窗宽窗位

    根据本系列教程文章上一篇说到,在完成C++和Opencv对Hessian矩阵滤波算法的实现和封装后, 再由C#调用C++ 的DLL,(参考:C#处理医学图像(一):基于Hessian矩阵的血管肺纹理骨 ...

  8. Jacobian矩阵和Hessian矩阵

    1.Jacobian矩阵 在矩阵论中,Jacobian矩阵是一阶偏导矩阵,其行列式称为Jacobian行列式.假设 函数 $f:R^n \to R^m$, 输入是向量 $x \in R^n$ ,输出为 ...

  9. Hessian矩阵

    http://baike.baidu.com/link?url=o1ts6Eirjn5mHQCZUHGykiI8tDIdtHHOe6IDXagtcvF9ncOfdDOzT8tmFj41_DEsiUCr ...

  10. Jacobian矩阵、Hessian矩阵和Newton's method

    在寻找极大极小值的过程中,有一个经典的算法叫做Newton's method,在学习Newton's method的过程中,会引入两个矩阵,使得理解的难度增大,下面就对这个问题进行描述. 1, Jac ...

随机推荐

  1. 社会工程学——进行IP追踪

    如果目标对象有一个公开的邮箱,可以往这个邮箱地址发试探性的Email,然后看看该邮件是否有[回信],从而了解对象是否在线.(注:这招是社会工程学的基本伎俩) 说一个稍微高级点的邮件技巧--[不依赖回信 ...

  2. 设备树DTS 学习: 4-uboot 传递 dtb 给 内核

    背景 得到 dtb 文件以后,我们需要想办法下载到 板子中,并给 Linux 内核使用. (高级版本的 uboot也有了 自己使用设备树支持,我们这里不讨论 uboot 使用的设备树) Linux 内 ...

  3. Ubuntu 22.04单机部署K3s

    安装docker 从docker官网获取最新的一键安装脚本,安装docker运行环境 curl -fsSL https://get.docker.com -o get-docker.sh sudo s ...

  4. jsp---------------------复选框,全选按钮

    js部分:注意:<script type="text/javascript" ></script>内不能有其他内容,否则会无效,若有则另起一对<scr ...

  5. win10 gvim

    前言 现有的vscode太过于繁重,notepad++也不理想,顿来心思,想在win10配置一个gvim环境. 正文 安装gvim,从releases中找一个x64的.exe下载安装即可,安装完毕,把 ...

  6. Python获得操作日志的最后几行记录

    该方法一般用于获得操作日志的最后几行记录 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 f = open('seek.txt', 'rb') 4 ...

  7. 全网最适合入门的面向对象编程教程:14 类和对象的 Python 实现-类的静态方法和类方法,你分得清吗?

    全网最适合入门的面向对象编程教程:14 类和对象的 Python 实现-类的静态方法和类方法,你分得清吗? 摘要: 本文主要介绍了Python中类和对象中的类方法和静态方法,以及类方法和静态方法的定义 ...

  8. [oeasy]python0111_字型码_字符字型编码_点阵字库_ascii演化

    编码进化 回忆上次内容 上次回顾了 早期的英文字符点阵 最小的 3*5 通用的 5*7   点阵字库逐渐规范化 ​     添加图片注释,不超过 140 字(可选)     这些点阵字符的字型 究竟是 ...

  9. [oeasy]python0037_电传打字机_打印头_print_head_carriage_词源

    换行回车 回忆上次内容 上次我们 diy了 自己的小动物 还可以 让小动物 变色.报时 还可以 说些话 这很亚文化 很酷炫的亚文化 不是吗? 回忆一下 最开始 研究报时 的 时候 回到 本行行头 的 ...

  10. MViTv2:Facebook出品,进一步优化的多尺度ViT | CVPR 2022

    论文将Multiscale Vision Transformers (MViTv2) 作为图像和视频分类以及对象检测的统一架构进行研究,结合分解的相对位置编码和残差池化连接提出了MViT的改进版本 来 ...