Concepts / Tensor Reshaping

Tensor Reshaping

Reshaping changes how a fixed sequence of values is grouped into rows and columns; the total number of elements must stay the same and the values keep their order.

  • Programming

Predicting What a Reshape Does

Tensors are the basic data containers used in PyTorch, and most of the work done with them involves changing how their values are arranged. This article follows one short program in which a single small tensor is created, inspected, reshaped, transposed, and multiplied by its own transpose. Each operation is simple on its own. The reason to study them together is that one wrong assumption early in the program, such as a shape you did not expect, carries forward into every later line and can look like a failure somewhere else entirely.

What do you think happens?

You have six numbers arranged as two rows of three. If you reshape them into three rows of two, what happens to the numbers themselves?

  • The numbers are reordered and some are multiplied

  • The numbers are unchanged and keep their sequence, only regrouped into different rows and columns

  • Some numbers are dropped so that the total fits the new shape

Reveal answer
Answer:

The numbers are unchanged and keep their sequence, only regrouped into different rows and columns.

Reshaping changes how a fixed sequence of values is grouped into rows and columns. The total number of elements must stay the same and the values keep their order. Nothing is shuffled, recalculated, or dropped.

Tracing a Six-Value Tensor Through a Program

The starting tensor is built from a list of two inner lists, each holding three numbers. PyTorch reads that nested structure and creates a two-dimensional tensor. Its shape attribute reports how many entries lie along each dimension, which is the first thing to check whenever a later operation behaves strangely. The program below runs the full sequence. As you read it, predict the printed result of each line before you look at the output.

Code walkthrough
import torch

x = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(x.shape)

reshaped = x.reshape(3, 2)
print(reshaped)

t = x.T
print(t)

product = x.matmul(x.T)
print(product)
  1. 1
    Line 3 creates the tensor. Its shape should be 2 by 3, so check that first.
  2. 2
    Line 5 prints the shape. If this is not 2 by 3, every later line will differ from the output shown here.
  3. 3
    Line 7 reshapes the tensor. Six values must still account for exactly six entries, and they appear in the same order.
  4. 4
    Line 10 applies the transpose attribute. No parentheses are used because .T is an attribute, not a method.
  5. 5
    Line 13 multiplies the tensor by its own transpose. The inner dimensions agree (3 and 3), so the product exists and is 2 by 2.
  • torch.tensor() reads the nested lists and builds a two-dimensional tensor
  • x.shape reports the size along each dimension: 2 rows and 3 columns
  • x.reshape(3, 2) returns a new view of the same six values arranged as 3 rows of 2
  • x.T flips rows and columns, giving a 3 by 2 tensor
  • x.matmul(x.T) multiplies the 2 by 3 tensor by its 3 by 2 transpose
Output
torch.Size([2, 3])
tensor([[1, 2],
        [3, 4],
        [5, 6]])
tensor([[1, 4],
        [2, 5],
        [3, 6]])
tensor([[14, 32],
        [32, 77]])

Reshape Regroups Without Reordering

The reshape method takes a new shape and returns a tensor with that shape. The starting tensor holds six values, so any new shape must also account for exactly six entries. Asking for a shape with a different total count cannot succeed. Reshaping does not shuffle or recalculate anything. The six values keep their sequence, and the new shape decides where each row begins and ends. Reading the same six values in order into three rows of two produces a different grouping of the same numbers, as the first grid below shows.

1row 0, col 01row 0, col 02row 0, col 12row 0, col 13row 0, col 23row 1, col 04row 1, col 04row 1, col 15row 1, col 15row 2, col 06row 1, col 26row 2, col 1
Which element lands at each row and column when the sequence 1 through 6 is read into a 2 by 3 grid versus a 3 by 2 grid?

Under the grids, the values are stored as one linear sequence, and the shape only tells the library how to index into that sequence. Reshape keeps that sequence intact and changes the indexing rule, which is why the values stay the same. The source's reshaped result is three rows of two: the pairs 1 and 2, 3 and 4, and 5 and 6. Those are the same six numbers in the same order as the original, regrouped.

1position 02position 13position 24position 35position 46position 5
How the six values of a 2D tensor are kept as one ordered sequence, and why reshape changes only how that sequence is indexed.

Transpose Swaps Rows and Columns

The transpose attribute, written .T with no parentheses, flips a two-dimensional tensor so that its rows become its columns and its columns become its rows. The first row of the original becomes the first column of the result, and the same pattern continues for every row. Transposing changes the shape from 2 by 3 to 3 by 2. In the diagram below, each element is labeled with its new position, and the elements that moved are marked.

1row 0, col 01now row 0, col 02row 0, col 14now row 0, col 13row 0, col 22now row 1, col 04row 1, col 05now row 1, col 15row 1, col 13now row 2, col 06row 1, col 26now row 2, col 1
After applying .T to the 2 by 3 tensor, where does each original element move, and how do the old rows become the new columns?
Worked example

Reading the first column of the transpose

Using x = [[1, 2, 3], [4, 5, 6]], what is the first column of x.T, and how does it relate to the original tensor?

  1. 1
    Identify the first row of x

    The first row of x is 1, 2, 3.

  2. 2
    Turn that row into a column

    Transposing makes the first row the first column, so the first column of x.T is 1, 2, 3 read top to bottom.

  3. 3
    Check against the printed transpose

    The source output for the transposed tensor begins with the rows 1 and 4, then 2 and 5, then 3 and 6. Reading down the first two entries of each row gives the first two columns of the original, which confirms the pattern.

