数值微分
基本原理
根据导数定义,当自变量有一个微小变化(h)(如(h = 0.000001))时,函数值的变化与自变量变化的比值可以近似表示函数在某点的导数。通过给出函数值以及自变量的差值,数值微分算法就能计算出导数值。
三种计算方式及截断误差
截断误差与步长(h)有关,一般来说,(h)越小,截断误差越小,近似程度越高。
误差分析
- 舍入误差:计算机系统中浮点数的运算存在舍入误差,它会随着(h)变小而逐渐增大。因为(h)越小时,计算过程中对小数位数的处理会更频繁,导致舍入误差累积。
- 综合影响:截断误差随(h)减小而减小,舍入误差随(h)减小而增大,二者共同作用使得数值微分的精度形成一个变化的函数,在某一特定的(h)值处达到最小值。
中心微分近似
为缓解截断误差提出了中心微分近似,它比单侧差分公式有更小的误差和更好的稳定性,公式为(f’(x) \approx \frac{f(x + h)-f(x - h)}{2h}),但它只能减少误差,无法解决舍入误差问题。
优缺点
- 优点:具有广泛的计算适用性,能适用于大部分表达式;对用户来说,求导过程是隐式的,不需要用户手动进行复杂的求导运算,使用起来较为方便;实现过程相对简单。
- 缺点:计算量较大,求解速度慢,因为每计算一个参数的导数,都需要重新进行计算;由于是数值逼近,会引入误差,结果可能不可靠、不稳定,难以获得准确的导数值。而且如果(h)选取不当,可能导致误差增大,甚至得到与正确结果符号相反的结果。同时还会引入截断误差和舍入误差,影响计算精度。
符号微分
基本原理与操作方式
- 符号微分利用链式求导规则,依据简单的求导规则(如对基本函数的求导规则、四则运算求导规则、复合函数求导规则等),对计算机程序中的表达式进行递归变换,以此来替代手动微分的过程。
- 例如,通过代数软件实现微分的相关公式,把公式的计算过程转化为微分过程,从而对用户提供的具有闭包(closed form)的数学表达式进行“自动微分”求解。具体步骤是先求出原始数学表达式的解析解,再将其转换为程序,最后通过程序计算出函数的梯度。
优势特点
- 精度较高:由于变换过程中不涉及具体的数值计算,仅在变换完成后的计算过程中可能存在舍入误差,从数学角度来看是严格等价的,所以能大大减小微分结果的误差,并且还可用于求解类似极值等较为复杂的数学问题。
- 简单易实现:按照既定的求导规则和递归变换方式,在操作上相对容易实现。
- 应用广泛:因其优点,被应用于 Mathematica、Maple、matlab、Maxima 等现代代数系统工具软件中。这些软件可以对符号表达式进行有效的处理和求导计算。
局限性
- 表达式膨胀问题:当表达式较为复杂时,符号微分对表达式进行严格展开和变换会导致所谓的表达式膨胀(expression swell)问题。例如在递归表达式的求导中,随着迭代次数的增加,符号微分的结果相比人工简化后的结果会复杂很多,表达式的规模不断增大,增加了计算和处理的难度。
- 形式限制:要求表达式必须是闭包(closed form)形式,即必须能写成完整的数学表达式,不能包含编程语言中的循环结构、条件结构等。因为只有这样才能将整个问题转化为一个纯数学符号问题进行处理,如果不满足这种形式要求,符号微分就无法适用 。
自动微分(AD)
自动微分是一种用于计算函数导数的方法,它结合了符号微分和数值计算的思想,其核心要点如下:
- 基于基本运算的分解:任何复杂的计算机程序所执行的运算,归根结底都是由加减乘除等基本算术运算以及指数、对数、三角函数等初等函数运算组成。自动微分就是利用这一事实,将复杂函数分解为一系列基本运算的组合。
- 符号微分与数值计算结合:先对最基本的算子(如常数、幂函数等)应用符号微分法,得到它们的导数表达式,然后代入具体数值进行计算,并保留中间结果。这样既利用了符号微分的精确性,又能通过数值计算得到具体的导数值。
- 链式求导法则的应用:自动微分的关键是将链式求导法则应用于整个函数。通过将函数分解为基本运算的组合,链式法则可以将这些基本运算的导数组合起来,从而计算出整个函数的导数。这样可以以任意精度自动地计算导数,而且计算量最多只比原始程序多一个常数级的运算。
- 计算图的构建:自动微分将原始函数表示为一个有向无环图(DAG),把公式中的一些部分整理出来作为新变量,并将这些新变量作为节点,依据运算逻辑构建计算图。在计算过程中,数据正向传播,计算出中间节点,并记录节点之间的依赖关系。这种计算图的表示方式使得自动微分能够清晰地描述函数的计算过程,并且便于应用链式法则进行导数计算。
总结
- 自动微分与可微编程的概念:
- 自动微分的未来趋势是可微编程,即将自动微分技术深度融入语言设计、编译器、解释器和IDE等工具链中,让微分成为高级编程语言的核心特性。
- 可微编程是一种编程范式,在这种范式下,数值计算程序能够始终利用自动微分来计算导数,进而实现对程序中参数的基于梯度的优化,常用的方法有梯度下降等基于高阶微分信息的学习方法。该编程范式在科学计算和AI等多个领域都有应用。
- 可微编程框架的工作方式与分类:
- 大多数可微编程框架通过构建包含程序控制流和数据结构的图来运行。
- 这些框架主要分为两类:
- 基于静态和编译图的方法:像TensorFlow、Theano、MXNet和PaddlePaddle等都属于此类。其优势在于能实现良好的编译器优化,并且适合扩展到大型系统中。然而,静态特性使它们的交互性欠佳,在编写包含循环和递归等复杂结构的程序时存在限制,同时用户也难以对程序进行推理和有效解释。
- 基于动态图的方法:例如PyTorch、AutoGrad和MindSpore等。它们的动态性和交互性使得大多数程序更易于编写和理解。但缺点是会带来解释器开销(尤其是在组合大量小操作时),还会降低可扩展性,并且减少了编译器优化所带来的益处。另外,Myia作为一个概念验证编译器工具链,以Python的一个子集作为前端,支持高阶函数、递归和高阶导数,还支持运算符重载。
- 先前方法的局限性及新方法:
- 先前的可微编程方法只能处理用特定语言编写的代码,AI框架方法还限制了与其他程序的互操作性。
- 新的可微编程方法通过从语言的语法或中间表示(IR)构造图形,解决了上述问题,实现了对任意代码的区分。
- 自动微分面临的挑战:
- 易用性方面:主要存在控制流表达不够灵活、处理复杂数据类型困难以及语言特性融合不足等问题。
- 高效性能方面:重点关注如何优化程序的分解、微分和组合的执行策略,以提高运行效率。
- 自动微分的未来发展方向:未来自动微分可能会朝着可微编程的方向发展,进一步深化自动微分技术与语言设计、编译器和解释器等工具链的融合,真正实现微分在高级编程语言中作为一等特性的目标。