我现在有一个以特征生成的bool掩码矢量。我想使用类似于Python numpy的二进制掩码,根据True值,我得到一个子矩阵或子向量,在那里我可以进一步对它们进行一些计算。
为了在本征中实现这一点,我目前将掩码向量“转换”为包含索引的另一个向量,方法是简单地迭代掩码:
Eigen::Array<bool, Eigen::Dynamic, 1> mask = ... // E.G.: [0, 1, 1, 1, 0, 1];
Eigen::Array<uint32_t, Eigen::Dynamic, 1> mask_idcs(mask.count(), 1);
int z_idx = 0;
for (int z = 0; z < mask.rows(); z++) {
if (mask(z)) {
mask_idcs(z_idx++) = z;
}
}
// do further calculations on vector(mask_idcs)
// E.G.: vector(mask_idcs)*3 + another_vector但是,我想进一步优化它,我想知道Eigen3是否为此提供了一个更优雅的解决方案,比如vector(from_bin_mask(mask)),它可能从库优化中受益。
这里已经出现了一些问题,但是似乎没有人回答这个简单的用例(1,2)。有些人提到了select-function,它返回大小相等的向量/矩阵/数组,但我想通过掩码丢弃元素,只对较小的向量/矩阵/数组进行进一步的工作。
有没有更优雅的方法来做这件事?否则还能进行优化吗?
(我使用的是Eigen::Array-type,因为大多数计算在用例中都是按元素计算的)
发布于 2022-04-23 00:47:04
据我所知,没有使用本征方法的“现成”解决方案。但是,值得注意的是(至少对于大于或等于3.4.0的特征版本),可以使用std::vector<int>进行索引(参见本节)。因此,您编写的代码可以简化为
Eigen::Array<bool, Eigen::Dynamic, 1> mask = ... // E.G.: [0, 1, 1, 1, 0, 1];
std::vector<int> mask_idcs;
for (int z = 0; z < mask.rows(); z++) {
if (mask(z)) {
mask_idcs.push_back(z);
}
}
// do further calculations on vector(mask_idcs)
// E.G.: vector(mask_idcs)*3 + another_vector如果使用的是c++20,则可以使用使用std::ranges的替代实现,而无需使用raw for-循环:
int const N = mask.size();
auto c = iota(0, N) | filter([&mask](auto const& i) { return mask[i]; });
auto masked_indices = std::vector(begin(c), end(c));
// ... Use it as vector(masked_indices) ...我已经在编译器资源管理器中实现了一些最小的示例,以防您想要查看。老实说,我希望有一种更简单的方法从原始范围初始化std::vector,但它目前是不那么简单。因此,我建议您将代码包装到一个助手函数中,例如
auto filtered_indices(auto const& mask) // or as you've suggested from_bin_mask(auto const& mask)
{
using std::ranges::begin;
using std::ranges::end;
using std::views::filter;
using std::views::iota;
int const N = mask.size();
auto c = iota(0, N) | filter([&mask](auto const& i) { return mask[i]; });
return std::vector(begin(c), end(c));
}然后用它作为,例如,
Eigen::ArrayXd F(5);
F << 0.0, 1.1548, 0.0, 0.0, 2.333;
auto mask = (F > 1e-15).eval();
auto D = (F(filtered_indices(mask)) + 3).eval();它不像在numpy中那么干净,但是它是这样的:)
发布于 2022-02-01 09:57:44
我找到了另一种方法,它似乎比比较每个元素(如果它等于0 )更优雅。
Eigen::SparseMatrix<bool> mask_sparse = mask.matrix().sparseView();
for (uint32_t k = 0; k<mask.outerSize(); ++k) {
for (Eigen::SparseMatrix<bool>::InnerIterator it(mask_sparse, k); it; ++it) {
std::cout << it.row() << std::endl; // row index
std::cout << it.col() << std::endl; // col index
// Do Stuff or built up an array
}
}在这里,我们至少可以建立一个向量(或多个向量,如果我们有更多的维数),然后使用它“掩蔽”一个向量或矩阵。(这是取自文档的)。
因此,对于这个特定的应用程序,我们只需:
Eigen::Array<uint32_t, Eigen::Dynamic, 1> mask_idcs(mask.count(), 1);
Eigen::SparseVector<bool> mask_sparse = mask.matrix().sparseView();
int z_idx = 0;
for (Eigen::SparseVector<bool>::InnerIterator it(mask_sparse); it; ++it) {
mask_idcs(z_idx++) = it.index()
}
// do Stuff like vector(mask_idcs)*3 + another_vector但是,我不知道哪个版本对于包含数千个元素的大型掩码来说更快。
https://stackoverflow.com/questions/70926877
复制相似问题