Charlie Parker
Charlie Parker

Reputation: 5169

Is there an easy way to transform a tensor (3D array) to a 2D array of the tensor slices as the vectors in MATLAB?

Consider a 3D matrix t of size d1 x d2 x d3. Is there a an easy way of making the matrix (2D array) of size d1d2 x d3?

so the naive implementation/pseudo-code would be something like:

T % d1 x d2 x d3
M % d1d2 x d3
for i=1:d3
    t_slice = t(:,:,i);
    m = reshape(t_slice, [d1d2, 1]); %columns of t_slice are the vector
    M(:,i) = m;
end

but it seemed something that should already be implemented or some library in matlab that already does this. Doing this by hand seems a little inefficient and I was suspecting that there was some clever MATLAB trick to do this. Am I right?

Ideally I thought something like:

M = reshape(T,[d1d2, d3])

would exist, but wasn't sure or couldn't find it yet...

I actually also mean to ask, is it possible to convert that matrix back to its tensor in a nice way in MATLAB?

Upvotes: 2

Views: 2239

Answers (1)

rayryeng
rayryeng

Reputation: 104535

Your idea is fine. What's wrong with what you had in your question at the bottom?

M = reshape(T, [d1*d2 d3]);

This would unroll each 2D slice in your 3D tensor into a single column and stack all of the columns together into a 2D matrix. I don't see where your problem lies, other than the fact that you didn't multiply d1 and d2 together. In general, you would want to do this, given T:

M = reshape(T, [size(T,1)*size(T,2) size(T,3)]);

Or, you can let MATLAB infer the amount of columns by doing:

M = reshape(T, size(T,1)*size(T,2), []);

To address your other question, to go back from the converted 2D matrix into its original 3D tensor, just do:

T2 = reshape(M, d1, d2, d3); 

In our case, this would be:

T2 = reshape(M, size(T,1), size(T,2), size(T,3));

Bear in mind that you must be cognizant of the original dimensions of T before doing this. Remember, reshape works by going over column by column and reshaping the matrix to whatever dimensions you see fit. This will now take each column and convert it back into a 2D slice, then do this for all columns until you get your original 3D matrix back.

To illustrate going back and forth, suppose we have this matrix T:

>> T = randi(10,3,3,3)

T(:,:,1) =

     9    10     3
    10     7     6
     2     1    10


T(:,:,2) =

    10    10     2
     2     5     5
    10     9    10


T(:,:,3) =

     8     1     7
    10     9     8
     7    10     8

To get our unrolled slices so that they fit into columns, use the first line of code above and you you should get a 9 x 3 matrix:

>> M = reshape(T, size(T,1)*size(T,2), [])

M =

     9    10     8
    10     2    10
     2    10     7
    10    10     1
     7     5     9
     1     9    10
     3     2     7
     6     5     8
    10    10     8

As you can see, each column is a slice from the 3D tensor unrolled into a single vector. Each column takes every column of a slice and stacks them on top of each other to get a single column.

To go backwards:

>> T2 = reshape(M, size(T,1), size(T,2), size(T,3))

T2(:,:,1) =

     9    10     3
    10     7     6
     2     1    10


T2(:,:,2) =

    10    10     2
     2     5     5
    10     9    10


T2(:,:,3) =

     8     1     7
    10     9     8
     7    10     8

As you can see, both T and T2 are the same.

Upvotes: 2

Related Questions