Sum over blocks in a 3D matrix - MATLAB - matlab

For a 3N by 3N by 3N matrix A, I would like to derive a N by N by N matrix B whose entries come from summation over blocks in A.
For example, B(1,1,1) = sum of all elements of A(1:3,1:3,1:3).
Basically, A is kind of a high resolution matrix and B is a low resolution matrix from summing over entries in A.

If memory is not a concern, you can use a "labelling" approach: build a 3-component label to group the elements of A, and use that label as the first input argument to accumarray to do the sum. The label uses integers from 1 to N, so the result of accumarray already has the desired shape (NxNxN).
N = 5;
F = 3; %// block size per dimension
A = rand(15,15,15); %// example data. Size FN x FN x FN
[ii jj kk] = ind2sub(size(A), 1:numel(A));
label = ceil([ii.' jj.' kk.']/F);
result = accumarray(label, A(:));

reshape + sum based approach and as such has to be pretty efficient -
sumrows = sum(reshape(A,3,[]),1); %// Sum along rows
sumcols = sum(reshape(sumrows,N,3,[]),2); %// Sum along cols
B = reshape(sum(reshape(sumcols,N*N,3,[]),2),N,N,N); %// Sum along 3rd dim
If you are crazy about one-liners, here's that combining all steps into one -
B = reshape(sum(reshape(sum(reshape(sum(reshape(A,3,[]),1),N,3,[]),2),N*N,3,[]),2),N,N,N);

For a 2D matrix, this would work:
B = reshape(sum(im2col(A, [3 3], 'distinct')), [N N]);
NB: You need the image processing toolbox.
But for 3D matrices, I don't know of any built-in function equivalent to im2col. You might have to use a loop. Left as an exercise to the reader ;)

Related

Matlab: how to run a For loop with multiple outputs?

So my question refers to the regress() function in matlab. Click here for the Matlab documentation
If I want to run multiple regressions using this function and output both the coefficients and the confidence intervals, what's the best way to do this in a For loop?
Matlab's own syntax for this is [b,bint] = regress(y,X). But when I try to implement this in a for loop it tells me that the dimension mismatch. My code is the following:
for i=1:6
[a, b]=regress(Dataset(:,i),capm_factors);
capm_coefs(i,:)=a;
capm_ci(i,:)=b;
end
Please help, thanks!
regress outputs a column vector of coefficients that minimize the least squared error between your input data (capm_factors) and your predicted values (Dataset(:,i)). However, in your for loop, you are assuming that a and b are row vectors.
Also, the first output of regress is the solution to your system, but the second output contains a matrix of confidence values where the first column denotes the lower end of the confidence interval for each variable and the second column denotes the upper end of the confidence interval.
Specifically, your input capm_factors should be a M x N matrix where M is the total number of input samples and N is the total number of features. In your code, a would thus give you a N x 1 vector and b would give you a N x 2 matrix.
If you'd like use a loop, make sure capm_coefs is a N x l matrix where l is the total number of times you want to loop and capm_ci should either be a N x 2 x l 3D matrix or perhaps a l element cell array. Either way is acceptable.... but I'll show you how to do both.
Something like this comes to mind:
Confidences as a 3D matrix
l = 6; %// Define # of trials
[M,N] = size(capm_factors); %// Get dimensions of data
capm_coefs = zeros(N, l);
capm_ci = zeros(N, 2, l);
for ii = 1 : l
[a,b] = regress(Dataset(:,i), capm_factors);
capm_coefs(:,ii) = a;
capm_ci(:,:,ii) = b;
end
You'd then access the coefficients for a trial via capm_coefs(:,ii) where ii is the iteration you want. Similarly, the confidence matrix can be accessed via capm_ci(:,:,ii)
Confidences as a cell array
l = 6; %// Define # of trials
[M,N] = size(capm_factors); %// Get dimensions of data
capm_coefs = zeros(N, l);
capm_ci = cell(l); %// Cell array declaration
for ii = 1 : l
[a,b] = regress(Dataset(:,i), capm_factors);
capm_coefs(:,ii) = a;
capm_ci{ii} = b; %// Assign confidences to cell array
end
Like above, you'd access the coefficients for a trial via capm_coefs(:,ii) where ii is the iteration you want. However, the confidence matrix can be accessed via capm_ci{ii} as we are now dealing with cell arrays.

Matlab code for generating a particular class of matrices

I need to generate all square matrices of order n with given properties.
Matrices are symmetric.
Entries are 0 and 1.
Diagonal elements are zeros.
I am using Matlab2012b. Can you help me with the code?
I was trying to write it down. It needs a long sequences of for loops. Any simpler technique?
Try this:
N = 4; %// matrix size
M = (N^2-N)/2; %// number of values to fill in each matrix
P = 2^M; %// number of matrices
x = dec2bin(0:P-1)-'0'; %// each row contains the values of a matrix, "packed" in a vector
result = NaN(N,N,P); %// preallocate
for k = 1:P
result(:,:,k) = squareform(x(k,:)); %// unpack values
end
The matrices are result(:,:,1), result(:,:,2) etc.

How to speed up this triple loop in matlab

I have a triple nested for loop in matlab and it takes enormous amount of time to solve it. Do you have any recommendations how can I speed up the simulation? This specific simulation is fast, but in the real code the 't' has thousand elements and and A and B about 400 elements.
A = [1,2,3];
B = [1,2];
t=[1:1:4];
or hh = 1:length(t)
for ii = 1:length(A)
T1(ii,hh)=A(ii)*t(hh)
for jj = 1:length(B)
T2(ii,jj,hh)=A(ii)*B(jj)*t(hh)
end
end
end
T1_part=sum(T1);
T2_part1=sum(sum(T2));
T2_part2=T2_part1(:,:);
T_final=T1_part+T2_part2
Results :
T_final =
24 48 72 96
Try replacing the loops with:
T1 = A'*t;
T2 = bsxfun(#times, A'*B, permute(t,[3 1 2]));
The reason for the permute is because bsxfun will expand the matrix along a singleton dimension so you need to make sure that your matrix expands along the right dimension. If you give bsxfun a row vector and a matrix, it will try do an element-wise multiplication of your row vector and each row of your matrix. But what we want is to multiply the entire matrix with each element of a vector but along a new orthogonal dimension. So permute changes the vector from a row vector to a 3D vector allowing bsxfun to expand along the correct dimension.
But then also you should first try to just pre-allocate memory for T1 and T2 using zeros, i.e. before your loop just try T2 = zeros(size(A,2), size(B,2), size(t,2)). You should always preallocate when possible when using a loop.
for both T1 and T2 you can use the element-wise product of two vectors, which gives you a matrix :
A = [1,2,3];
B = [1,2];
> T1=B'*A
T1 =
1 2 3
2 4 6

Multiply two matrices in Matlab to obtain 3-dimensional matrix

I have two sparse matrices in Matlab, A and B,
and I want to compute a three-dimensional matrix C such that
C(i,j,k) = A(i,j) * B(j,k)
can I do this without a loop?
(Side question: Is there a name for this operation?)
Edit:
Seems my question has already been asked (just for full matrices):
Create a 3-dim matrix from two 2-dim matrices
For full matrices:
You can do it using bsxfun and shiftdim:
C = bsxfun(#times, A, shiftdim(B,-1))
Explanation: Let A be of size M x N and B of size N x P. Applying shiftdim(B,-1) gives a 1 x N x P array. bsxfun implicitly replicates A along the third dimension and shiftdim(B,-1) along the first to compute the desired element-wise product.
Another possibility, usually less efficient than bsxfun, is to repeat the arrays explicity along the desired dimensions, using repmat:
C = repmat(A, [1 1 size(B,2)]) .* repmat(shiftdim(B,-1), [size(A,1) 1 1])
For sparse matrices:
The result cannot be sparse, as sparse ND-arrays are not supported.. But you can do the computations with sparse A and B using linear indexing:
ind1 = repmat(1:numel(A),1,size(B,2));
ind2 = repmat(1:numel(B),size(A,1),1);
ind2 = ind2(:).';
C = NaN([size(A,1),size(A,2),size(B,2)]); %// preallocate with appropriate shape
C(:) = full(A(ind1).*B(ind2)); %// need to use full if C is to be 3D
Answer to your side question: the name for this operation is a hash join.

MATLAB - resizing matrix using matrix multiplication and not the RESIZE command

For a specific problem, I need to design the resizing of a matrix process using multiplication of matrices alone.
Given a matrix of A of dimensions (a*b,1) where a and b are integers, I need to find a way to resize A to dimensions (a,b) like this:
M*A*N = resize(A,a,b)
where dim(M) = (a,a*b) and dim(N) = (1,b). It doesn't have to be two matrices but I don't think it is possible any other way.
If you can't use reshape or vec2mat, you need to do your manipulation for each element of A separately.
There is no such M and N that you are searching for.
Suppose:
resh_A = M*A*N;
Let's study one row of this equation. Assume one row of M*A :
temp_i = M(i, :) * A;
Since M(i, :) is 1 x a*b and A is a*b x 1; temp_i whould be a 1 x 1 matrix.
Now temp_i * N should result in the ith row of your result (or resh_A).
Thus resh_A will look like:
(note N is 1 x b)
temp_1 * N % row1
temp_2 * N % row2
temp_3 * N % row3
...
which is not a general matrix (it's a matrix with rank 1).