Matlab 中的稀疏随机矩阵,其值范围不同于 [0,1]

Sparse random matrix in Matlab with values in different range than [0,1]

如何在 Matlab 中创建一个值范围不同于默认 [0,1] 的稀疏随机矩阵,比如 [-1,1]?我尝试过但显然不起作用的两件事是:

p = 2 * sprand(5,5,0.1) - 1

哪个returns

>> p = -1.0000 -1.0000 -1.0000 -1.0000 -1.0000
       -1.0000 -1.0000 -1.0000 -1.0000 -1.0000  
       -1.0000 -1.0000 -1.0000 -1.0000 -1.0000
       -1.0000 -1.0000 -0.4850 -1.0000 -1.0000
        0.6814 -1.0000 -1.0000 -1.0000 -1.0000

p = ceil(sprand(5,5,0.1));
p(find(p)) = 2 * rand(5) - 1;
full(p)

哪个returns

>> ans =          0  0       0  0  0 
                  0  0       0  0  0
                  0  0       0  0  0
                  0  0  0.3112  0  0
             0.3112  0       0  0  0

我想要一个不涉及任何循环且仅使用矩阵操作或内置 Matlab 函数的解决方案。

其实我想出了一个办法:

>> p = sprand(5,5,0.1)
>> d = 2 * rand(5) - 1
>> p(find(p)) = d(find(p))

这使用 sprand 生成稀疏结构,randthe canonical way 移动随机值的范围以获得值在 [-1] 范围内的 5x5 矩阵,1],然后 find 函数找到具有非零值的稀疏矩阵的线性索引,并使用这些索引从随机矩阵中分配相应的值。

我看到的唯一缺点是您仍然必须生成完整的随机矩阵,所以我仍然想知道如何更有效地做到这一点。

没有必要丢弃 sprand 中的均匀随机变量并分配第二个完整的随机值矩阵。我会这样做 logical indexing and nonzeros:

p = sprand(5,5,0.1);
p(p~=0) = 2*nonzeros(p)-1;

或者,您也可以这样做(在使用 R2015a 进行的一些简单测试中,对于大型阵列来说速度会慢一些):

p = sprand(5,5,0.1);
ne0 = (p~=0);
p(ne0) = 2*p(ne0)-1;

在非常旧的 Matlab 版本中,稀疏数组可能不支持逻辑索引。在这种情况下,您可以使用 find:

p = sprand(5,5,0.1);
p(find(p)) = 2*nonzeros(p)-1;

最后,您还可以使用 randperm, ind2sub, rand and sparse:

实现您自己的功能
function R = sprand11(m,n,density)
%SPRAND11  Sparse random matrix distributed on the interval (-1,1)
idx = randperm(m*n,round(density*m*n));     % Find random indices
[i,j] = ind2sub([m n],idx);                 % Convert linear indices subscripts
R = sparse(i,j,2*rand(1,numel(idx))-1,m,n); % Create sparse random matrix

我不确定这是否正是 sprand 在引擎盖下实现的方式,但它应该接近。它的速度也是上述解决方案的两倍。


所有这些选项都避免生成完整的 M×N 矩阵或将 p 转换为完整矩阵然后再转换回稀疏矩阵。如果你不介意临时创建一个大的全矩阵,fasted方法(假设你有足够的内存)可能是这样的:

function R = sprand11(m,n,density)
idx = randperm(m*n,round(density*m*n)); % Find random indices
R = zeros(m,n);
R(idx) = 2*rand(1,numel(idx))-1;        % Create random matrix
R = sparse(R);                          % Convert to sparse