Vectorizing Arithmetic Operations - matlab

I am trying to improve the performance of my code by converting some iterations into matrix operations in Matlab. One of these is the following code and I need to figure out how can I avoid using loop in the operation.
Here gamma_ic & bow are two dimensional matrices.
c & z are variables set from outer iterations.
for z=1:maxNumber,
for c=1:K,
n = 0;
for y2=1:number_documents,
n = n+(gamma_ic(y2,c)*bow(y2,z));
end
mu(z,c) = n / 2.3;
end
end
Appreciate your assistance.
Edit. Added The loop for c and z. The iteration goes on till the maximum indices in gamma_ic & bow. Added mu which is another two dimensional matrix to show usage of n.

This should work for you to get mu, which seems to be the desired output -
mu = bow(1:number_documents,1:maxNumber).'*gamma_ic(1:number_documents,1:K)./2.3

Related

MATLAB Matrix Multiply Code efficiency

I am using MATLAB to prototype a few matrix multiply techniques and compare efficiency. Eventually, I will move the prototype codes to C. It is for a homework assignment where we need to write an efficient matrix multiply routine (by being aware of cache size, locality, etc.).
I am curious about the efficiency differences between these two very similar loops:
Matrix Multiply Loop 1
- sum over columns of A times elements of B -> column of C
function [C] = dgemm_naivepe( A,B,C,n )
for j=1:n
tempcol=zeros(n,1);
for k=1:n
for i=1:n
tempcol(i)=tempcol(i)+A(i+(k-1)*n)*B(k+(j-1)*n);
end
end
for k=1:n
C(k+(j-1)*n)=tempcol(k);
end
end
end
Matrix Multiply Loop 2
- sum over columns of A times elements of B -> column of C
function [C] = dgemm_naivepe( A,B,C,n )
for j=1:n
for k=1:n
for i=1:n
C(i+(j-1)*n)=C(i+(j-1)*n)+A(i+(k-1)*n)*B(k+(j-1)*n);
end
end
end
end
After several test runs of various matrix sizes, I found that Loop 1 is faster than Loop 2. Could someone help me understand why this is?
edit: As you can see, the matrices are stored as 1D arrays in column major ordering.

How to replace multiple values in a matrix in matlab

I'm trying to turn N number of zeros into a "1". My code works to change only one zero at a time. What is the best way to simultaneously change the zeros into a "1" N number of times?
N=4;
board=zeros(N);
board(randi(numel(board)))=1
Thank you
Edit:
N=4;
board=zeros(N);
x=1;
while (x<=N)
board(randi(numel(board)))=1;
x=x+1;
end
Would it be possible to get this to work? It's not giving me an error, but it's not giving me an output either...
I am suggesting a small improvement over atru's answer. All you need to do is this:
N=4;
board=zeros(N);
board(randperm(numel(board), N)) = 1;
Here randperm will basically generate N random numbers from the set 1:(N*N) to fill your matrix
You can generate an NxN matrix of 0s with M randomly placed 1s in a single line
myMatrix = reshape(randperm(N^2)<=M, N, N);
Just replace M with N in your specific case.
This is one way to do it while avoiding an explicit for loop
N=4;
board=zeros(N);
ind_1s = randperm(N*N);
board(ind_1s(1:N)) = 1;
This generates random permutations of all matrix indices and then it fills first N with 1s.
Your solution will work too but it needs a condition for cases when the newly chosen index already has a 1 in there
N=4;
board=zeros(N);
x=1;
while (x<=N)
ind_1s = randi(numel(board));
if board(ind_1s)==0
board(ind_1s)=1;
x=x+1;
end
end
For large matrices the first one may be better performance wise, but that would need to be check with matlab profiler or simple timing.

Summation using for loop in MATLAB

