Бібліотеки C ++ для статистичних обчислень


23

У мене є особливий алгоритм MCMC, який я хотів би перенести на C / C ++. Значна частина дорогих обчислень вже є на C через Cython, але я хочу, щоб весь зразок був написаний компільованою мовою, щоб я міг просто писати обгортки для Python / R / Matlab / що завгодно.

Після тикання навколо я схиляюся до С ++. Кілька відомих мені бібліотек - Armadillo (http://arma.sourceforge.net/) та Scythe (http://scythe.wustl.edu/). Обидва намагаються наслідувати деякі аспекти R / Matlab, щоб полегшити криву навчання, що мені дуже подобається. Коси квадрати трохи краще, що я хочу зробити, я думаю. Зокрема, його RNG включає багато розповсюджень, де Armadillo має єдину / нормальну, що незручно. Armadillo, здається, перебуває у досить активному розвитку, тоді як Scythe побачив свій останній реліз у 2007 році.

Тож мені цікаво, якщо хтось має досвід роботи з цими бібліотеками - або з іншими, які я майже напевно пропустив - і якщо так, чи є щось, що можна порекомендувати одному за інших для статистики, добре знайомого з Python / R / Matlab але менше - з компільованими мовами (не зовсім неосвіченими, але не зовсім знаннями ...).

Відповіді:


18

Ми витратили деякий час, роблячи обгортання з C ++ в R (і назад), набагато простіше через наш пакет Rcpp .

А тому, що лінійна алгебра - це вже настільки добре зрозуміле і закодоване поле, Армаділло , сучасна, сучасна, витончена, добре задокументована, невелика, шаблонна, ... бібліотека була цілком природною для нашого першого розширеного обгортка: RcppArmadillo .

Це привернуло увагу і інших користувачів MCMC. Я провів одноденну роботу в бізнес-школі міста У Рочестера минулого літа і маю допомогу іншому досліднику в Середньому Заході з подібними дослідженнями. Спробуйте RcppArmadillo - він добре працює, активно підтримується (новий Armadillo випуск 1.1.4 сьогодні, я зроблю новий RcppArmadillo пізніше) і підтримується.

І тому що я просто так люблю цей приклад, ось швидка "швидка" версія lm()коефіцієнта повернення та std.errors:

extern "C" SEXP fastLm(SEXP ys, SEXP Xs) {

  try {
    Rcpp::NumericVector yr(ys);                 // creates Rcpp vector 
    Rcpp::NumericMatrix Xr(Xs);                 // creates Rcpp matrix 
    int n = Xr.nrow(), k = Xr.ncol();

    arma::mat X(Xr.begin(), n, k, false);       // avoids extra copy
    arma::colvec y(yr.begin(), yr.size(), false);

    arma::colvec coef = arma::solve(X, y);      // fit model y ~ X
    arma::colvec res = y - X*coef;              // residuals

    double s2 = std::inner_product(res.begin(), res.end(), 
                                   res.begin(), double())/(n - k);
                                            // std.errors of coefficients
    arma::colvec std_err = 
           arma::sqrt(s2 * arma::diagvec( arma::pinv(arma::trans(X)*X) ));  

    return Rcpp::List::create(Rcpp::Named("coefficients") = coef,
                              Rcpp::Named("stderr")       = std_err,
                              Rcpp::Named("df")           = n - k);

  } catch( std::exception &ex ) {
      forward_exception_to_r( ex );
  } catch(...) { 
      ::Rf_error( "c++ exception (unknown reason)" ); 
  }
  return R_NilValue; // -Wall
}

Нарешті, ви також отримуєте негайне прототипування через вбудовану лінію, що може зробити час для коду швидше.


Спасибі Дірк - у мене було відчуття, що ти відповідеш раніше, ніж пізніше :). З огляду на те, що я хочу отримати код, з якого я можу зателефонувати з іншого програмного забезпечення (головним чином, Python, але також Matlab), можливо, хорошим робочим процесом було б прообразувати в Rcpp / RcppArmadillo, а потім перейти до "прямого" Armadillo? Синтаксис тощо виглядає дуже схоже.
JMS

1
Сподіваюся, ви виявили це корисним.
Дірк Еддельбуеттель

Повторіть своє 2-е запитання з редакції: Звичайно. Armadillo залежить від мало, або, в нашому випадку, нічого, крім R. Rcpp / RcppArmadillo не допоможе вам інтерфейсу та тестування прототипового коду, який можна використовувати самостійно, або із обгортками Python та Matlab, які ви можете додати пізніше. У Конрада можуть бути вказівники на щось; У мене немає ні для Python, ні для Matlab.
Дірк Еддельбуеттель

