有限差法(Finite Difference)求梯度和Hessian Matrix(海森矩阵)的python实现

这篇具有很好参考价值的文章主要介绍了有限差法(Finite Difference)求梯度和Hessian Matrix(海森矩阵)的python实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数学参考

有限差方法求导,Finite Difference Approximations of Derivatives,是数值计算中常用的求导方法。数学上也比较简单易用。本文主要针对的是向量值函数,也就是 f ( x ) : R n → R f(x):\mathbb{R^n}\rightarrow \mathbb{R} f(x):RnR当然,普通的标量值函数是向量值函数的一种特例。

本文采用的数学参考是:有限差方法
参考的主要是Central Difference Approximations小节中的Second-order derivatives based on gradient calls的那个公式。

代码

用法

将下面代码中的Hessian矩阵一节中的Hessian函数直接复制到你的代码中,然后就可以按照用法示例使用。

特别要注意,eps的选择比较关键,直接决定了有限差方法的精度。建议大家根据函数参数的数量级动态的设置,例如某参数变化范围1-10,就可以设置为0.001;而某参数变化范围为0-0.0001,则可设置为0.000001,之类的。

用法示例

def func(x):
    x_0 = x[0]
    x_1 = x[1]
    return x_0**2 + x_1**2
hessian(func, [0,0], esp = [0.01, 0.01])

得到结果:

array([[2., 0.],
       [0., 2.]], dtype=float32)

函数主体

准备

本文的方法只需要numpy包,几乎可以说不需要任何包,而且不受到什么限制,只要满足输入格式就能求取,比所谓autogradnumdifftools好用的多。

梯度函数

为了求Hessian矩阵,本文采用的方法需要首先求取梯度。首先需要有一个函数func,示例的func如下:

def func(x, **args):
    x_0 = x[0]
    x_1 = x[1]
    return x_0**2 + x_1**2

该函数是一个 R 2 → R \mathbb{R^2}\rightarrow \mathbb{R} R2R的函数。将该函数输入进下面的函数grad_func_generator中之后,就可以返回梯度函数,支持在任何一点求取梯度。这里输入x应该是一个列表,是各个维度的输入。例如x = [0,0].

def grad_func_generator(func, eps = 0.00001):
    def gradient_func(point):
        n_var = len(point)
        gradient = np.zeros(n_var, np.float32)
        # nth gradient
        for i in range(n_var):
            # 初始化左点和右点,同时不改变原来的展开点
            left_point = point.copy()
            right_point = point.copy()
            left_point[i] = point[i] - eps
            right_point[i] = point[i] + eps
            gradient[i] = (func(right_point) - func(left_point))/(2*eps)
        return gradient
    return gradient_func

求取梯度:

grad_f = grad_func_generator(func) # 生成梯度函数
grad_f([1,1])

可以得到结果:

array([2., 2.], dtype=float32)

Hessian矩阵

利用已经实现的梯度函数,可以实现Hessian矩阵。

# -*- coding: utf-8 -*-
# @author: Dasheng Fan
# @email: fandasheng1999@163.com

def hessian(func, point = [0, 0], eps = [0.001, 0.001]):
    """
    Hessian matrix of func at expendung point.
    """
    n_var = len(point)
    def grad_func_generator(func):
        def gradient_func(point):
            gradient = np.zeros(n_var, np.float32)
            # nth gradient
            for i in range(n_var):
                # 初始化左点和右点,同时不改变原来的展开点
                left_point = point.copy()
                right_point = point.copy()
                left_point[i] = point[i] - eps[i]
                right_point[i] = point[i] + eps[i]
                gradient[i] = (func(right_point) - func(left_point))/(2*eps[i])
            return gradient
        return gradient_func

    grad_func = grad_func_generator(func)
    hessian_matrix = np.zeros((n_var, n_var), np.float32)
    for i in range(n_var):
        for j in range(n_var):
            # 第一项
            left_point_j = point.copy()
            right_point_j = point.copy()
            right_point_j[j] = point[j] + eps[j]
            left_point_j[j] = point[j] - eps[j]
            diff_i = (grad_func(right_point_j)[i] - grad_func(left_point_j)[i])/(4*eps[j])
            # 第二项
            left_point_i = point.copy()
            right_point_i = point.copy()
            right_point_i[i] = point[i] + eps[i]
            left_point_i[i] = point[i] - eps[i]
            diff_j = (grad_func(right_point_i)[j] - grad_func(left_point_i)[j])/(4*eps[i])

            hessian_matrix[i, j] = diff_i + diff_j

    return hessian_matrix

可以通过输入函数func和求取二阶导数的点x,就可以输出该点处的Hessian矩阵。

