Как мне включить более объективные функции в мой файл 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
файл.