ไลบรารี C ++ สำหรับการคำนวณเชิงสถิติ


23

ฉันมีอัลกอริทึม MCMC เฉพาะซึ่งฉันต้องการพอร์ตไปยัง C / C ++ การคำนวณราคาแพงส่วนใหญ่อยู่ใน C ผ่านทาง Cython แล้ว แต่ฉันต้องการให้มีตัวอย่างทั้งหมดเขียนด้วยภาษาที่รวบรวมเพื่อที่ฉันจะได้เขียน wrappers สำหรับ Python / R / Matlab / อะไรก็ได้

หลังจากแหย่ไปมาฉันก็เอนไปทาง C ++ ห้องสมุดที่เกี่ยวข้องสองแห่งที่ฉันรู้จักคือ Armadillo (http://arma.sourceforge.net/) และ Scythe (http://scythe.wustl.edu/) ทั้งคู่พยายามเลียนแบบบางแง่มุมของ R / Matlab เพื่อทำให้เส้นโค้งการเรียนรู้ง่ายขึ้นซึ่งฉันชอบมาก Scythe กำลังดีขึ้นเล็กน้อยกับสิ่งที่ฉันอยากทำ โดยเฉพาะอย่างยิ่ง RNG ของมันรวมถึงการกระจายจำนวนมากที่อาร์มาดิลโล่มีเพียงชุดเครื่องแบบ / ปกติซึ่งไม่สะดวก อาร์มาดิลโล่ดูเหมือนว่าจะอยู่ภายใต้การพัฒนาที่ค่อนข้างคึกคักในขณะที่ Scythe ได้เปิดตัวครั้งสุดท้ายในปี 2550

ดังนั้นสิ่งที่ฉันสงสัยคือถ้าใครมีประสบการณ์กับห้องสมุดเหล่านี้ - หรือคนอื่น ๆ ที่ฉันเกือบจะพลาดแน่นอน - และถ้าเป็นเช่นนั้นไม่ว่าจะมีอะไรแนะนำให้คนอื่นมากกว่าสำหรับนักสถิติที่คุ้นเคยกับ Python / R / Matlab แต่น้อยกว่านั้นด้วยภาษาที่คอมไพล์แล้ว (ไม่ได้ไม่รู้อย่างสมบูรณ์ แต่ไม่เชี่ยวชาญ ... )

คำตอบ:


18

เราใช้เวลาในการตัดจาก C ++ ไปเป็นR (และย้อนกลับสำหรับเรื่องนั้น) ง่ายขึ้นมากผ่านแพ็คเกจ Rcppของเรา

และเนื่องจากพีชคณิตเชิงเส้นนั้นเป็นสนามที่เข้าใจและมีรหัสมาแล้วอาร์มาดิลโลกระแสที่ทันสมัยทันสมัย ​​plesant well-documted ขนาดเล็ก templated ... ไลบรารีจึงเป็นแบบที่เป็นธรรมชาติมากสำหรับเสื้อคลุมแรกของเรา: RcppArmadillo .

สิ่งนี้ดึงดูดความสนใจของผู้ใช้ MCMC รายอื่นเช่นกัน ฉันทำงานหนึ่งวันที่ U of Rochester เมื่อฤดูร้อนปีที่แล้วและได้ช่วยเหลือนักวิจัยอีกคนใน MidWest ด้วยการสำรวจที่คล้ายกัน ให้RcppArmadilloลอง - มันทำงานได้ดีจะถูกเก็บไว้อย่างแข็งขัน (ปล่อยนิ่มใหม่ 1.1.4 วันนี้ผมจะทำให้ RcppArmadillo ใหม่ในภายหลัง) และได้รับการสนับสนุน

และเพราะฉันแค่ luuv ตัวอย่างนี้มากนี่คือ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 แล้วย้ายไปที่ "ตรง" ตัวนิ่ม? ไวยากรณ์ ฯลฯ ดูคล้ายกันมาก
JMS

1
หวังว่าคุณจะพบว่ามันมีประโยชน์
Dirk Eddelbuettel

ตอบคำถามที่ 2 ของคุณจากการแก้ไข: แน่นอน อาร์มาดิลโล่ขึ้นอยู่กับเล็ก ๆ น้อย ๆ หรือในกรณีของเราไม่มีอะไรนอกเหนือจากอาร์ Rcpp / RcppArmadillo จะช่วยคุณอินเทอร์เฟซและทดสอบรหัสต้นแบบที่สามารถนำกลับมาใช้แบบสแตนด์อโลนหรือด้วย Python และ Matlab คอนราดอาจมีพอยน์เตอร์สำหรับบางอย่าง; ฉันไม่มี Python หรือ Matlab
Dirk Eddelbuettel

ขออภัยที่ดึงพรมออกมา :) ฉันต้องการให้ปุ่ม Enter เพื่อส่งคืนรถ แต่มันส่งความคิดเห็นของฉันแทน อย่างไรก็ตามขอขอบคุณสำหรับความช่วยเหลือของคุณ - ฉันสนุกกับการซ่อมแซมและขุดกลับมาที่รายชื่อผู้รับจดหมาย Rcpp ทุกวันวันนี้
JMS

