Как мне включить более объективные функции в мой файл TMB .cpp?

Целевые функции 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;
}

2 ответа

Решение

Аргумент "map" для 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 для подбора моделей с различной сигма и без нее.

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)

При использовании "карты" указанный параметр (и) (в данном случае сигма) фиксируется на значении, указанном в "параметрах".

После оптимизации мы проводим проверку работоспособности - она ​​должна быть почти одинаковой.

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

Включение и выключение случайных эффектов немного сложнее. Пример этого приведен здесь, где вы можете использовать CppAD::Variable() проверить, уменьшать ли отрицательное логарифмическое правдоподобие или нет.

Для неодинаковых целевых функций (не подмножеств друг друга) вы можете передать DATA_INTEGER или же DATA_STRING в шаблон, например, как они сделали в glmmTMB здесь, и выберите целевую функцию в зависимости от значения этого DATA_*,

Я просто хотел уточнить, что означает @alexforrence

Для не похожих друг на друга целевых функций (не подмножеств друг друга) вы можете передать DATA_INTEGER или DATA_STRING в шаблон, например, как это было в glmmTMB, и выбрать целевую функцию в зависимости от значения этого DATA_*

Оказывается, есть фрагмент кода на github TMB, который охватывает этот сценарий, который я здесь дублирую:

#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 файл.

Другие вопросы по тегам