How to create a sparse matrix in MATLAB given the

2020-07-24 04:01发布

I need to create matrix in MATLAB with the following requirement. Given a vector v, for example, [1,2,2,1,3,5,1], I need to form a matrix:

[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.e. the matrix's ith column contains only one non-zero element (a single 1) at row v[i]. How can I avoid a loop and do this in an efficient way?

标签: matlab matrix
5条回答
欢心
2楼-- · 2020-07-24 04:14

Others are pointing out that loops are fine here. I'll point out that sparse is FAR better. Your matrix is sparse, very much so, so use the capability of sparse to solve the problem, and save a vast amount of storage in case that matrix is large.

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.

So if the matrix is at all large, there is a huge difference in time.

How about space?

whos A B
  Name         Size                 Bytes  Class     Attributes

  A         3000x3000            72000000  double              
  B         3000x3000               72008  double    sparse    

The matrices are identical otherwise.

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

The sparse matrix takes very little space, and you can use it just like any other matrix.

Use the capabilities of MATLAB.

查看更多
时光不老,我们不散
3楼-- · 2020-07-24 04:14

First, I have to give my standard disclaimer, that despite the commonly held notion that loops should generally be avoided in MATLAB, loops have actually become much more efficient in modern releases of MATLAB, in large part, due to the JIT accelerator. So, certainly, benchmark your code to determine if loops actually are a bottleneck.

That said, my first thought on how to approach this problem without a loop was to index into an identity matrix (as shown below).

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

I think that this is a nice, clean looking solution; however, I don't necessarily know that it is significantly more efficient than using a loop. As a point of comparison, I implemented the following solution using a loop:

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

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

Based on my test runs, it looks like the top (no loop) solution is generally faster for those cases where v is not very long. However, when v contains many elements (>100 for example), I was actually seeing average times where the loop solution was beating the alternative.

查看更多
我只想做你的唯一
4楼-- · 2020-07-24 04:25
>> 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楼-- · 2020-07-24 04:27
m = max(v);
n = length(v);
M = zeros(m, n);
M([0:(n-1)]*m + v) = 1;
查看更多
Lonely孤独者°
6楼-- · 2020-07-24 04:40

This is very similar to the step required in creating a target vector in Neural Network Assignment (Week 5- Handwritten Digit Recognition from Andrew NG ML course). We had to create a vector of 10 X 1 size for a single training output say ith output of y. If the ith training output in y is 2, the vectorized ith output was [0 1 0 0 0 0 0 0 0 0]'. So, For 5000 training examples, we required 5000 vectors.

Without much ado, The code is :


>> 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' is the desired output. A useful link : https://www.ee.columbia.edu/~marios/matlab/Matlab%20Tricks.pdf

查看更多
登录 后发表回答