8

ฉันจะขอแนะนำให้คุณมีลักษณะที่RCppและแพคเกจสำหรับRcppArmadillo Rโดยพื้นฐานแล้วคุณไม่จำเป็นต้องกังวลเกี่ยวกับสิ่งห่อหุ้มเพราะมีอยู่แล้ว "รวม" นอกจากนี้น้ำตาล syntactic จะหวานจริง ๆ (ปุนตั้งใจ)

ตามคำพูดด้านข้างฉันขอแนะนำให้คุณดูJAGSซึ่ง MCMC และซอร์สโค้ดของมันคือ C ++


2
ฉันต้องการที่สองนี้ หากคุณกำลังมองหาอย่างรวดเร็วและง่ายต่อการอินเตอร์เฟซที่รวบรวมรหัสกับ R, RcppกับRcppArmadilloเป็นวิธีที่จะไป แก้ไข: การใช้ Rcpp คุณยังสามารถเข้าถึง RNG ทั้งหมดที่ฝังอยู่ในรหัส C พื้นฐานอาร์
fabians

ขอขอบคุณที่โหวตความมั่นใจ ฉันกำลังจะแนะนำ ;-) เดียวกัน
Dirk Eddelbuettel

7

Boost Random จากไลบรารี Boost C ++ อาจเหมาะสำหรับคุณ นอกเหนือจาก RNG หลายประเภทแล้วยังมีการกระจายที่แตกต่างหลากหลายเช่น

  • เครื่องแบบ (ของจริง)
  • สม่ำเสมอ (หน่วยทรงกลมหรือมิติโดยพลการ)
  • Bernoulli
  • มีสองจำนวน
  • Cauchy
  • แกมมา
  • Poisson
  • ทางเรขาคณิต
  • สามเหลี่ยม
  • ที่ชี้แจง
  • ปกติ
  • lognormal

นอกจากนี้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 ที่มีคุณสมบัติประเภทและการทำงานของเมทริกซ์ที่แตกต่างหลากหลาย


ขอบคุณสำหรับทิป. บูสต์ดูเหมือนค้อนขนาดใหญ่สำหรับเล็บเล็ก ๆ ของฉัน แต่เป็นผู้ใหญ่และดูแลรักษา
JMS

ฉันไม่แน่ใจว่า boot :: math :: binomial_distribution มีฟังก์ชันเดียวกับที่นำมาใช้ใน R binom.test () สองด้าน ฉันค้นหาข้อมูลอ้างอิงและไม่พบฟังก์ชันนี้ ฉันพยายามใช้สิ่งนี้และมันก็ไม่สำคัญอะไร!
Kemin Zhou

1

มีไลบรารี C / C ++ มากมายอยู่ที่นั่นส่วนใหญ่มุ่งเน้นไปที่โดเมนปัญหาเฉพาะของ (เช่นตัวแก้ PDE) มีห้องสมุดที่ครบวงจรสองแห่งที่ฉันสามารถนึกได้ว่าคุณอาจพบว่ามีประโยชน์เป็นพิเศษเพราะพวกมันเขียนด้วยภาษา C แต่มีตัวห่องูหลามที่ดีเยี่ยมอยู่แล้ว

1) IMSL CและPyIMSL

2) trilinosและpytrilinos

ฉันไม่เคยใช้ trilinos เพราะฟังก์ชั่นใช้วิธีการวิเคราะห์เชิงตัวเลขเป็นหลัก แต่ฉันใช้ 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: สร้างหมายเลขเทียมปลอมจากการแจกแจง Cauchy
  • random_chi_squared: สร้างหมายเลขหลอกเทียมจากการแจกแจงแบบไคสแควร์
  • 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: สร้างหมายเลขเทียมปลอมจากการแจกแจง von Mises
  • random_weibull: สร้างหมายเลขปลอมจากการแจกแจงแบบ Weibull
  • Random_general_continuous: สร้างหมายเลขเทียมสุ่มจากการแจกแจงแบบต่อเนื่องทั่วไป

