指定导数

函数 FindRoot 有一个 选项;函数 FindMinimumFindMaximumFindFit 有一个 Gradient 选项;而"牛顿" 方法有一个方法选项 . 所有这些导数都用同样的基本结构来指定. 下面是用来指定导数计算方法的方式总结.    

Automatic寻找函数的一个符号化导数,当符号化导数无法找到时,则用有限差分近似
SymbolicAutomatic 相同,但在使用有限差分时,给出一个警告信息
FiniteDifference使用有限差分对导数进行近似
expression使用给定的 expression 及变量的局部数值值来计算导数

计算梯度,雅可比,和Hessian导数的方法.

对于一个导数的基本指定就是用来计算它的方法. 然而,所有导数也都采用选项. 这些可以通过使用列表 来指明. 下面是一个导数选项的总结.

选项名
默认值
"EvaluationMonitor"None当每次进行导数计算的时候,利用变量的局部值来计算的表达式. 经常用 而不是 指定来防止符号化的计算
"Sparse"Automatic导数的稀疏结构;可以是 AutomaticTrueFalse,或者是给出非零结构的一种模式 SparseArray
"DifferenceOrder"1当使用有限差分来计算导数时,所使用的差分阶数

计算梯度、雅可比和Hessian导数的选项.

我们将使用一些例子来说明以上这些方法和选项如何配合使用.     

这里加载一个包含一些功用函数的程序包.
这里定义了一个函数,唯一的目的是只对数值变量值进行计算.
In[2]:=
Click for copyable input

如果只使用 Method->"Newton"FindMinimum 会释放一条 lstol 消,这是因为,由于缺乏良好的导数信息,它不能够足够精确地解出极小值.

这里显示了 FindMinimum 所采取的步骤,这里它不得不使用有限差分来计算梯度和Hessian的.
In[3]:=
Click for copyable input
Out[3]=

下面介绍如何使用梯度选项来指定导数.

这里使用梯度的符号表达式来计算 的极小值.
In[4]:=
Click for copyable input
Out[4]=

符号化的导数不会总是有的. 如果在有限差分上,您需要更高的准确度,您可以从默认的值1增加差分阶数,但代价是额外的函数计算.

这里通过使用二阶有限差分计算梯度的方法来计算 的极小值.
In[5]:=
Click for copyable input
Out[5]=

请注意,函数计算的次数要高得多,因为函数计算被用来计算梯度,进而近似计算Hessian. (Hessian是使用有限差分计算的,因为从提供的信息看,我们没有符号化的表达式可以用来计算. )

所提供的一些关于函数,梯度,和Hessian计算次数的信息是相当有用的. 是 EvaluationMonitor 选项使之成为可能. 下面这个例子,只是合计各种类型计算的次数. (绘图时用 ReapSow 收集那些执行过计算的值. )

这里在计算极小值的同时用计数器来记录步骤数目和函数,梯度,以及Hessian的计算次数.
In[6]:=
Click for copyable input
Out[6]=

在决定什么方法和/或方法参数对于具有相似特点的一类问题可能是最成功的时候,使用这种诊断方法会是非常有益的.

当 Wolfram 语言能够访问函数的符号化结构时,它会自动对函数及其导数做结构分析并在适当的情况下,使用 SparseArray 对象来代表导数. 由于随后的数值线性代数可以使用稀疏结构,这可以对搜索的整体效率产生深刻的影响. 当 Wolfram 语言不能做结构分析时,一般来说,它必须假定该结构是稠密的. 但是,如果您知道该导数的稀疏结构是什么,您可以使用 方法选项对它进行指定,从而在导数计算(使用有限差分,计算的次数可以显著地降低)和随后的线性代数计算中,获得巨大的效率优势. 这个问题对于使用向量值的变量工作时尤为重要. 一个说明这方面问题的好例子是扩展的 Rosenbrock 问题,它有一个非常简单的稀疏结构.

这里用 程序包,获得随时可以用 FindRoot 求解的符号化表示的具有1000个变量的扩展的 Rosenbrock 函数.
In[7]:=
Click for copyable input
Out[7]//Short=
这里使用函数的符号化表示的形式求解问题.
In[8]:=
Click for copyable input
Out[8]=

对于一个形式像这样简单的函数来说,很容易写出函数的向量形式,这可以比符号化表示的形式更快地计算出来,即使是使用自动编译.

这里定义了一个扩展的 Rosenbrock 函数的向量形式,它可以非常快地进行计算.
In[9]:=
Click for copyable input
这里从问题结构中把初始点作为向量提取出来.
In[10]:=
Click for copyable input
Out[10]//Short=
下面在求解问题的计算中用了一个向量变量和向量函数.
In[11]:=
Click for copyable input
Out[11]=

通过函数来求解,在函数计算上很快,但总体上却较慢。原因是,由于 模式使得符号化分析不透明,雅可比必须使用有限差分进行计算. 这倒不是说有限差分多么慢,而是它需要做100次函数计算,以获得雅可比的所有列. 如果对结构有了解,这可以减少到两次计算就可得到雅可比. 对于这个函数,雅可比的结构很简单.

这里定义了一个模式 SparseArray,它具有扩展的 Rosenbrock 函数的雅可比的非零部分的结构. (通过指定规则中的值为 SparseArray 被当作一个 Pattern 类型的模版,正如输出形式中所显示的那样.)
In[12]:=
Click for copyable input
Out[12]=
这里在了解实际雅可比结构的情况下,求解该问题,并呈现出对成本的显著节约.
In[13]:=
Click for copyable input
Out[13]=

当一个稀疏结构给定时,我们也可以由符号化表达式计算得到值,这些值的计算对应于稀疏结构模板中给出的位置. 请注意,该值必须直接对应于 SparseArray 中排序给出的位置 (使用 ArrayRules 可以看到排序). 获得一个一致的指标排序的一个方法是对矩阵进行两次转置,这可以产生一个指标按字典顺序排序的 SparseArray.

这里对非零结构矩阵进行两次转置,以使指标排序.
In[14]:=
Click for copyable input
Out[14]=
这里定义了一个函数,它将返回在雅可比中对应于非零结构矩阵中指标位置的非零值.
In[15]:=
Click for copyable input
这里用产生的稀疏符号化雅可比求解问题.
In[16]:=
Click for copyable input
Out[16]=

在这种情况下,使用稀疏雅可比没有显著地更快,因为该雅可比如此稀疏,以至于只要两次函数计算就可以找到它的有限差分近似;也因为该问题在接近极小值处定义得足够好,以至于雅可比的更高的准确度并没有带来任何显著的差异.