hessian(func, [0,0])

得到结果

array([[2., 0.],
       [0., 2.]], dtype=float32)

如果和numdifftools的结果对照,可以发现一样。但是numdifftools非常难用,总是报错,而且速度奇慢,如果需要循环中算,更是龟速。我们的程序只需要numpy包就能实现,非常方便好用,速度非常快。文章来源地址https://www.toymoban.com/news/detail-778492.html

到了这里,关于有限差法(Finite Difference)求梯度和Hessian Matrix(海森矩阵)的python实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Leetcode 3115. Maximum Prime Difference

    Leetcode 3115. Maximum Prime Difference 1. 解题思路 2. 代码实现 题目链接:3115. Maximum Prime Difference 这一题思路上非常的直接,就是找到数组当中所有的质数的位置,然后去首尾两个计算位置的距离即可。 因此,问题也就变成了一个判断任意一个数是不是素数的问题,这个就老生常谈

    2024年04月16日
    浏览(41)
  • Python实现视频运动目标检测——帧差法

    Python实现视频运动目标检测——帧差法 在许多场景中,我们需要对视频中的运动目标进行检测。而在这个过程中,帧差法是一种常用的方法。本文将详细阐述Python如何利用帧差法实现视频运动目标检测。 首先,我们需要导入OpenCV库,它是一个强大的计算机视觉库,可以用于

    2024年02月15日
    浏览(46)
  • (表征学习论文阅读)FINITE SCALAR QUANTIZATION: VQ-VAE MADE SIMPLE

    向量量化(Vector Quantization)或称为矢量量化最早在1984年由Gray提出,主要应用于数据压缩、检索领域,具体的阐述可以参考我写的另一篇关于VQ算法的文章。随着基于神经网络的离散表征学习模型的兴起,VQ技术也开始重新被重视。它在图像、音频等表征学习中体现出了优秀的

    2024年04月26日
    浏览(29)
  • 【OpenCV】“帧差法”实现移动物体的检测(车辆识别)

    目录 一、帧差法 1、概念 2、为什么帧差法可以检测运动的物体?  二、使用OpenCV配合帧差法实现车辆识别 1、加载视频 2、灰度处理+帧差计算 3、二值化 4、腐蚀 5、膨胀 6、框选出车辆 三、全部代码+实现效果 1、代码 2、车辆检测效果 四、帧差法存在不足之处         帧差

    2024年02月02日
    浏览(50)
  • ZYNQ图像处理项目——帧差法运动目标跟踪

    帧差法顾名思义就是对输入的前后两帧图像做差值,然后检测出两帧图像不同的地方,并且可以实时跟踪运动的目标轮廓。 本设计是基于ZYNQ7010和VIVADO2018.3实现的帧差法运动目标检测,针对运动目标检测算法在传统 PC端上实时性较差的问题,设计了一种基于 ZYNQ 硬件加速的运

    2024年02月07日
    浏览(81)
  • Difference Between [Checkpoints ] and [state_dict]

    在PyTorch中,checkpoints 和状态字典(state_dict)都是用于保存和加载模型参数的机制,但它们有略微不同的目的。 1. 状态字典 ( state_dict ): 状态字典是PyTorch提供的一个Python字典对象,将每个层的参数(权重和偏置)映射到其相应的PyTorch张量。 它表示模型参数的当前状态。 通过

    2024年01月25日
    浏览(39)
  • c++中set_difference这个函数的意义和用法

    今天正好碰到了这个函数,虽然大概可以猜出这个函数的作用,但是仍然期待一个通俗易懂的解释,网上搜索了一下,搜到百度百科,感觉没有抓住重点,虽然示例也勉强可以理解,但是总感觉讲究不够直观。 下图绿色部分就是这个函数的功能了。   于是,最终在Notion的帮

    2024年02月01日
    浏览(56)
  • 使用opencv结合帧差法和背景减法 检测场景异常情况

    帧差法是一种简单的背景减法技术,用于检测当前帧和背景帧之间的差异。以下是使用OpenCV实现帧差法的Python代码示例: 用于检测是否下雨,漏水等情况。 要截取摄像头的3秒时间并使用帧差法进行动态背景差异检测,你可以使用OpenCV库来完成这项任务。首先,你需要设置一

    2024年02月07日
    浏览(40)
  • leetcode - 2616. Minimize the Maximum Difference of Pairs

    You are given a 0-indexed integer array nums and an integer p. Find p pairs of indices of nums such that the maximum difference amongst all the pairs is minimized. Also, ensure no index appears more than once amongst the p pairs. Note that for a pair of elements at the index i and j, the difference of this pair is |nums[i] - nums[j]|, where |x| represents th

    2024年02月13日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包