我正在处理一个涉及使用似然函数(lik
)及其渐变(grad
)的优化问题。这两个函数都使用Rcpp
库进行编码,并被送到R中的optim(...,method="BFGS")
优化函数。
在计算似然性的过程中,会创建许多变量,并且对将来的梯度计算也有用。为了避免每次需要进行渐变评估时重新计算这些变量,我想出了创建env
用来与lik
“沟通”的环境(grad
)的想法。 。换句话说,每次评估lik
时,它都会在环境env
中存储所需的变量
likelihoodscript<-
using Rcpp::Environment;
Environment e(env);
// likelihood function is computed
//var1 to varK are created
//they can be MatrixXd, SparseMatrix, double, etc.
e.assign("namevar1",var1);
e.assign("namevar2",var2);
...
e.assign("namevarK",varK);
return wrap(likvalue);
然后,当需要进行grad
评估时,我会从grad
函数中搜索环境中所需的变量:
gradientscript<-
using Rcpp::Environment;
Environment e(env);
//var1 to varK are recovered from the environment
SEXP input_var1 = e.get("var1");
int var1 = as<int>(var1);
SEXP input_var2= e.get("var2");
MatrixXd var2 = as<MatrixXd>(var2);
...
SEXP input_varK = e.get("varK");
double varK = as<double>(varK);
// gradient function is computed
return wrap(gradvector);
理论上,如果我使用相同的初始参数集开始优化问题,我应该每次都得到相同的结果(lik
,grad
或{内部没有随机操作{1}}),但碰巧结果有时会有所不同。让我们说,如果我用完全相同的参数重复20次优化,15次我有很好的结果,但其中5次我有不同(或非常不同)的东西。我在这些错误中搜索了“模式”,但它们看起来完全是随机的。
据我所知,这可能是由于环境哈希表中的键值识别错误,因此我尝试在R中使用optim()
包。一些改进(可能是好结果的18倍,而不是15),但还不是问题的确切解决方案。
如果有人知道问题可能来自哪里,请回答。 非常感谢你。
Pd积。我尝试了同样的事情,但使用的是hash
而不是list
:同样的问题,甚至是最差的问题。
答案 0 :(得分:0)
如果没有您身边的具体例子,很难说出问题所在。这是我想出的可能是你的代码。也许这可以帮助你,或者它可以帮助你指出你与我的例子的不同之处。
我的代码可以工作,并且cpp
函数的所有不同的优化运行都会产生相同的结果。
library(inline)
#Rosenbrock Banana function as in optim examples
#it stores two values in the provided environment
fun_str='using Rcpp::Environment;
Environment e(env);
NumericVector xx(x);
double a=(xx[1] - xx[0] * xx[0]);
double b=(1.0 - xx[0]);
e.assign("a",a);
e.assign("b",b);
return(wrap(100.0 * pow(a,2.0) + pow(b,2.0)));'
#corresponding gradient
#it accesses the two variables that we have stored above
grad_str='using Rcpp::Environment;
Environment e(env);
double a=e["a"];
double b=e["b"];
NumericVector xx(x);
NumericVector res(2);
res[0]= -400.0 * xx[0] * a - 2.0 * b;
res[1]=200.0*a;
return(wrap(res));'
#define rcpp functions
fun_cpp=cxxfunction(signature(x="numeric",env = "environment"),
fun_str,
plugin = "Rcpp")
grad_cpp=cxxfunction(signature(x="numeric",env = "environment"),
grad_str,
plugin = "Rcpp")
res_vec=list()
#loop through 100 runs of the same BFGS optimization and store results
for (i in 1:100) {
container_env=new.env()
res_vec[[length(res_vec)+1]]=optim(par=c(-1.2,1),fn=fun_cpp,gr=grad_cpp,method="BFGS",env=container_env)
}
#compare all results
sum_var=0
for (i in 2:length(res_vec)) sum_var=sum_var+all.equal(res_vec[[i]],res_vec[[i-1]])
sum_var
#99
所以你看他们都给出了相同的结果。
此外,结果与optim
示例部分中给出的仅R代码的结果一致。