Row-normalize matrix - matlab

Is there any efficient (speed of computation + amount of keystrokes) way to perform row-normalization in MATLAB, using the built in functions?
This is what I've came up with so far
A = rand(m, n); % m rows, n cols
v = pdist2(zeros(1, size(A, 2)), A);
normA = diag(1./v) * A;

Assuming you want row sums to be 1:
bsxfun(#times, A, 1./(sum(A, 2)))
Edit
If you're looking for the l2 norm as #Oli suggests below, then
bsxfun(#times, A, 1./sqrt(sum(A.^2, 2)))
In that case, you can semi-gracefully handle zero row sums by doing
bsxfun(#times, A, 1./(max(sum(A, 2), eps)))

Related

Multiply n vectors of length p by n matrices of size pxp

I have n complex vectors of length p that I want to multiply by n complex matrices of size p-by-p. I am looking for the most efficient way to do this in MATLAB. If it matters, I am imagining that n is large and p is small.
An example using a loop (which I would like to avoid) is shown below.
N = 1e4;
p = 5;
A = randn(p, N); % N vectors of length p
B = randn(p, p, N); % N matrices of size pxp
C = zeros(p, N);
for k = 1:N
C(:, k) = B(:, :, k) * A(:, k);
end
It's been suggested that I might be able to achieve this efficiently using tensor functions, but I haven't been able to figure that out.
Here's a way using implicit expansion:
C = permute(sum(B.*permute(A, [3 1 2]), 2), [1 3 2]);
For old Matlab versions (before R2016b) you need to rewrite it with bsxfun:
C = permute(sum(bsxfun(#times, B, permute(A, [3 1 2])), 2), [1 3 2]);
You can accomplish that in various ways:
A = rand(3, 3, 1e6);
B = rand(3, 1);
tic, C = zeros(3, size(A, 3));
for i = 1:size(A, 3)
C(:,i) = A(:,:,i)*B ;
end, toc
tic; C = reshape(reshape(permute(A,[2,1,3]),3,[]).'*B,3,[]); toc
tic; C = squeeze(sum(bsxfun(#times, A, reshape(B, 1, 3)), 2)); toc
In my system:
Elapsed time is 2.067629 seconds. % Loop
Elapsed time is 0.064164 seconds. % permute
Elapsed time is 0.145738 seconds % sum(times())

Linear combination of the Slices in a 3D

I have a 3D matrix sized (x,y,N) and a 2D matrix sized (N,N).
I would like to manipulate the two in a way that each column in the 2D matrix has the coefficients for a linear combination of the 2D sized- (x, y) slices in the 3D matrix. And I would like to do this for all N columns in the 2D matrix.
Schematically,
Currently the code looks like:
A = zeros(numel(x_axis), numel(y_axis), N);
B = zeros(numel(x_axis), numel(y_axis), N);
C = zeros(N, N)
for i = 1 : N
for j = 1 : N
A(:,:,i) = A(:,:,i) + B(:,:,j) * C(j,i);
end
end
But it is quite slow. Is there any way to speed up the MATLAB code by vectorizing?
If I understand your problem well, then this should work:
[p,q,N] = size(B);
A = reshape( reshape(B, [p*q, N]) * C, [p, q, N]);
edit: Cleaner version suggested by Suever:
A = reshape(reshape(B, [], size(B, 3)) * C, size(B))
Generalization to the R-D case:
A = reshape(reshape(B, [], size(B, ndims(B))) * C, size(B))
You can use bsxfun which will calculate this very quickly for you. We have to use permute to re-arrange C a little bit to ensure that it has conformant dimensions for using bsxfun and then we perform the summation along the third dimension of the resulting output and apply squeeze to remove the singleton third dimension.
A = squeeze(sum(bsxfun(#times, B, permute(C, [3 4 1 2])), 3))

Is it possible to use mldivide "\" on a 3D matrix in Matlab

Is it possible to use mldivide (\) on a 3D matrix in MATLAB? I would like to avoid using a for loop?
Sample:
A = rand(4, 100, 5);
B = rand(4,4);
I need to perform:
C = B\A;
What I'm doing now:
Apply the mldivide on a for loop for each "slice" i:
for i = 1:size(A, 3)
C(:,:,i) = B \ A(:,:,i);
end
You can reshape A into a 2D matrix to perform the division and then back to the expected size afterwards. The reshape operations should be relatively quick due to the fact that MATLAB doesn't alter the underlying data.
C = reshape(B \ reshape(A, size(A, 1), []), size(B, 1), size(A, 2), []);
And if we break that down:
%// Reshape A to be 4 x 500
Anew = reshape(A, size(A, 1), []);
%// Perform left division
C = B \ Anew;
%// Reshape C to be the expected size (4 x 100 x 5)
C = reshape(C, size(B, 1), size(A, 2), []);
This should work for any valid (size(A, 1) == size(B, 2)) matrices A and B of any size.

Apply a function to all column pairs between two matrices in Matlab

I have a Matlab function z = foo(x, y) that takes two column vector as inputs and output a scalar. Now I would like to apply this function to two matrices A(dimension n * d1) and B (dimension n * d2) and generate a d1 * d2 matrix, such that output(i, j) = foo( A(:, i), B(:, j) ). It should basically resemble the behavior of applying the corr function to two matrices.
I tried the solutions in this link, but the encounter the same problem in the first answer, and the meshgrid step in second solution is way too slow.
Any suggestions? Thanks very much in advance!
If foo accepts a matrix then:
%Find dimensions
dA = size(A,2);
dB = size(B,2);
%Generate a list of all possible column pairs for the two matrices
indA = ceil((1:dA*dB)/dA);
indB = mod(0:dA*dB, dB)+1;
X = A(:, indA);
Y = B(:, indB);
z = foo(X,Y)
then you'll probably be able to reshape z to what you want

Vectorizing a weighted sum of matrices in MATLAB

I'm trying to vectorize the following operation in MATLAB, but it's got me stumped. I've learned from experience that there usually is a way, so I'm not giving up just yet. Any help would be appreciated.
I have a collection of m row-vectors each of size n, arranged in an m x n matrix; call it X.
I also have an m-sized vector of weights, w.
I want to compute a weighted sum of the matrices formed by the self outer products of the vectors in X.
Here is a MWE using a for loop:
m = 100;
n = 5;
X = rand(m, n);
w = rand(1, m);
S = zeros(n, n);
for i = 1 : m
S = S + (w(i) * X(i, :)' * X(i, :));
end
S
This is probably the fastest approach:
S = X' * bsxfun(#times, X, w(:));
You could also do
S = squeeze(sum(bsxfun(#times, ...
bsxfun(#times, conj(X), permute(X, [1 3 2])), w(:)), 1));
(or remove the complex conjugate if not needed).
You can employ two approaches here that use one bsxfun call and few permutes and reshapes. The reshaping trick basically allows us to use the efficient matrix multiplication and thus avoid any extra bsxfun call we might have required otherwise.
Approach #1
[m1,n1] = size(X);
XXmult = bsxfun(#times,X,permute(X,[1 3 2])); %// For X(i, :)' * X(i, :) step
S = reshape(reshape(permute(XXmult,[2 3 1]),[],m1)*w(:),n1,[]) %// multiply weights w
Approach #2
[m1,n1] = size(X);
XXmult = bsxfun(#times,permute(X,[2 3 1]),permute(X,[3 2 1]));
S = reshape(reshape(XXmult,[],m1)*w(:),n1,[])
Shortest answer, and probably fastest:
S = X'*diag(W)*X
Been using it for an unscented Kalman filter, works great.