优化问题是我研究过程中需要大量使用的工具。

学习资料

常见问题

  1. 这个优化函数是求最大值的还是最小值?

By default optim performs minimization, but it will maximize if control$fnscale is negative.

使用实例

一维函数例子

例子1:

函数 \(f(x) = -e^ {-(x-2)^2}\),可以求其导数 \(f(x)^{'}\)

f <- function(x) -exp(-( (x-2)^2 ))
optim(1, f)$par
## Warning in optim(1, f): one-dimensional optimization by Nelder-Mead is unreliable:
## use "Brent" or optimize() directly
## [1] 1.9
optimise(f, c(0,10))
## $minimum
## [1] 2
## 
## $objective
## [1] -1
df <- function(x) -2*(x-2)*f(x)
optim(1, f, df, method="CG")$par
## [1] 2
# with "Brent" method
optim(1,f,method="Brent",lower=-0,upper=3)$par
## [1] 2
# figure
library(ggplot2)
x = seq(0,3,length.out = 100)
y = f(x)
ggplot(data.frame(x,y), aes(x, y)) + geom_point(color = "green",size = 1)

例子2:

函数 \(f(x) = sin(x cos(x))\)

#算法可以很快地发现与初值相近的局部最优值。
f <- function(x) sin(x*cos(x))
optim(2, f)$par
## [1] 2.316016
optim(4, f)$par
## [1] 4.342236
optim(6, f)$par
## [1] 5.688647
optim(8, f)$par
## [1] 7.132227

二维函数例子

函数 \[f(x,y) = (1-x)^2 + 100 (y - x^2)^2\]

# 绘图
f <- function(x1,y1) (1-x1)^2 + 100*(y1 - x1^2)^2
x <- seq(-2,2,by=.15)
y <- seq(-1,3,by=.15)
z <- outer(x,y,f)
persp(x,y,z,phi=45,theta=-45,col="yellow",shade=.00000001,ticktype="detailed")

# 求解
f <- function(x) (1-x[1])^2 + 100*(x[2]-x[1]^2)^2
# starting values must be a vector now
optim( c(0,0), f )$par
## [1] 0.9999564 0.9999085

加速了。。。直取敌首,迅猛推进,找到关键问题。最小二乘法!!!

d = data.frame(x=1:6,y=c(1,3,5,6,8,12))
ggplot(d,aes(x,y)) + geom_point() +  stat_smooth(method = "lm")

# 最小问题的优化函数
min.RSS = function(data,par) {
    with(data,sum((par[1]+par[2]*x-y)^2))
}
#optim函数调用的格式
result = optim(par=c(0,0),min.RSS,data=d)
#optim调用的结果参数
result$par
## [1] -1.265596  2.028418
result$value
## [1] 2.81905
result$counts
## function gradient 
##       91       NA
result$convergence
## [1] 0
result$message
## NULL
#可视化分析结果
ggplot(d,aes(x,y)) + geom_point() +geom_abline(intercept=result$par[1],
    slope=result$par[2],color="red")

#optim与lm的结果对比分析
lm(y~x,data=d)
## 
## Call:
## lm(formula = y ~ x, data = d)
## 
## Coefficients:
## (Intercept)            x  
##      -1.267        2.029
result$par
## [1] -1.265596  2.028418

这个里面的每行代码都很关键,真的需要认真记忆!!!