Вибачте, що витягнув килимок :) Я хочу, щоб ключ введення повернув перевезення, але він надіслав мій коментар. Так чи інакше, дякую за вашу допомогу - я цілий день насолоджувався майстерністю та копанням через список розсилки Rcpp.
JMS

8

Я настійно пропоную вам ознайомитись RCppі RcppArmadilloпакети для R. В основному, вам не потрібно буде турбуватися про обгортки, оскільки вони вже «включені». Крім того, синтаксичний цукор дійсно солодкий (призначений для каламбуру).

В якості побічного зауваження я рекомендую вам ознайомитись з тим JAGS, що робить MCMC та його вихідний код у C ++.


2
Я хотів би другий. Якщо ви шукаєте швидкий і простий спосіб інтерфейс скомпільований код з R, Rcppз RcppArmadilloце шлях. Редагувати: Використовуючи Rcpp, ви також маєте доступ до всіх RNG, які містяться в C-коді, що лежить в основі R.
fabians

Дякуємо за вотум довіри. Я збирався запропонувати те саме ;-)
Дірк Еддельбуеттель,

7

Збільшення випадкових випадків із бібліотек Boost C ++ могло б вам підійти. На додаток до багатьох типів RNG, він пропонує безліч різних дистрибутивів, наприклад, наприклад

  • Уніформа (реальна)
  • Уніформа (одинична сфера або довільний вимір)
  • Бернуллі
  • Двомісні
  • Коші
  • Гамма
  • Пуассон
  • Геометричні
  • Трикутник
  • Експоненціальна
  • Нормальний
  • Лонормальне

Крім того, Boost Math доповнює вищезазначені дистрибутиви, з яких ви можете вибирати з численними функціями щільності багатьох дистрибутивів. Він також має кілька акуратних помічників; просто, щоб дати вам ідею:

students_t dist(5);

cout << "CDF at t = 1 is " << cdf(dist, 1.0) << endl;
cout << "Complement of CDF at t = 1 is " << cdf(complement(dist, 1.0)) << endl;

for(double i = 10; i < 1e10; i *= 10)
{
   // Calculate the quantile for a 1 in i chance:
   double t = quantile(complement(dist, 1/i));
   // Print it out:
   cout << "Quantile of students-t with 5 degrees of freedom\n"
           "for a 1 in " << i << " chance is " << t << endl;
}

Якщо ви вирішили використовувати Boost, ви також можете використовувати його бібліотеку UBLAS, яка містить безліч різних матричних типів та операцій.


Дякую за пораду. Boost виглядає як би великий молоток для мого маленького нігтя, але зрілий і доглянутий.
JMS

Я не впевнений, що boot :: math :: binomial_distribution має ту саму функцію, що й у двосторонній R binom.test (). Я заглянув у довідник і не зміг знайти цю функцію. Я намагався це здійснити, і це не банально!
Кемін Чжоу

1

Існує чимало бібліотек C / C ++ там, більшість з яких зосереджується на певній проблемній області (наприклад, PDE-вирішувачі). Є дві вичерпні бібліотеки, які, на мою думку, можуть бути особливо корисними, оскільки вони написані на C, але мають чудові обгортки Python.

1) IMSL C і PyIMSL

2) трилінос і пітрилінос

Я ніколи не використовував триліно, оскільки функціональність полягає в основному на методах чисельного аналізу, але я багато використовую PyIMSL для статистичної роботи (і в попередньому робочому житті я також розробляв програмне забезпечення).

Що стосується RNG, то тут вони знаходяться в C та Python в IMSL

ДИСКРЕТ

  • random_binomial: генерує псевдовипадкові двочленні числа з біноміального розподілу.
  • random_geometric: генерує псевдовипадкові числа з геометричного розподілу.
  • random_hypergeometric: генерує псевдовипадкові числа з гіпергеометричного розподілу.
  • random_logarithmic: генерує псевдовипадкові числа з логарифмічного розподілу.
  • random_neg_binomial: генерує псевдовипадкові числа з негативного біноміального розподілу.
  • random_poisson: генерує псевдовипадкові числа з розподілу Пуассона.
  • random_uniform_discrete: Створює псевдовипадкові числа з дискретного рівномірного розподілу.
  • random_general_discrete: генерує псевдовипадкові числа із загального дискретного розподілу, використовуючи метод псевдоніму або необов'язково метод пошуку таблиці.

