Why does squeeze transpose my matrices without my permission and how to stop it?

I have tensors of the following size 1 x 1 x D x M. I'd like to squeeze it such that we always have a matrix of size D x M. The code that should do it is:
X = zeros(1,1,D,M);
X = squeeze(X); % (D x M)
However, notice that if the special case where D = 1 then we get the *wrong* behaviour of squeeze:
D = 1;
X = zeros(1,1,D,M);
X = squeeze(X); % (M x 1) = (M x D)
Instead of the desired/expected 1 x M = D x M.
I can easily just write an if code where if D=1 then transpose else do something else, but it seems super hacky because if squeeze has that unexpected weird behaviour who knows what other strange thing it might do. Is there no way to just remove the 1's without squeeze doing transposing for me for any numbers?

Answers (2)

I think you will find that squeeze's behavior, while surprising to you, is exactly as documented. Why would you expect it not to squeeze out the D=1 dimension?
I'm sympathetic, though. My recommendation is to use the permute command to rearrange the dimensions (which is what you actually want).

7 Comments

Well, it is sort of weird that it squeezes but adds x 1 where it shouldn't...I'd argue it should just keep 1 x M. I guess I have to hard code if D = 1 then do what I actually want.
Why not just
X = permute(X,[3 4 1 2])
?
No hard-coding needed.
All arrays have trailing singleton dimensions. So that array, which you saw as 1x1xm, was actually of size:
1x1xmx1x1x1x...
So, squeeze squeezes out the initial pair of singleton dimensions, leaving an mx1x1x1x1... vector behind.
I guess from my view that is definitively hard coding because now we are inserting as an assumption we always get 4D tensors. A correct program should also not do that for any tensor and any position where the singletons would be present.
also, how is that the behaviour it should do from reading the docs? even after reading it Im still surprised of the behaviour because it says that it should keep row and column vectors as is and it doesn't, right?
"B = squeeze(A) returns an array B with the same elements as A, but with all singleton dimensions removed. A singleton dimension is any dimension for which size(A,dim) = 1"
When your D is 1, all three leading dimensions are singleton, and the documentation does say it removes all singleton dimensions
A 1x1xm array is NOT a row OR a column vector. So, while squeeze does not touch row or column vectors, it does work on arrays.

Sign in to comment.

You could set up a function that uses permute but allows for unlimited dimensions:
mysqueeze = @(x) permute(x, [3:ndims(x) 1 2])
>> size(mysqueeze(rand(1,1,2,3)))
ans =
2 3
>> size(mysqueeze(rand(1,1,1,3)))
ans =
1 3
size(mysqueeze(rand(1,1,2,3,4)))
ans =
2 3 4

4 Comments

omg, how did u manage to write that without loops?
wait....it doesn't work if you have say zeros(1,1,3,1,,1,1,4,1,1) it wouldn't squeeze it to 3,4.
I think what I had in mind was:
function [ W ] = squeeze_keep_dimensions( W )
% always returns D1 x D2 even if D1=1
num_dim = ndims(W);
if num_dim == 2
return;
else
% size(W) >= 3
dimensions_W = size(W);
for d=1:num_dim-1
current_dim = dimensions_W(d);
if current_dim ~= 1
W = squeeze(W);
return;
end
end
% all dimensions are equal to 1
W = squeeze(W); % (D2 x D1) = (D2 x D1) = (D2 x 1)
W = W'; % (D1 x D2)
return;
end
end
I guess I'm not entirely clear on what your criteria is for keeping vs dropping a particular dimension. How is the function supposed to know which dimensions should remain, even if they are singleton? Will there always be two non-singleton dimensions?

Sign in to comment.

Categories

Products

Tags

Asked:

on 17 Jun 2016

Commented:

on 20 Jun 2016

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!