Result

The first row of the original becomes the first column of x.T. The printed transpose has rows 1 and 4, 2 and 5, 3 and 6, so the old rows now run down the columns.

Matrix Multiplication and Inner Dimensions

The matmul method multiplies two tensors as matrices. In the program above, the tensor is multiplied by its own transpose. The original is 2 by 3 and the transpose is 3 by 2. The inner dimensions, the 3 at the end of the first shape and the 3 at the start of the second, agree, so the product is defined. The outer dimensions, the 2 and the 2, give the shape of the result. Before running matmul, check that the inner dimensions match. If they do not, the operation cannot succeed.

Formula, step by step
  1. 1
    The first tensor has 2 rows and 3 columns, so its shape is $2 \times 3$.
  2. 2
    The second tensor is the transpose, with 3 rows and 2 columns, so its shape is $3 \times 2$.
  3. 3
    The inner values 3 and 3 agree, so the multiplication is defined.
  4. 4
    The outer values 2 and 2 give the shape of the product, which is $2 \times 2$.

Each output entry combines one row of the first tensor with one column of the second. The source prints the product with rows 14 and 32 in the first row and 32 and 77 in the second. To check the top-left entry by hand, multiply the first row by the first column and add the products: 1 times 1, plus 2 times 2, plus 3 times 3, which equals 14. Checking a single entry this way is a fast test when a result looks wrong, because it takes only a few multiplications.

python
Output (expected)
3 3
torch.Size([2, 2])
Notes on the code
  • x.shape[1] is the inner size of the first tensor
  • x.T.shape[0] is the inner size of the second tensor
  • Equal values mean the multiplication is defined

Mistakes That Hide Shape Errors

Shape problems are the most common source of confusing tensor results. The mistakes below are easy to make because each one looks reasonable until the printed shape or values are compared with what was expected.

  • Common mistake

    Expecting reshape to reorder or recalculate the values

    What it looks like

    Reshaping 2 by 3 into 3 by 2 and expecting the numbers to come out shuffled or multiplied.

    Why it fails

    Reshaping keeps the six values in their sequence and only changes where each row begins and ends.

    Do this instead

    Read the output as the same numbers regrouped. Treat any reordering as a signal to check the input.

  • Common mistake

    Choosing a reshape whose total count does not match

    What it looks like

    Asking for a shape that holds eight entries from a tensor of six values.

    Why it fails

    Any new shape must account for exactly as many entries as the original tensor holds.

    Do this instead

    Multiply the dimensions of the requested shape and confirm the product equals the original element count.

  • Common mistake

    Using .T with parentheses

    What it looks like
    Writing x.T() instead of x.T.
    Why it fails

    The transpose is an attribute, written without parentheses.

    Do this instead

    Write x.T and check the printed shape afterward.

  • Common mistake

    Multiplying tensors without checking inner dimensions

    What it looks like

    Calling matmul on a 2 by 3 tensor and a 2 by 3 tensor directly.

    Why it fails

    The inner dimensions 3 and 2 do not agree, so the product is not defined.

    Do this instead

    Compare the last dimension of the first tensor with the first dimension of the second, or transpose one tensor so they agree.

  • Common mistake

    Debugging the last line instead of the first divergence

    What it looks like

    Seeing a wrong final matrix and rewriting the matmul call while the reshape earlier in the program was already producing a different shape.

    Why it fails

    A single wrong assumption early on carries forward and can look like a failure later.

    Do this instead

    Move forward one line at a time, checking shape and values after each step. The first line where the observed result departs from your prediction is the failure location.

Best practice

Print the shape immediately after creating a tensor and again after every reshape, transpose, or matmul. The shape is the first thing to check whenever a later operation behaves strangely, and it costs one line of code per step.

Finding Where a Result First Diverges

When an output differs from what you expected, the efficient approach is to move forward through the program one operation at a time. Predict the shape and values after each line, compare them with what is printed, and stop at the first mismatch. That line is the failure location. Later lines may be consequences of it rather than separate causes.

  1. 1
    Print x.shape after creating x and confirm it is 2 by 3.
  2. 2
    Predict the shape after x.reshape(3, 2) and check the printed shape.
  3. 3
    Predict the values after reshape and confirm the six numbers keep their order.
  4. 4
    Predict the shape of x.T and check it against the printed transpose.
  5. 5
    Check the inner dimensions of the matmul call before reading its result.
  6. 6
    Verify one entry of the product by multiplying a row by a column.
MEDIUM

A program creates a tensor y with shape 3 by 4, then calls y.reshape(2, 6) and y.T, and finally y.matmul(y.T). Before running it, predict the shape after each line. At which line would you expect a shape error, and why?

Hints
  • Reshape must keep the total number of entries, which is 12 for a 3 by 4 tensor.
  • The transpose of a 3 by 4 tensor is 4 by 3.
  • Check whether the inner dimensions of y and y.T agree: 4 and 3 do not match.

Key Takeaways

  • Reshaping regroups a fixed sequence of values into new rows and columns. The total number of elements must stay the same, and the values keep their order.
  • Transposing with .T, written without parentheses, swaps rows and columns, so a 2 by 3 tensor becomes 3 by 2 and the first row becomes the first column.
  • Matrix multiplication with .matmul() requires the inner dimensions to agree. The result takes its shape from the outer dimensions, and each entry combines one row of the first tensor with one column of the second.
  • When results look wrong, print the shape and check values line by line, stopping at the first line where the output departs from your prediction.

Related concepts

More concepts starting with T