I want to sum all elements of matrix in Matlab. If I had a matrix called A, then I can sum all elements by calling
sum(A(:));
But I would like to sum elements returning from a function like this:
sum(gammaln(A)) % where gammaln is the logarithm of gamma function
Of course I can do this in two steps:
B = gammaln(A);
sum(B(:));
But here I create a B matrix, which I don't need at all. And also I can do it this way:
sum(sum(gammaln(A)))
But, the number of sum's will be equal to the dimension of my matrix. It looks ugly, and the matrix dimension may change.
I'm curious if there is any way of doing this.
use reshape instead of (:) operator:
sum(reshape(gammaln(A),[],1))
Related
I have two matrices X and Y, both of order mxn. I want to create a new matrix O of order mxm such that each i,j th entry in this new matrix is computed by applying a function to ith and jth row of X and Y respectively. In my case m = 10000 and n = 500. I tried using a loop but it takes forever. Is there an efficient way to do it?
I am targeting two functions dot product -- dot(row_i, row_j) and exp(-1*norm(row_i-row_j)). But I was wondering if there is a general way so that I can plugin any function.
Solution #1
For the first case, it looks like you can simply use matrix multiplication after transposing Y -
X*Y'
If you are dealing with complex numbers -
conj(X*ctranspose(Y))
Solution #2
For the second case, you need to do a little more work. You need to use bsxfun with permute to re-arrange dimensions and employ the raw form of norm calculations and finally squeeze to get a 2D array output -
squeeze(exp(-1*sqrt(sum(bsxfun(#minus,X,permute(Y,[3 2 1])).^2,2)))
If you would like to avoid squeeze, you can use two permute's -
exp(-1*sqrt(sum(bsxfun(#minus,permute(X,[1 3 2]),permute(Y,[3 1 2])).^2,3)))
I would also advise you to look into this problem - Efficiently compute pairwise squared Euclidean distance in Matlab.
In conclusion, there isn't a common most efficient way that could be employed for every function to ith and jth row of X. If you are still hell bent on that, you can use anonymous function handles with bsxfun, but I am afraid it won't be the most efficient technique.
For the second part, you could also use pdist2:
result = exp(-pdist2(X,Y));
I am trying to minimize sum((A-r*B).^2) in Matlab where A and B are matrices and r is the scalar I am manipulating. I tried the following code:
f = #(r) sum((A-r*B).^2);
Answer = fminbnd(f,lowrange,highrange);
But I get an error.
If A and B are matrices, then sum((A - r*B).^2) will not give you a single value. This will give you an array of values. If the input to sum is a matrix, the output of sum will give you an array where each element is the sum along the rows for each column in your matrix.
The function you are specifying to fminbnd must evaluate to a single value. I'm assuming you want to determine the sum of squared differences in your function, and so you need to wrap your sum with another sum. As such, try this instead:
f = #(r) sum(sum((A-r*B).^2));
Answer = fminbnd(f,lowrange,highrange);
The function f will now find the difference between matrices A and B which is weighted by r, square these differences and then add up all of these differences together.
Try that and see if it works.
If you don't need to impose limits on the possible values of the optimized scalar r, then you should be able to solve this equation directly without searching for the minimum. If A and B are vectors, use:
ropt=(B'*B)^(-1)*B'*A;
If A and B are arrays and you want to minimize the sum of squared residuals of all elements of the arrays then I believe the following will work (same formula, but convert A and B to vectors).
ropt=(B(:)'*B(:))^(-1)*B(:)'*A(:);
Examples:
b=[1;2;3]
a=2*b;
ropt=(b'*b)^(-1)*b'*a
returns ropt=2.0000, as desired
Similarly, for a matrix:
b=magic(3);
a=2*b;
ropt=(b(:)'*b(:))^(-1)*b(:)'*a(:)
also returns ropt=2.0000. This should work fine even if there isn't a perfect solution, as there is in the examples above.
I have two 50 x 6 matrices, say A and B. I want to assign weights to each element of columns in matrix - more weight to elements occurring earlier in a column and less weight to elements occurring later in the same column...likewise for all 6 columns. Something like this:
cumsum(weight(row)*(A(row,col)-B(row,col)); % cumsum is for cumulative sum of matrix
How can we do it efficiently without using loops?
If you have your weight vector w as a 50x1 vector, then you can rewrite your code as
cumsum(repmat(w,1,6).*(A-B))
BTW, I don't know why you have the cumsum operating on a scalar in a loop... it has no effect. I'm assuming that you meant that's what you wanted to do with the entire matrix. Calling cumsum on a matrix will operate along each column by default. If you need to operate along the rows, you should call it with the optional dimension argument as cumsum(x,2), where x is whatever matrix you have.
I am wondering if there is any build in function or an easy way to plot a histogram of elements of a 2d array.
For example, if A=rand(100,1), then A is an 1D array, and hist(A) can do the histogram.
However, what if A=rand(100,100), and I would like to make a histogram on elements of A, just like treating each element in A as an element on a 1D array. Is there a easy way to do so?
You just have to reshape A into a vector, then you can use hist as usual:
hist(A(:))
This command will do what you want:
hist(reshape(A, prod(size(A)), 1))
What it does is create a vector out of the matrix A by reshaping it into a matrix with one column and a number of rows equal to the number of elements of A:
prod(size(A)) = number_of_columns(A) * number_of_rows(A)
Or the short way:
hist(A(:))
This takes every element of A in sequence and thus also generates a vector.
I am trying to take a matrix and normalize the values in each cell around the average for that column. By normalize I mean subtract the value in each cell from the mean value in that column i.e. subtract the mean for Column1 from the values in Column1...subtract mean for ColumnN from the values in ColumnN. I am looking for script in Matlab. Thanks!
You could use the function mean to get the mean of each column, then the function bsxfun to subtract that from each column:
M = bsxfun(#minus, M, mean(M, 1));
Additionally, starting in version R2016b, you can take advantage of the fact that MATLAB will perform implicit expansion of operands to the correct size for the arithmetic operation. This means you can simply do this:
M = M-mean(M, 1);
Try the mean function for starters. Passing a matrix to it will result in all the columns being averaged and returns a row vector.
Next, you need to subtract off the mean. To do that, the matrices must be the same size, so use repmat on your mean row vector.
a=rand(10);
abar=mean(a);
abar=repmat(abar,size(a,1),1);
anorm=a-abar;
or the one-liner:
anorm=a-repmat(mean(a),size(a,1),1);
% Assuming your matrix is in A
m = mean(A);
A_norm = A - repmat(m,size(A,1),1)
As has been pointed out, you'll want the mean function, which when called without any additional arguments gives the mean of each column in the input. A slight complication then comes up because you can't simply subtract the mean -- its dimensions are different from the original matrix.
So try this:
a = magic(4)
b = a - repmat(mean(a),[size(a,1) 1]) % subtract columnwise mean from elements in a
repmat replicates the mean to match the data dimensions.