Here is a visual representation of what squeeze/unsqueeze do for an effectively 2d matrix:

When you are unsqueezing a tensor, it is ambiguous which dimension you wish to 'unsqueeze' it across (as a row or column etc). The dim argument dictates this - i.e. position of the new dimension to be added.
Hence the resulting unsqueezed tensors have the same information, but the indices used to access them are different.
Answer from End genocide - save Gaza on Stack OverflowHere is a visual representation of what squeeze/unsqueeze do for an effectively 2d matrix:

When you are unsqueezing a tensor, it is ambiguous which dimension you wish to 'unsqueeze' it across (as a row or column etc). The dim argument dictates this - i.e. position of the new dimension to be added.
Hence the resulting unsqueezed tensors have the same information, but the indices used to access them are different.
Simply put, unsqueeze() "adds" a superficial 1 dimension to tensor (at the specified dimension), while squeeze removes all superficial 1 dimensions from tensor.
A 1 dimension is superficial in the sense that it does not add any more elements to the tensor than would be there without it. Whenever this is true of a tensor dimension, it will always have the size 1 - hence the name "1 dimension".
You should look at tensor's shape attribute to see it easily. In your last case it would be:
import torch
tensor = torch.tensor([1, 0, 2, 3, 4])
tensor.shape # torch.Size([5])
tensor.unsqueeze(dim=0).shape # [1, 5]
tensor.unsqueeze(dim=1).shape # [5, 1]
It is useful for providing single sample to the network (which requires first dimension to be batch), for images it would be:
# 3 channels, 32 width, 32 height
tensor = torch.randn(3, 32, 32)
# 1 batch, 3 channels, 32 width, 32 height
tensor.unsqueeze(dim=0).shape
unsqueeze can be seen if you create tensor with 1 dimensions, e.g. like this:
# 3 channels, 32 width, 32 height and some 1 unnecessary dimensions
tensor = torch.randn(3, 1, 32, 1, 32, 1)
# 1 batch, 3 channels, 32 width, 32 height again
tensor.squeeze().unsqueeze(0) # [1, 3, 32, 32]
Idk if I if I am misunderstanding something, but torch.squeeze just seems like a less transparent alternative to getting a view via indexing into 0 elements. Just had to a fix a bug caused by squeeze getting called on a tensor with dynamic size along a dimension, that would occasionally be 1.