J = 0;
sumTerm = 0;
for i=1:m
sumTerm = sumTerm + ((theta(1)+theta(2)*X(i))-y(i)).^2;
end
J = (1/2*m)*sumTerm;
Is this the right way to do summation ?
How about this:
J = 0.5 * sum(((theta(1)*ones(size(X))+theta(2)*X)-y).^2)/m
Or as #rayryeng pointed out, you can even drop the ones
J = 0.5 * sum(((theta(1)+theta(2)*X)-y).^2)/m
That's correct, but you'll want to implement that vectorized instead of using loops. You can take advantage of this by using linear algebra to compute the sum for you. You can compute theta(1) + theta(2)*X(i) - y(i) for each term by first creating the matrix X that is a matrix of points where the first column is appended with all ones and the next column contains your single feature / data points. You would finally compute the difference between the output from the prediction line and the true output for each data point by X*theta - y which would thus produce a vector of differences for each data point. This is also assuming that your array of points and theta are both column vectors, and I believe that this is the right structure since this looks like you're implementing the cost function for univariate linear regression from Andrew Ng's Machine Learning course.
You can then compute the dot product of this vector with itself to compute the sum of square differences, then you can divide by 2*m when you're done:
vec = [ones(m,1) X]*theta - y;
J = (vec.'*vec) / (2*m); %'
The reason why you should pursue a linear algebra solution instead is because native matrix and vector operations in MATLAB are very, very fast and if you can find a solution to your computational problems with linear algebra, it'll be the fastest you can ever get your code to compute things.
For example, see this post on why matrix multiplication in MATLAB is amongst the fastest when benchmarking with other platforms: Why is MATLAB so fast in matrix multiplication?

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!

How to calculate matrix entries efficently using Matlab

I have a cell array myBasis of sparse matricies B_1,...,B_n.
I want to evaluate with Matlab the matrix Q(i,j) = trace (B^T_i * B_j).
Therefore, I wrote the following code:
for i=1:n
for j=1:n
B=myBasis{i};
C=myBasis{j};
Q(i,j)=trace(B'*C);
end
end
Which takes already 68 seconds when n=1226 and B_i has 50 rows, and 50 colums.
Is there any chance to speed this up? Usually I exclude for-loops from my matlab code in a c++ file - but I have no experience how to handle a sparse cell array in C++.
As noted by Inox Q is symmetric and therefore you only need to explicitly compute half the entries.
Computing trace( B.'*C ) is equivalent to B(:).'*C(:):
trace(B.'*C) = sum_i [B.'*C]_ii = sum_i sum_j B_ij * C_ij
which is the sum of element-wise products and therefore equivalent to B(:).'*C(:).
When explicitly computing trace( B.'*C ) you are actually pre-computing all k-by-k entries of B.'*C only to use the diagonal later on. AFAIK, Matlab does not optimize its calculation to save it from computing all the entries.
Here's a way
for ii = 1:n
B = myBasis{ii};
for jj = ii:n
C = myBasis{jj};
t = full( B(:).'*C(:) ); % equivalent to trace(B'*C)!
Q(ii,jj) = t;
Q(jj,ii) = t;
end
end
PS,
It is best not to use i and j as variable names in Matlab.
PPS,
You should notice that ' operator in Matlab is not matrix transpose, but hermitian conjugate, for actual transpose you need to use .'. In most cases complex numbers are not involved and there is no difference between the two operators, but once complex data is introduced, confusing between the two operators makes debugging quite a mess...
Well, a couple of thoughts
1) Basic stuff: A'*B = (B'*A)' and trace(A) = trace(A'). Well, only this trick cut your calculations by almost 50%. Your Q(i,j) matrix is symmetric, and you only need to calculate n(n+1)/2 terms (and not n²)
2) To calculate the trace you don't need to calculate every term of B'*C, just the diagonal. Nevertheless, I don't know if it's easy to create a script in Matlab that is actually faster then just calculating B'*C (MatLab is pretty fast with matrix operations).
But I would definitely implement (1)