Універсальні безперервні розподіли

  • random_beta: генерує псевдовипадкові числа з бета-розподілу.
  • random_cauchy: генерує псевдовипадкові числа з розподілу Коші.
  • random_chi_squared: генерує псевдовипадкові числа з розподілу chi-квадрата.
  • random_exponential: генерує псевдовипадкові числа зі стандартного експоненціального розподілу.
  • random_exponential_mix: генерує псевдовипадкові змішані числа зі стандартного експоненціального розподілу.
  • random_gamma: генерує псевдовипадкові числа зі стандартного розподілу гамми.
  • random_lognormal: генерує псевдовипадкові числа з лонормального розподілу.
  • random_normal: генерує псевдовипадкові числа зі стандартного нормального розподілу.
  • random_stable: встановлює таблицю для генерації псевдовипадкових чисел із загального дискретного розподілу.
  • random_student_t: генерує псевдовипадкові числа з t-розподілу Стьюдента.
  • random_triangular: генерує псевдовипадкові числа з трикутного розподілу.
  • random_uniform: генерує псевдовипадкові числа з рівномірного (0, 1) розподілу.
  • random_von_mises: генерує псевдовипадкові числа з розподілу фон Мізеса.
  • random_weibull: генерує псевдовипадкові числа з розподілу Weibull.
  • random_general_continuous: генерує псевдовипадкові числа із загального безперервного розподілу.

МНОГОБІЛЬВАРІАТНІ НЕЗАБАЖНІ РОЗМІСТИ

  • random_normal_multivariate: генерує псевдовипадкові числа з багатоваріантного нормального розподілу.
  • random_orthogonal_matrix: Створює псевдовипадкову ортогональну матрицю або кореляційну матрицю.
  • random_mvar_from_data: генерує псевдовипадкові числа з багатоваріантного розподілу, визначеного для даного зразка.
  • random_multinomial: генерує псевдовипадкові числа з мультиноміального розподілу.
  • random_sphere: створює псевдовипадкові точки на одиничному колі або K-мірній сфері.
  • random_table_twoway: Створює псевдовипадкову двосторонню таблицю.

ЗАМОВЛЕННЯ СТАТИСТИКИ

  • random_order_normal: генерує статистику псевдовипадкових порядків із стандартного нормального розподілу.
  • random_order_uniform: Створює статистику псевдовипадкових порядків з рівномірного (0, 1) розподілу.

СТОХАСТИЧНІ ПРОЦЕСИ

  • random_arma: генерує псевдовипадкові номери процесу ARMA.
  • random_npp: генерує псевдовипадкові числа з неоднорідного процесу Пуассона.

ЗРАЗКИ ТА ВПРОВАДЖЕННЯ

  • random_permutation: створює псевдовипадкову перестановку.
  • random_sample_indices: Створює просту псевдовипадкову вибірку індексів.
  • random_sample: генерує просту псевдовипадкову вибірку з кінцевої сукупності.

ФУНКЦІЇ ДЕРЖАВНОСТІ

  • random_option: Вибирає рівномірний (0, 1) мультипликативний конгрурентний генератор псевдовипадкових чисел.
  • random_option_get: Отримує рівномірний (0, 1) мультиплікативний конгрурентний генератор псевдовипадкових чисел.
  • random_seed_get: отримує поточне значення насіння, що використовується у генераторах випадкових чисел IMSL.
  • random_substream_seed_get: Отримує насіння для вроджених генераторів, які не здійснюють перетасування, що генеруватиме випадкові числа, починаючи з 100000 чисел далі.
  • random_seed_set: ініціалізує випадкове насіння для використання у генераторах випадкових чисел IMSL.
  • random_table_set: Встановлює поточну таблицю, що використовується в генераторі перетасованих даних.
  • random_table_get: Отримує поточну таблицю, використану в генераторі перетасованих даних.
  • random_GFSR_table_set: Встановлює поточну таблицю, що використовується в генераторі GFSR.
  • random_GFSR_table_get: Отримує поточну таблицю, що використовується в генераторі GFSR.
  • random_MT32_init: ініціалізує 32-розрядний генератор Mersenne Twister за допомогою масиву.
  • random_MT32_table_get: Отримує поточну таблицю, використовувану в 32-бітному генераторі Mersenne Twister.
  • random_MT32_table_set: Встановлює поточну таблицю, використовувану в 32-бітному генераторі Mersenne Twister.
  • random_MT64_init: ініціалізує 64-бітний генератор Mersenne Twister за допомогою масиву.
  • random_MT64_table_get: Отримує поточну таблицю, використовувану в 64-бітному генераторі Mersenne Twister.
  • random_MT64_table_set: Встановлює поточну таблицю, що використовується в 64-розрядному генераторі Mersenne Twister.

НИСКО-БЕЗПЕЧЕННЯ ПОСЛІДЖЕННЯ

  • faure_next_point: обчислює перетасовану послідовність Faure.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.