假设我使用R
,optimx
来解决优化问题。有什么办法可以随着时间的推移提取参数和目标函数值吗?
f<-function(x){
return(sum(abs(x)))
}
gr<-function(x){
return(sign(x))
}
opt=optimx::optimx(runif(2),f,gr,method="BFGS")
目标是试图制作这样的情节:
我认为我们可以使用以下代码手动执行Gradient Decent,但我如何才能在optimx
中执行此操作?
x=c(0.5,1.5)
alpha=0.1
max_iter=20
x_trace=matrix(rep(0,max_iter*2),ncol=2)
for (i in 1:max_iter){
x=x-alpha*gr(x)
x_trace[i,]=x
}
f_trace=apply(x_trace,1,f)
答案 0 :(得分:5)
创建副作用:
f<-function(x){
.GlobalEnv$i <- get("i", envir = .GlobalEnv) + 1
.GlobalEnv$log[get("i", envir = .GlobalEnv),] <- x
return(sum(abs(x)))
}
gr<-function(x){
return(sign(x))
}
library(optimx)
i <- 0
log <- matrix(numeric(100 * 2), ncol = 2)
opt <- optimx(c(0.8, -0.9),f,gr,method="BFGS")
log <- log[seq_len(i), ]
plot(log, type = "l", xlim = c(-2, 2), ylim = c(-1.2, 1.2))
请注意,这包括所有函数调用,即使算法拒绝结果和重试的函数调用。 control = list(trace = TRUE, REPORT = 1)
允许optimx
打印已接受尝试的函数值,您可以capture.output
这个并使用它来仅从log
获取这些参数。
最好更改optimx
以返回所有已接受的尝试,但我不打算投入那种努力。你可以问纳什教授是否愿意这样做,但如果你没有引人注目的常见用例,他可能也不会这样做。
答案 1 :(得分:2)
据我所知,method="L-BFGS-B"
可以制作参数的进度报告。但结果没有报告,所以我保留了消息并提取了值。
library(optimx); library(dplyr)
cap <- capture.output(optimx(runif(2), f, gr, method="L-BFGS-B",
control=list(trace=6, REPORT=1)))
temp <- cap[grep("X =|X0 =", cap)]
d <- gsub("X0 = |X = |Cauchy X = ", "", temp) %>% strsplit(" ") %>%
unlist() %>% as.numeric() %>% matrix(ncol=2, byrow=T)
plot(-2:2,-2:2, type="n", ann=F)
for(i in c(1,2,4)) polygon(c(-0.5,0,0.5,0, -0.5)*i, c(0, 0.5, 0, -0.5, 0)*i)
points(d, pch=letters[1:nrow(d)])
[编辑]
正如帮助所说,源代码(opt/lbfgs_bcm.shar)有助于准确理解这些值(@Roland评论,谢谢!!)。将this approach与method="L-BFGS-B"
一起使用,您可以获得有关control=list(trace=6, REPORT=1)
报告的值的其他信息。