【问题标题】:Drawing a random non-zero element from a sparse matrix从稀疏矩阵中绘制随机非零元素
【发布时间】:2012-02-14 23:52:21
【问题描述】:

我有一个非常大的稀疏逻辑矩阵。我想从中绘制随机非零元素,而不将其所有非零元素存储在单独的向量中(例如,通过使用 find 命令)。有没有简单的方法可以做到这一点?

目前我正在实施拒绝抽样,它正在绘制一个随机元素并检查它是否非零。但当非零元素的比例较小时,效率不高。

【问题讨论】:

  • 我认为 find 对稀疏矩阵进行了优化,如果你担心的话。
  • 我担心的是内存而不是运行时间。但是,即使在运行时间方面,如果您只想对几个项目进行采样,find 也不是那么高效。
  • 使用nonzeros 应该比find 更节省内存,因为您不存储行和列索引。

标签: matlab


【解决方案1】:

如果您想选择随机位置,稀疏逻辑矩阵并不是您的数据非常实用的表示。拒绝抽样和find 是唯一对我有意义的两种方式。以下是您如何有效地执行它们(假设您想要获得 4 个随机位置):

%# using find
idx = find(S);
%# draw 4 without replacement
fourRandomIdx = idx(randperm(length(idx),4));
%# draw 4 with replacement
fourRandomIdx = idx(randi(1,length(idx),4));
%# get row, column values
[row,col] = ind2sub(size(S),fourRandomIdx);



%# using rejection sampling
density = nnz(S)/prod(size(S));
%# estimate how many samples you need to get at least 4 hits
%# and multiply by 2 (or 3)
n = ceil( 1 / (1-(1-density)^4) ) * 2;
%# random indices w/ replacement
randIdx = randi(1,n,prod(size(S)));
%# identify the first four non-zero elements
[row,col] = find(S(randIdx),4,'first');

【讨论】:

    【解决方案2】:

    具有 nnz 个非零元素的 n x m 矩阵需要 nnz + n + 1 个整数来存储其非零条目的位置。对于逻辑矩阵,不需要存储非零条目的值:这些都是真的。相应地,您最好将逻辑稀疏矩阵与 n 和 m 一起转换为其非零条目的线性索引列表,这仅需要 nnz + 2 个整数的存储空间。从这些(和 ind2sub)中,您可以轻松地重建与您在 1..nnz 范围内使用 randi 随机选择的任何非零条目相对应的下标

    【讨论】:

    • 我的应用程序也需要从零条目中采样。因此,我维护稀疏矩阵以便能够检查随机条目的值。使用您的索引解决方案,不可能对零元素进行采样。
    • 你能澄清你的目标吗?您的原始帖子表明您要绘制“随机非零元素”;但是,在您的评论中,您似乎还想从零条目中提取。你能澄清一下吗?即,当您从矩阵中随机抽取时,您是从所有条目中抽取,还是仅抽取一些(如果是,是哪个)?当您绘制时,您想要什么(例如,索引,或者索引和元素值,或者......)?最后,这个矩阵是作为随机矩阵出现的,还是由其他东西构建而成的,这样它的表示在你的控制范围内?
    【解决方案3】:

    find 是获取稀疏矩阵中非零元素的标准接口。看看这里http://www.mathworks.se/help/techdoc/math/f6-9182.html#f6-13040

    [i,j,s] = find(S)
    

    find 返回向量 i 中非零值的行索引、向量 j 中的列索引以及向量 s 中的非零值本身。

    无需获取 s。只需在 i,j 中选择一个随机索引。

    【讨论】:

    • 也许我的观点不够清楚。我不想使用 find 因为我必须将索引存储在一个单独的向量中(在您的示例中为 i 和 j ),这将非常占用内存。将其与作为稀疏逻辑矩阵的稀疏矩阵本身进行比较。
    【解决方案4】:

    通过以 3 列格式表示条目,也就是坐标列表(i、j、值),您可以简单地从列表中选择项目。为此,您可以使用原始方法创建稀疏矩阵(即sparse() 的前体),或使用find 命令,例如[i,j,s] = find(S);

    如果您不需要这些条目,而您似乎不需要,您可以提取ij

    如果由于某种原因,您的矩阵很大并且您的 RAM 限制很严重,您可以简单地将矩阵划分为多个区域,并让选择给定子矩阵的概率与非零元素的数量成正比(使用nnz)在该子矩阵中。您甚至可以将矩阵分成单独的列,其余的计算是微不足道的。注意:通过将sum 应用于矩阵,您可以获得每列的计数(假设您的条目只有 1 秒)。

    通过这种方式,您甚至不必为拒绝采样而烦恼(在这种情况下,这对我来说似乎毫无意义,因为 Matlab 知道所有非零条目的位置)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-12
      • 1970-01-01
      • 1970-01-01
      • 2017-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多