簡體   English   中英

給定非零元素的位置,如何在 MATLAB 中創建稀疏矩陣

[英]How to create a sparse matrix in MATLAB given the locations of non-zero elements

我需要在 MATLAB 中創建具有以下要求的矩陣。 給定一個向量v ,例如[1,2,2,1,3,5,1] ,我需要形成一個矩陣:

[1 0 0 1 0 0 1;
 0 1 1 0 0 0 0;
 0 0 0 0 1 0 0;
 0 0 0 0 0 0 0;
 0 0 0 0 0 1 0]

即矩陣的第i列在第v[i]行僅包含一個非零元素(單個1 )。 如何避免循環並以有效的方式執行此操作?

其他人指出循環在這里很好。 我會指出稀疏要好得多。 你的矩陣是稀疏的,非常稀疏,所以使用稀疏的能力來解決問題,並在矩陣很大的情況下節省大量的存儲空間。

N = 3000;
v = ceil(rand(1,3000)*3000);

tic
A = zeros(N,N);
for i = 1:N
  A(v(i),i) = 1;
end
toc
Elapsed time is 0.069082 seconds.

tic
B = sparse(v,1:N,1,N,N);
toc
Elapsed time is 0.001308 seconds.

因此,如果矩陣很大,則時間上存在巨大差異。

空間呢?

whos A B
  Name         Size                 Bytes  Class     Attributes

  A         3000x3000            72000000  double              
  B         3000x3000               72008  double    sparse    

其他方面的矩陣是相同的。

sum(sum(abs(A - B)))
ans =
     0

稀疏矩陣占用的空間非常小,您可以像使用任何其他矩陣一樣使用它。

使用 MATLAB 的功能。

首先,我必須給出我的標准免責聲明,盡管普遍認為在 MATLAB 中通常應該避免循環,但在 MATLAB 的現代版本中,循環實際上變得更加高效,這在很大程度上要歸功於 JIT 加速器。 所以,當然,對你的代碼進行基准測試以確定循環是否真的是一個瓶頸。

也就是說,我關於如何在沒有循環的情況下解決這個問題的第一個想法是索引到一個單位矩陣(如下所示)。

identityMatrix = eye(max(v(:)));
result = identityMatrix(:,v);

我認為這是一個漂亮、干凈的解決方案; 但是,我並不知道這是顯著比使用一個循環更加有效。 作為比較,我使用循環實現了以下解決方案:

numRows = max(v(:));
numCols = length(v);
result = zeros(numRows,numCols);

for i=1:numCols
    result(v(i),i) = 1;
end

根據我的測試運行,對於v不是很長的那些情況,頂部(無循環)解決方案似乎通常更快。 然而,當v包含許多元素(例如 >100)時,我實際上看到了循環解決方案擊敗替代方案的平均時間。

m = max(v);
n = length(v);
M = zeros(m, n);
M([0:(n-1)]*m + v) = 1;
>> v =  [1,2,2,1,3,5,1];
>> a = zeros(max(v), length(v));
>> a((0 : size(a, 1) : numel(a) - 1) + v) = 1

a =

     1     0     0     1     0     0     1
     0     1     1     0     0     0     0
     0     0     0     0     1     0     0
     0     0     0     0     0     0     0
     0     0     0     0     0     1     0

這與在神經網絡分配(第 5 周 - Andrew NG ML 課程的手寫數字識別)中創建目標向量所需的步驟非常相似。 我們必須為單個訓練輸出創建一個 10 X 1 大小的向量,比如 y 的第 i 個輸出。 如果 y 中的第 i 個訓練輸出為 2,則向量化的第 i 個輸出為 [0 1 0 0 0 0 0 0 0 0]'。 因此,對於 5000 個訓練示例,我們需要 5000 個向量。

廢話不多說,代碼如下:


>> v =  [1,2,2,1,3,5,1];
>> v_vec = (1:5)==v';
>> v_vec
v_vec =

  1  0  0  0  0
  0  1  0  0  0
  0  1  0  0  0
  1  0  0  0  0
  0  0  1  0  0
  0  0  0  0  1
  1  0  0  0  0

>> v_vec'
ans =

  1  0  0  1  0  0  1
  0  1  1  0  0  0  0
  0  0  0  0  1  0  0
  0  0  0  0  0  0  0
  0  0  0  0  0  1  0

v_vec' 是所需的輸出。 一個有用的鏈接: https : //www.ee.columbia.edu/~marios/matlab/Matlab%20Tricks.pdf

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM