Подтвердить что ты не робот

Перемещение за пределы функции R optim

Я пытаюсь использовать R для оценки многочленной логитной модели с ручной спецификацией. Я нашел несколько пакетов, которые позволяют вам оценивать модели MNL здесь или здесь.

Я нашел несколько других статей о "прокатке" вашей собственной функции MLE здесь. Однако, из-за моего копания - все эти функции и пакеты полагаются на внутреннюю функцию optim.

В моих тестовых тестах optim является узким местом. Используя смоделированный набор данных с ~ 16000 наблюдениями и 7 параметрами, R занимает около 90 секунд на моей машине. Эквивалентная модель в Biogeme занимает ~ 10 секунд. Коллега, который пишет свой собственный код в Ox, сообщает около 4 секунд для этой же модели.

Есть ли у кого-нибудь опыт написания собственной функции MLE или можно указать мне в сторону чего-то, что оптимизировано за пределами функции optim по умолчанию (каламбур не предназначен)?

Если кто-то хочет, чтобы R-код воссоздал модель, дайте мне знать - я получу ее. Я не предоставил его, поскольку он не имеет прямого отношения к проблеме оптимизации функции optim и для сохранения пространства...

EDIT: Спасибо всем за ваши мысли. Основываясь на множестве комментариев ниже, мы смогли получить R в том же самом поле, что и Biogeme, для более сложных моделей, и R действительно быстрее для нескольких более мелких/более простых моделей, которые мы запускали. Я думаю, что долгосрочное решение этой проблемы будет связано с написанием отдельной функции максимизации, которая опирается на fortran или библиотеку C, но, безусловно, открыта для других подходов.

4b9b3361

Ответ 1

Пробовал с функцией nlm() уже? Не знаю, если это намного быстрее, но оно улучшает скорость. Также проверьте параметры. Оптимист использует медленный алгоритм по умолчанию. Вы можете получить > 5-кратное ускорение, используя алгоритм Квази-Ньютона (метод = "BFGS" ) вместо значения по умолчанию. Если вы не слишком беспокоитесь о последних цифрах, вы также можете установить уровни допуска выше nlm(), чтобы получить дополнительную скорость.

f <- function(x) sum((x-1:length(x))^2)

a <- 1:5

system.time(replicate(500,
     optim(a,f)
))
   user  system elapsed 
   0.78    0.00    0.79 

system.time(replicate(500,
     optim(a,f,method="BFGS")
))
   user  system elapsed 
   0.11    0.00    0.11 

system.time(replicate(500,
     nlm(f,a)
))
   user  system elapsed 
   0.10    0.00    0.09 

system.time(replicate(500,
      nlm(f,a,steptol=1e-4,gradtol=1e-4)
))
   user  system elapsed 
   0.03    0.00    0.03 

Ответ 3

FWIW, я сделал это в C-ish, используя OPTIF9. Тебе было бы тяжело идти быстрее. Существует множество способов замедления работы, например, путем запуска интерпретатора, такого как R.

Добавлено: Из комментариев видно, что OPTIF9 используется в качестве механизма оптимизации. Это означает, что, скорее всего, основная часть времени тратится на оценку целевой функции в R. Хотя возможно, что функции C используются под некоторыми операциями, все же накладные расходы переводчика. Существует быстрый способ определить, какие строки вызовов кода и функций в R ответственны в течение большей части времени, а именно, чтобы приостановить его с помощью клавиши Escape и изучить стек. Если оператор стоит X% времени, он находится в стеке X% времени. Вы можете обнаружить, что есть операции, которые не идут на C и должны быть. Любой коэффициент ускорения, который вы получите таким образом, будет сохранен, когда вы найдете способ распараллеливать выполнение R.

Ответ 4

Я являюсь автором пакета R optimParallel, который может быть полезен в вашем случае. Пакет предоставляет параллельные версии методов оптимизации на основе градиента optim(). Основной функцией пакета является optimParallel(), который имеет одинаковое использование и вывод, как optim(). Использование optimParallel() может значительно сократить время оптимизации, как показано на следующем рисунке (p - количество параметров). enter image description here Для получения дополнительной информации см. Https://cran.r-project.org/package=optimParallel и http://arxiv.org/abs/1804.11058.