我如何在TMB .CPP文件中包含更多目标功能

How do I include more objective functions in my TMB .cpp file?

本文关键字:包含更 目标 功能 文件 CPP TMB      更新时间:2023-10-16

TMB目标函数似乎是在一个保存到<name>.cpp文件的一个功能块中定义的。然后,在编译文件后,通过加载命令dyn.load(dynlib(<name>))访问每个目标函数。

是否可以在每个.cpp文件中存储多个目标函数?例如,以下两个目标函数彼此非常相似,但是目前需要将其保存到不同的文件:

// TMB Tutorial but with fixed variance
#include <TMB.hpp>                                // Links in the TMB libraries
template<class Type>
Type objective_function<Type>::operator() ()
{
    DATA_VECTOR(x);                                 // Data vector transmitted from R
    PARAMETER(mu);                                  // Parameter value transmitted from R
    Type sigma = 1.0;
    Type f;                                         // Declare the "objective function" (neg. log. likelihood)
    f = -sum(dnorm(x,mu,sigma,true));               // Use R-style call to normal density
    return f;
}

// TMB Tutorial
#include <TMB.hpp>                                // Links in the TMB libraries
template<class Type>
Type objective_function<Type>::operator() ()
{
    DATA_VECTOR(x);                                 // Data vector transmitted from R
    PARAMETER(mu);                                  // Parameter value transmitted from R
    PARAMETER(sigma);                               //                 
    Type f;                                         // Declare the "objective function" (neg. log. likelihood)
    f = -sum(dnorm(x,mu,sigma,true));               // Use R-style call to normal density
    return f;
}

MakeADFun()的"映射"参数允许您以特定值修复参数。

在此示例中,我们只需要编译/加载后一个模板。首先,我们将模板写入文件,编译并加载结果dll。

library(TMB)
file_conn <- file('test.cpp')
writeLines("
#include <TMB.hpp>                                
template<class Type>
Type objective_function<Type>::operator() ()
{
    DATA_VECTOR(x);                                 
    PARAMETER(mu);                                  
    PARAMETER(sigma);                               
    Type f;                                         
    f = -sum(dnorm(x,mu,sigma,true));               
    return f;
}
", file_conn)
close(file_conn)
compile('test.cpp')
dyn.load(dynlib('test'))

我们可以使用相同的DLL适合有或没有不同Sigma的模型。

n <- 100
x <- rnorm(n = n, mean = 0, sd = 1) 
f1 <- MakeADFun(data = list(x = x),
               parameters = list(mu = 0, sigma = 1),
               DLL = 'test')
f2 <- MakeADFun(data = list(x = x),
                parameters = list(mu = 0, sigma = 1),
                DLL = 'test',
                map = list(sigma = factor(NA)))
opt1 <- do.call('optim', f1)
opt2 <- do.call('optim', f2)

使用"映射"时,指定的参数(在这种情况下为Sigma)是固定在"参数"中给出的值。

中给出的值。

优化之后,我们进行理智检查 - MUS应该几乎相同。

> opt1$par
        mu      sigma 
0.08300554 1.07926521 
> opt2$par
        mu 
0.08300712 

换和关闭随机效果要困难得多。此处给出的一个示例,您可以在其中使用CppAD::Variable()检查是否降低了负log-likelione。

对于非相似的目标函数(不是彼此的子集),您可以将DATA_INTEGERDATA_STRING传递到模板中,例如就像他们在GLMMTMB中所做的一样,并根据DATA_*的值选择目标函数。

我只是想清楚地说明@AlexForrence的含义

对于非相似的目标函数(不是彼此的子集),您可以将data_integer或data_string传递到模板中,例如就像他们在GLMMTMB中所做的一样,并根据该数据的值选择目标函数_*

事实证明,TMB GitHub上有一个代码片段,可以涵盖此情况,我在此处复制:

#include <TMB.hpp>
template<class Type>
Type objective_function<Type>::operator() ()
{
  DATA_STRING(model_type);
  if (model_type == "model1") {
    #include "model1.h"
  } else
  if (model_type == "model2") {
    #include "model2.h"
  } else {
    error ("Unknown model type")
  }
  return 0;
}

也就是说,通过一个字符串,告诉目标函数要选择的模型,然后在单独的.h文件中包含该功能的文本。