**优化**和**uniroot**有什么区别?

ano*_*ova 5 r

我查看了uniroot和optimize的描述,但它们有些不同,但书籍参考是一样的,我想知道是否有理由选择一个而不是另一个?

Stu*_*art 8

至于理由选择一个而不是另一个.在(可能)大多数情况下,一个人会更自然.正如@shadow所说,optimise是用于最小化(或最大化)并且uniroot用于寻找零点.

但在某些情况下,您可以使用其中任何一种来解决问题.这通常是因为你可以采取衍生工具,但可能还有另一种方法来重构你的问题.本答案的其余部分将讨论这些情况,您实际上可以选择并需要在两种情况之间进行选择.

举个简单的例子,我们可能想找到函数的最小值:

Func = function(x) {
  (2*x-pi)^2 + exp(1)*x - 18
}
Run Code Online (Sandbox Code Playgroud)

一种方法是使用optimizeas:

OResult = optimize(Func, lower = 0, upper = 5)
OResult
$minimum
[1] 1.231011

$objective
[1] -14.19195
Run Code Online (Sandbox Code Playgroud)

另一种方法是通过采用导数来转换函数.由于最佳点是当导数为零时,我们需要像uniroot这样的寻根算法.所以功能变成:

DerivFunction = function(x) {
  4*(2*x-pi) + exp(1)
}
Run Code Online (Sandbox Code Playgroud)

哪个优化了:

UResult = uniroot(DerivFunction , interval = c(0,5))
UResult
$root
[1] 1.231011

$f.root
[1] 4.440892e-16

$iter
[1] 2

$init.it
[1] NA

$estim.prec
[1] 6.103516e-05
Run Code Online (Sandbox Code Playgroud)

速度

如果您在上述方法之间做出选择,那么您可能会optimize为了简单而选择.uniroot然而,有些情况可能会更快.

使用上面的例子,optimize函数调用函数7次,而uniroot只调用导数函数5次.(这可以通过将计数器放在上面的函数中找到).这是合乎逻辑的,优化不知道最小值有多低,而uniroot确实知道目标函数值为零.因此,uniroot通常会知道x轴的方向,而优化则需要更多地查看.

如果我们做基准测试,那么优化速度要快得多.所以一般来说(如果你正在考虑速度)使用优化,除非它是一个非常密集的函数,其中函数调用比优化算法正在做的更昂贵(当然在这些情况下,通常很难得到一种形式的要使用的问题uniroot).

library(microbenchmark)
microbenchmark(
  optimize(Func, lower = 0, upper = 5),
  uniroot(DerivFunction, interval = c(0,5))
)
Unit: microseconds
                                       expr    min     lq     mean  median     uq     max neval
       optimize(Func, lower = 0, upper = 5) 18.264 19.785 23.50664 20.7370 23.781 129.365   100
 uniroot(DerivFunction, interval = c(0, 5)) 63.161 67.346 74.10322 69.8195 76.858 143.062   100
Run Code Online (Sandbox Code Playgroud)

多个局部最优

优化函数可能找不到全局最优,而只是局部最优.同样如此uniroot,可以找到局部零但不存在其他零.uniroot不同于optimize然而由于同时设置优化找到最大或最小值,uniroot会发现,相交y轴的点.如果你uniroot是一个导数,那么这一点可能是最小值或最大值.

例如,如果我们有以下功能和衍生物:

TwoMinFunction = function(x){
  ((x)^4)/4 + x^3 - 3*x^2 - 8*x + 16
}

TwoZeroDerivFunction = function(x){
  (x^3 + 3*x^2 ? 6*x ? 8) 
}
Run Code Online (Sandbox Code Playgroud)

此功能如下图所示: TwoMinimumFunction

OResult = optimize(TwoMinFunction, lower = -6, upper = 4)
OResult
$minimum
[1] -4.000001

$objective
[1] 8.007817e-12

UResult = uniroot(TwoZeroDerivFunction , interval = c(-6,4))
UResult
$root
[1] -1

$f.root
[1] 0

$iter
[1] 1

$init.it
[1] NA

$estim.prec
[1] 5
Run Code Online (Sandbox Code Playgroud)

这里发生的是优化发现两个最小值之一.另一方面,uniroot功能发现了一个最大值(因为uniroot无法区分最小值和最大值).


sha*_*dow 6

这两个功能有完全不同的用途:

  • optimize 用于查找函数的最小值(或最大值).

  • uniroot 用于查找函数的根(零).