การกระจายที่หลากหลายต่อเนื่อง

  • Random_normal_multivariate: สร้างหมายเลขหลอกเทียมจากการแจกแจงปกติหลายตัวแปร
  • random_orthogonal_matrix: สร้างเมทริกซ์ orthogonal เทียมหรือเมทริกซ์สหสัมพันธ์
  • random_mvar_from_data: สร้างหมายเลขปลอมเทียมจากการแจกแจงหลายตัวแปรที่พิจารณาจากตัวอย่างที่กำหนด
  • Random_multinomial: สร้างหมายเลขปลอมเทียมจากการแจกแจงพหุนาม
  • Random_sphere: สร้างคะแนนหลอกเทียมในวงกลมหน่วยหรือทรงกลม K-dimension
  • random_table_twoway: สร้างตารางสองทางหลอกเทียม

สถิติการสั่งซื้อ

  • Random_order_normal: สร้างสถิติการสั่งซื้อแบบหลอกเทียมจากการแจกแจงแบบปกติมาตรฐาน
  • Random_order_uniform: สร้างสถิติการสั่งซื้อหลอกเทียมจากการแจกแจงแบบสม่ำเสมอ (0, 1)

กระบวนการทำด้วยพลาสติกแข็ง

  • random_arma: สร้างหมายเลขกระบวนการ pseudorandom ARMA
  • random_npp: สร้างหมายเลขหลอกเทียมจากกระบวนการปัวซองที่ไม่ใช่แบบเอกพันธ์

ตัวอย่างและผลการดำเนินงาน

  • Random_permutation: สร้างการเปลี่ยนลำดับแบบสุ่มเทียม
  • Random_sample_indices: สร้างตัวอย่างดัชนีปลอมแบบง่าย ๆ
  • random_sample: สร้างตัวอย่าง pseudorandom ง่ายๆจากประชากรที่ จำกัด

ฟังก์ชั่นยูทิลิตี้

  • Random_option: เลือกชุดตัวสร้างหมายเลขปลอมแบบสมมาตร (0, 1) แบบสมมาตรแบบสุ่ม
  • random_option_get: ดึงตัวกำเนิดตัวเลขแบบหลอกหลายตัว (0, 1) แบบสมนาคุณ
  • Random_seed_get: ดึงค่าปัจจุบันของเมล็ดที่ใช้ในเครื่องกำเนิดตัวเลขสุ่ม IMSL
  • random_substream_seed_get: ดึงเมล็ดพันธุ์สำหรับเครื่องกำเนิดไฟฟ้าที่มีความสอดคล้องกันซึ่งไม่ได้สับแบบที่จะสร้างตัวเลขสุ่มที่เริ่มต้นที่ 100,000 เลขที่ไกลกว่า
  • Random_seed_set: เริ่มต้นเมล็ดสุ่มเพื่อใช้ในเครื่องกำเนิดเลขสุ่ม IMSL
  • random_table_set: ตั้งค่าตารางปัจจุบันที่ใช้ในเครื่องกำเนิดแบบสับ
  • random_table_get: ดึงตารางปัจจุบันที่ใช้ในเครื่องกำเนิดแบบสับ
  • random_GFSR_table_set: ตั้งค่าตารางปัจจุบันที่ใช้ในเครื่องกำเนิด GFSR
  • random_GFSR_table_get: ดึงตารางปัจจุบันที่ใช้ในเครื่องกำเนิด GFSR
  • Random_MT32_init: เริ่มต้นตัวสร้าง Mersenne Twister 32 บิตโดยใช้อาร์เรย์
  • random_MT32_table_get: ดึงตารางปัจจุบันที่ใช้ในตัวสร้าง Mersenne Twister 32 บิต
  • random_MT32_table_set: ตั้งค่าตารางปัจจุบันที่ใช้ในตัวสร้าง Mersenne Twister 32 บิต
  • random_MT64_init: เริ่มต้นตัวสร้าง Mersenne Twister 64 บิตโดยใช้อาร์เรย์
  • random_MT64_table_get: ดึงตารางปัจจุบันที่ใช้ในตัวสร้าง Mersenne Twister 64 บิต
  • random_MT64_table_set: ตั้งค่าตารางปัจจุบันที่ใช้ในตัวสร้าง Mersenne Twister 64 บิต

ลำดับความแตกต่างต่ำ

  • faure_next_point: คำนวณลำดับ Faure แบบสับ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.