【问题标题】:efficiently sample from modified arma::vec object从修改后的 arma::vec 对象中高效采样
【发布时间】:2018-06-27 17:38:39
【问题描述】:

我正在使用 Rcpp 来加速一些 R 代码。但是,我真的在与类型作斗争——因为这些在 R 中是外来的。这是我正在尝试做的简化版本:

#include <RcppArmadillo.h>
#include <algorithm>
//[[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;

// [[Rcpp::export]]
NumericVector fun(SEXP Pk, int k, int i, const vec& a, const mat& D) {
  // this is dummy version of my actual function - with actual arguments.;
  // I'm guessing SEXP is going to need to be replaced with something else when it's called from C++ not R.;
  return D.col(i);
}

// [[Rcpp::export]]
NumericVector f(const arma::vec& assignment, char k, int B, const mat& D) {
    uvec k_ind = find(assignment == k);
    NumericVector output(assignment.size());  // for dummy output.

    uvec::iterator k_itr = k_ind.begin();

    for(; k_itr != k_ind.end(); ++k_itr) {
        // this is R code, as I don't know the best way to do this in C++;
        k_rep = sample(c(assignment[assignment != k], -1), size = B, replace = TRUE);

        output = fun(k_rep, k, *k_itr, assignment, D);
        // do something with output;
    }

    // compile result, ultimately return a List (after I figure out how to do that.  For right now, I'll cheat and return the last output);
    return output;
}

我正在努力解决的部分是assignment 的随机抽样。我知道sample已经在Rarmadillo中实现了。但是,我可以看到两种方法,但我不确定哪种方法更有效/可行。

方法一:

  • 制作assignment 值的表格。将 assignment == k 替换为 -1 并将其“计数”设置为 1。
  • 从“名称”表中抽取样本,概率与计数成正比。

方法二:

  • assignment 向量的相关子集复制到一个新向量中,并为-1 增加一个点。
  • 从复制的向量中以相同的概率采样。

我想说方法 1 会更有效,除了 assignment 当前的类型为 arma::vec,我不确定如何从中制作表格 - 或者有多少成本将其转换为更兼容的格式。我想我可以实现方法 2,但我希望避免昂贵的副本。

感谢您提供的任何见解。

【问题讨论】:

  • 可以直接在Rcpp中使用sample。见本页底部:teuder.github.io/rcpp4everyone_en/…
  • 我发现 R-C++ 混合相当混乱。您能否提供一个仅包含示例输入和预期输出的 R 解决方案?
  • @MelissaKey:我建议您重新阅读有关 RcppArmadillo sample 函数的帖子,您可以在 Rcpp Gallery 找到该函数,然后重新处理您的问题。目前,我们真的无法为您提供帮助。
  • 感谢您的尝试。我正在解决它 - 当我提出更具体的问题时,我无法通过您提供的大量资源找到答案,我会问他们。

标签: r rcpp armadillo


【解决方案1】:

许多变量声明与您所做的赋值不一致,例如 assignment = k 是无法比较的,因为赋值具有实值并且 k 是一个字符。由于queston写得不好,我可以随意更改变量类型。这个编译..

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>

// [[Rcpp::export]]
arma::vec fun(const Rcpp::NumericVector& Pk, int k, unsigned int i, const arma::ivec& a, const arma::mat& D)
{
  return D.col(i);
}

// [[Rcpp::export]]
Rcpp::NumericMatrix f(const arma::ivec& assignment, int k, unsigned int B, const arma::mat& D) 
{
  arma::uvec k_ind = find(assignment == k);
  arma::ivec KK = assignment(find(assignment != k));
  //these 2 row are for KK = c(assignment[assignment != k], -1)  
  //I dont know what is this -1 is for, why -1 ? maybe you dont need it.
     KK.insert_rows(KK.n_rows, 1);
     KK(KK.n_rows - 1) = -1;

  arma::uvec k_ind_not = find(assignment != k);
  Rcpp::NumericVector k_rep(B);
  arma::mat output(D.n_rows,k_ind.n_rows);  // for dummy output.

  for(unsigned int i =0; i < k_ind.n_rows ; i++) 
  {
    k_rep = Rcpp::RcppArmadillo::sample(KK, B, true);

    output(arma::span::all, i) = fun(k_rep, k, i, assignment, D);
    // do something with output;
  }

  // compile result, ultimately return a List (after I figure out how to do that.  For right now, I'll cheat and return the last output);
  return Rcpp::wrap(output);
}

这不是优化的(因为问题是假的),这写得不好,因为我认为 R 在搜索向量的索引时会足够快(所以在 R 中执行此操作并在 Rcpp 中实现仅乐趣).. .在这里浪费时间没有用,还有其他问题需要在 Rcpp 中实现求解器,而不是这个搜索的东西...... 但这不是一个有用的问题,因为您对算法的要求比对函数签名的要求更多

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2018-08-01
    • 1970-01-01
    相关资源
    最近更新 更多