【问题标题】:Best way to transform an array of ints into a bitset representation in C++?将整数数组转换为 C++ 中的位集表示的最佳方法?
【发布时间】:2020-05-09 20:13:33
【问题描述】:

我看到过一些关于该主题的类似问题,但我对编程比较陌生,无法理解解决方案中使用的某些语言。

假设我有 2 个有限集 A,B 表示为数组,其中:

int A[2] = {1, 3};
int B[2] = {1, 2};

我想要代表 A 和 B 的位集(列向量 V)。

    v1 v2
(1) 1, 1
(2) 0, 1
(3) 1, 0

这样我可以轻松地对行 (k) 求和,并获得值 k 在我的所有集合 A_1 到 A_n 中出现的次数。

我正在寻找最快的方法来做到这一点。我可以粗略地想象我如何首先初始化一个位向量矩阵(将每个值设置为 0)然后循环遍历每个集合 A_i,将我的矩阵的相应条目设置为 1,但是这个解决方案似乎没用,因为我仍然必须遍历每个集合 A_i 中的每个元素。

我试图避免遍历每个集合的每个元素,而是通过对位行求和来获得出现次数,但我无法弄清楚如何以高效的方式优雅地进行这种转换。

动机:我正在尝试实现 ID3 决策树算法,并尝试使用位向量来计算标签的比例以进行熵计算。

【问题讨论】:

  • 出于某种原因,“假设我有 2 个 finite 集”让我崩溃了。甚至不用看名字就知道这是一个数学家:D
  • 目前尚不清楚您希望如何通过执行 less 工作来解决此问题,而不是至少读取每个集合的每个元素至少一次。除非集合元素中有一些您没有告诉我们的结构,否则如果您不允许查看它们的所有元素,则处理 AB 中的所有信息是非常不可能的。也许添加有关如何生成/构建AB 的信息会有所帮助? (PS:我认为你在第一个 sn-p 中有错字)。
  • 如果您所追求的只是每个元素的出现次数,为什么不使用(散列)映射而不是几个位向量呢?您仍然必须检查每个 set 元素一次(见上文),但不是在事后对位求和,而是可以在地图中增加一个计数器......或者,由于您的值看起来很密集,一个简单的数组?
  • 数学评论让我大吃一惊,哈哈。我同意,如果不至少查看每个元素一次,就不清楚如何做到这一点。我试图在线跟踪算法的实现,在我看来,作者似乎在暗示有一种方法可以在不检查每个元素的情况下转换表示。它来自以下 pdf:mltrain.cc/wp-content/uploads/2017/10/ryan-curtin.pdf ... 在幻灯片 139 上,他似乎在暗示这是可能的
  • @mathsterjedi 实际上,如果您没有关于如何构造集合的其他信息,那么如果不迭代集合就不可能做到这一点。会怎么样?如果您无法查看容器包含的内容,则无法描述容器的内容(就像我要求您描述不透明的黑匣子内的内容一样,没有任何其他信息,您无法猜测里面的内容描述它,除非你是上帝:))。

标签: c++ machine-learning data-mining bitset bitvector


【解决方案1】:

演示中的关键是,您不是为了从它们构建位集而明确地形成集合,而是构造位集而不是集合。

简而言之,你有

std::vector<double> unsortedDataInRow(numDataInRow) = ...;
std::vector<int> labels(numLabels) = ...;

然后你得到

std::vector<unsigned> sortedIndices = getSortedIndices(unsortedDataInRow);

以便对unsortedDataInRow[sortedIndices[i]] 进行排序。但不是从他们那里构建std::vector&lt;int&gt; sortedLabels,而是填写一个

std::vector<std::vector<bool>> bitsets(numLabels, std::vector<bool>(numDataInRow));
// this gets zero-initialized

这样bitsets[label][i] == (unsortedLabels[sortedIndices[i]] == label):

for (auto sortedIndex : sortedIndices)
  bitsets[unsortedLabels[sortedIndices]][sortedIndex] = true;

这有助于提高性能,因为您(可能)在InfoGain 中进行标签计数(即确定P(c),然后通过popcnt 比通过counts[labels[i]]++; 更快地完成)比您执行以上。

请注意,这只是一个草图 - std::vector&lt;bool&gt; 没有内置方法来获取 popcnt。您必须希望您的编译器能够识别手写的。或者,使用boost::dynamic_bitset,或其他一些库,或手写的。

【讨论】:

  • 这也是我的怀疑,但我并不清楚。我已将其投票为正确答案。感谢您抽出宝贵时间!
猜你喜欢
  • 2011-02-09
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 2023-03-18
相关资源
最近更新 更多