Indexing Matrices Matlab - matlab

I'm trying to compute two matrices , one of which is 400*2 and the other being 20*20. The first one contains x and y coordinates of 400 points and the second being another 400 points with x's being 2nd(i,i) and y's being (i,k) both i and k's are 20 number counters.I'm trying to compute the distances between those 2 matrix points which would give me 400*400 matrix. The code i'm using is ;
for i=1:20
for j=1:400
for k=1:20
L(j,)=sqrt((C(j,1)-M(i,i))^2+(C(j,2)-M(k,i))^2);
end
end
end
C being the first matrix and M being the second. Now i know i made it sound a little hard but the trouble is i cant find a counter to give to L(j, ) that part. If you guys have any idea please do tell...
Edit: Well first of all think there is 2 point vectors. X's being -0.95:0.1:0.95 and y's are the same. M vector is that all of the x's paired with a Y so it would make 20*20 matrix or a 400*2 however i could not make it work like a 400*2 so have gone with 20*20.The matrix is a little hard for me to do so my indexing of M shows that.If you got a better way to pair them i would appreciate it as well.
My matrix looks like this ;
-0.95 -0.85 -0.75...
-0.95 -0.85 -0.75 ...
.
.
.

The above code should be very slow... Using a lot of for-loop is not "matlab-style"
What I would do is:
Mdiag=repmat(diag(M)',20,1);
L=pdist2(C,[Mdiag(:) M(:)]);
The first line extracts the diagonal terms of M and repeat them.
After that [Mdiag(:) M(:)] is a standard form of your second set of points.
pdist2 is a function that compute all the pairwise distances.

Does it matter what order they are in? I am assuming it doesn't, so long as you know what that order is. I'd use this:
for i=1:20
for j=1:400
for k=1:20
L(j,(i-1)*20+k) = sqrt((C(j,1)-M(i,i))^2+(C(j,2)-M(k,i))^2);
end
end
end

Related

covariance of a 400 50X50 matrix of matlab

I want to calculate covariance of 400 50 X 50 matrices using loop so when I tried..
for i=t-9:t+59
for j=r-9:r+59
a(:,:,p)=vidFrames2(i:(i+49),j:(j+49));
b(:,:,p)=cov3d(double(a));
p=p+1;
end
end
this code I got error "Assignment has more non-singleton rhs dimensions than non-singleton subscripts"
but when i want to remove this error by squeeze function in this code,
b(p,:)=cov3d(squeeze(double(a)));
I got "Subscripted assignment dimension mismatch."
how can I calculate covariance of 3d matrix....the cov3d function is-
function xy = cov3d(x)
[m,n,r] = size(x);
if m==1
x=zeros(n,n,r,class(x));
else
xc=bsxfun(#minus,x,sum(x,1)/m);
for i=1:r
xci=xc(:,:,i);
xy(:,:,i)=xci'*xci;
end
xy=xy/(m-1);
end
actually i wanted 400 number of covariance matrices stored in a variable.after this change i only get one covariance matrix.actually i am working on a frame where i am storing the initial coordinate values in i and j of a 50 X 50 matrix. then i want to get the pixel values of the 10 X 10 neighbourhood in the form of 50 X 50 matix. that means if i entered the initial coordinate as (100,100), then i want to get pixel values stored within region (91,91)(91,141)(141,91)(141,141).then store the covariance value of this matix. then again it will find the pixel values of the region (92,91),(142,91)(92,141),(142,141)and so on and covers the whole area..so if i cover the whole area then i think i will get total 400 matrices.and i want to store the covariance value of all the regions,.. today i changed the upper limit of the for loops to i=t-9:t+60 and j=r-9:r+60 but i did not get 400 covariance matrices
A few comments about your code:
cov3d is designed to return a 3D matrix, where the input is also a 3D matrix that calculates the covariance for each slice in this 3D matrix. From your code, the outer for loops (indices i and j) go from t-9 to t+59 in steps of 1 for each variable. As such, the pair of loops will execute ((t+59) - (t-9) + 1)^2 = 69^2 = 4761 times. I'm assuming that at each iteration, you are extracting a 2D matrix located at a which is why you initially said 400 times. You basically want to extract 400 matrices, but you are actually extracting 4761 matrices. Make sure a is properly declared to account for this many elements.
a(:,:,p)=vidFrames2(i:(i+49),j:(j+49)); accesses one slice, yet b(:,:,p)=cov3d(double(a)); is accessing the entire 3D matrix of a. Therefore, you will get a 3D matrix as the output of cov3d, yet you are trying to assign this to a single slice in b. What you should probably do is create your a matrix first, then make one call to cov3d when you're done.
Therefore, try changing your code to this:
%// Create `a` matrix first
for i=t-9:t+59
for j=r-9:r+59
a(:,:,p)=vidFrames2(i:(i+49),j:(j+49));
p=p+1;
end
end
%// Now call cov3d
b = cov3d(double(a));
Hopefully this will work the way you intended your code to originally work.

How can I calculate dyadics in matlab without using for loops?

I was wondering if someone could help me with my problem.
Let say that I have the coordinates of MxN vectors in a tensor r of dimensions [M,N,3]. I would like to save in a 3M-by-3N block matrix all dyadic products r_0'*r_0, where r_0 is the vector r_0 = r(m,n,:) for some m and n, and I would like to do this without using for loops.
If haven't explain myself correctly, here is an example code that shows what I would like to obtain (but using for loops, of course):
N=10;
M=5;
r=rand(M,N,3);
Dyadic=zeros(3*M,3*N);
for m=1:M
a1=3*m-2;
a2=3*m;
for n=1:N
b1=3*n-2;
b2=3*n;
aux(3)=r(m,n,3);
aux(2)=r(m,n,2);
aux(1)=r(m,n,1);
Dyadic(a1:a2,b1:b2)=transpose(aux)*aux
end
end
Thanks in advance!
You need to use bsxfun(#times and then re-arrange elements to have the desired output -
%// Get the multipliication result
mat_mult = bsxfun(#times,permute(r,[1 2 4 3]),r);
%// OR if you would like to keep mat_mult as 3D that could be potentially faster -
%// mat_mult = bsxfun(#times,reshape(r,[],3),permute(reshape(r,[],3),[1 3 2]));
%// Re-arrange elements to have them the way you are indexing in nested loops
Dyadic = reshape(permute(reshape(mat_mult,M,N,3,[]),[3 1 4 2]),M*3,N*3);
The major play about this solution is really the re-arrangement of elements after we have the multiplication result.
Quick runtime tests with the input r as 1000 x 1000 x 3 sized array, show that this bsxfun based approach gives over 20x speedup over the nested loop code listed in the question!

Remove duplicates in correlations in matlab

Please see the following issue:
P=rand(4,4);
for i=1:size(P,2)
for j=1:size(P,2)
[r,p]=corr(P(:,i),P(:,j))
end
end
Clearly, the loop will cause the number of correlations to be doubled (i.e., corr(P(:,1),P(:,4)) and corr(P(:,4),P(:,1)). Does anyone have a suggestion on how to avoid this? Perhaps not using a loop?
Thanks!
I have four suggestions for you, depending on what exactly you are doing to compute your matrices. I'm assuming the example you gave is a simplified version of what needs to be done.
First Method - Adjusting the inner loop index
One thing you can do is change your j loop index so that it only goes from 1 up to i. This way, you get a lower triangular matrix and just concentrate on the values within the lower triangular half of your matrix. The upper half would essentially be all set to zero. In other words:
for i = 1 : size(P,2)
for j = 1 : i
%// Your code here
end
end
Second Method - Leave it unchanged, but then use unique
You can go ahead and use the same matrix like you did before with the full two for loops, but you can then filter the duplicates by using unique. In other words, you can do this:
[Y,indices] = unique(P);
Y will give you a list of unique values within the matrix P and indices will give you the locations of where these occurred within P. Note that these are column major indices, and so if you wanted to find the row and column locations of where these locations occur, you can do:
[rows,cols] = ind2sub(size(P), indices);
Third Method - Use pdist and squareform
Since you're looking for a solution that requires no loops, take a look at the pdist function. Given a M x N matrix, pdist will find distances between each pair of rows in a matrix. squareform will then transform these distances into a matrix like what you have seen above. In other words, do this:
dists = pdist(P.', 'correlation');
distMatrix = squareform(dists);
Fourth Method - Use the corr method straight out of the box
You can just use corr in the following way:
[rho, pvals] = corr(P);
corr in this case will produce a m x m matrix that contains the correlation coefficient between each pair of columns an n x m matrix stored in P.
Hopefully one of these will work!
this works ?
for i=1:size(P,2)
for j=1:i
Since you are just correlating each column with the other, then why not just use (straight from the documentation)
[Rho,Pval] = corr(P);
I don't have the Statistics Toolbox, but according to http://www.mathworks.com/help/stats/corr.html,
corr(X) returns a p-by-p matrix containing the pairwise linear correlation coefficient between each pair of columns in the n-by-p matrix X.

Duplicating a 2d matrix in matlab along a 3rd axis MANY times

I'm looking to duplication a 784x784 matrix in matlab along a 3rd axis. The following code seems to work:
mat = reshape(repmat(mat, 1,10000),784,784,10000);
Unfortunately, it takes so long to run it's worthless (changing the 10,000s to 1000 makes it take a few minutes, and using 10,000 makes my whole machine freeze up practically). is there a faster way to do this?
For reference, I'm looking to use mvnpdf on 10,000 vectors each of length 784, using the same covariance matrix for each. So my final call looks like
mvnpdf(X,mu,mat)
%size(X) = (10000,784), size(mu) = (10000,784), size(mat) = 784,784,10000
If there's a way to do this that's not repeating the covariance matrix 10,000 times, that'd be helpful too. Thanks!
For replication in more than 2 dimensions, you need to supply the replication counts as an array:
out = repmat(mat,[1,1,10000])
Creating a 784x784 matrix 10,000 times isn't going to take advantage of the vectorization in MATLAB, which is going to be more useful for small arrays. Avoiding a for loop also won't help too much, given the following:
The main speedup you can gain here is by computing the inverse of the covariance matrix once, and then computing the pdf yourself. The inverse of sigma takes O(n^3), and you are needlessly doing that 10,000 times. (Also, the square root determinant can be precomputed.) For reference, the PDF of the multivariate normal distribution is computed as follows:
http://en.wikipedia.org/wiki/Multivariate_normal_distribution#Properties
Better to just compute the inverse once, and then compute z = x - mu for each value, then doing z'Sz for each pdf value, and applying a simple function and a constant. But wait! You can vectorize that, too.
I don't have MATLAB in front of me, but this is basically what you need to do, and it'll run in an instant.
s = inv(sigma);
c = -0.5*log(det(s)) - (k/2)*log(2*pi);
z = x - mu; % 10000 x 784 matrix
ans = exp( c - 0.5 .* dot(z*s, z, 2) ); % 10000 x 1 vector

Vectorizing code

I dont quite get the vectorizing way of thinking of matlab, mostly due to the simple examples provided in the documentation, and i hope someone can help me understand it a little better.
So, what i'm trying to accomplish is to take a sample of NxN from a matrix of ncols x nrows x ielements and compute the average for each ielement and store the maximum of the averages. Using for loops, the code would look like this:
for x = 1+margin : nrows-margin
for y = 1+margin : ncols-margin
for i=1:ielem
% take a NxN sample
sample = input_matrix(y-margin:y+margin,x-margin:x+margin,i)
% compute the average of all elements
result(i) = mean2(sample);
end %for i
% store the max of the computed averages
output_matrix(y,x)=max(result);
end %for y
end %for x
can anyone do a good vectorization of this example of a situation ? T
First of all, vectorization is not as important as it once was, due to enhancements in compiling the code before it is ran, but it's still a very common practice and can lead to some enhancements. Older Matlab version executed one line at a time, which would leave a for loop much slower than a vectorized version of the same code.
The part of your matrix that could be vectorized is the inner more for loop. I'll show a simple example of what you are trying to do, I'll let you take the example and put it into your code.
input=randn(5,5,3);
max(mean(mean(input,1),2))
Basically, the inner two mean take the mean of the input array, and the outer max will find the maximum value over the range. If you want, you can break it out step by step, and see what it does. The mean(input,1) will take the mean over the first dimension, mean(input,2) over the second, etc. After the first two means are done, all that is left is a vector, which the max function will easily work. It should be noted that the size of the vector pre-max is [1 1 3], the dimensions are preserved when doing this operation.