Matrix Multiplication with Tensors
The starting tensor is built from a list of two inner lists, each holding three numbers.
Predicting Before Printing
This article follows a short PyTorch program in which one small tensor is created, inspected, reshaped, transposed, and multiplied by its own transpose. Each step is simple on its own. The habit this article builds is predicting the result of each line before reading the output, then checking the prediction against what actually printed. A single 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.
Before reading any further, try this prediction. The starting tensor has two rows of three numbers. If you apply the transpose attribute to it, what shape do you expect the result to have? Commit to an answer, then keep reading.
What do you think happens?
A starting tensor has shape (2, 3). What is the shape after applying .T to it?
Reveal answer
(3, 2)
The transpose swaps the two dimensions. Two rows of three become three rows of two, so the rows of the original become the columns of the result.
Tracing the Starting Tensor
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. The shape attribute reports how many entries lie along each dimension. It is the first thing to check whenever a later operation behaves strangely, because almost every error in this kind of program traces back to a shape that was not what you assumed.
torch.Size([2, 3])
tensor([[1, 2, 3],
[4, 5, 6]])- The outer list holds two inner lists, so PyTorch creates two rows.
- Each inner list holds three numbers, so each row has three entries.
- shape reports the number of entries along each dimension, in row-then-column order.
The six values in this tensor form one fixed sequence: 1, 2, 3, 4, 5, 6. Every operation in the program either regroups that sequence, flips it, or combines it arithmetically. Reading the shape first tells you how those six values are currently grouped.
Reshape Regroups the Same Six Values
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, because there is no way to place seven values into six slots or five values into six slots.
The important point is the order of the values. Reshaping does not shuffle or recalculate anything. The six values keep their sequence, and the new shape determines 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. The diagram below shows this: each position in the flat sequence maps to exactly one cell in the new layout.
torch.Size([3, 2])
tensor([[1, 2],
[3, 4],
[5, 6]])- The requested shape (3, 2) has 3 times 2 = 6 entries, matching the original count.
- The printed rows are the pairs 1 and 2, 3 and 4, and 5 and 6, read in the original order.
Predicting a reshape before running it
A tensor holds the six values 1, 2, 3, 4, 5, 6 in that order. Predict the reshape to (2, 3) and the reshape to (4, 2), and decide which one can succeed.
- 1Count the entries
The tensor has 6 entries, so the new shape must multiply to 6.
- 2Check (2, 3)
2 times 3 equals 6, so this shape is valid. Fill the first row with 1, 2, 3 and the second with 4, 5, 6.
- 3Check (4, 2)
4 times 2 equals 8, which is not 6. The requested shape needs eight entries that do not exist, so this reshape cannot succeed.
- 4Confirm order
For the valid shape, the sequence 1 through 6 is kept. Only the row boundaries change.
The reshape to (2, 3) succeeds and gives rows 1 2 3 and 4 5 6. The reshape to (4, 2) cannot succeed because its total count does not match six.
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. Because the two dimensions trade places, a tensor of shape (2, 3) becomes a tensor of shape (3, 2).
torch.Size([3, 2])
tensor([[1, 4],
[2, 5],
[3, 6]])- The shape changes from (2, 3) to (3, 2), confirming the prediction from the opening.
- The first printed row, 1 and 4, is the first column of the original tensor.
- The second printed row, 2 and 5, is the second column of the original tensor.
Notice how the earlier prediction is checked here. If you predicted (3, 2) and the printed shape is torch.Size([3, 2]), the prediction held. If the shape had come back as (2, 3), the transpose would not have run as expected, and the mistake would be in the input or in which attribute was called, not in the matrix arithmetic that comes next.
Matmul Needs Matching Inner Dimensions
The matmul method multiplies two tensors as matrices. In this program the tensor is multiplied by its own transpose. The original is two by three and the transpose is three by two. The inner dimensions must agree: the three in the first tensor and the three in the second tensor. When they agree, they drop out of the result, and the outer dimensions form the shape of the product.
- 1The first tensor has m rows and n columns.
- 2The second tensor must have n rows, so its row count matches the first tensor's column count.
- 3The inner n drops out, and the product has m rows and p columns.
torch.Size([2, 2])
tensor([[14, 32],
[32, 77]])- A has shape (2, 3) and A.T has shape (3, 2); the inner dimensions 3 and 3 agree.
- The result has the outer dimensions, 2 and 2, so its shape is (2, 2).
- The top-left entry 14 combines row 0 of A with column 0 of A.T.
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. The entry at position (0, 1) is 1 times 4, plus 2 times 5, plus 3 times 6, which equals 32. Checking one entry this way is a fast test when a result looks wrong, because it isolates a single cell from the rest of the program.
Checking the inner dimensions before multiplying
A has shape (2, 3) and B has shape (3, 4). Decide whether A.matmul(B) is defined, and if so, what shape it returns.
- 1Read the inner dimensions
The columns of A are 3 and the rows of B are 3. These are the inner dimensions.
- 2Compare them
3 equals 3, so the inner dimensions agree and the product is defined.
- 3Drop the inner dimension
The inner 3 drops out of the result.
- 4Read the outer dimensions
The rows of A are 2 and the columns of B are 4, so the result has shape (2, 4).
A.matmul(B) is defined and returns a tensor of shape (2, 4).
Mistakes Beginners Make with Shapes
Common mistake Assuming reshape reorders or recalculates the values
What it looks likeExpecting A.reshape(3, 2) to print 1 4 / 2 5 / 3 6 because it looks like a transpose.
Why it failsReshape does not shuffle values. The six values keep their sequence and only the row boundaries change.
Do this insteadRead the new rows as consecutive runs of the original sequence: 1 2, then 3 4, then 5 6.
Common mistake Choosing a reshape whose total count does not match
What it looks likeCalling A.reshape(4, 2) on a tensor with six entries.
Why it fails4 times 2 is 8, and the tensor has only 6 entries, so there is no valid placement.
Do this insteadMultiply the requested dimensions first and confirm the product equals the original element count.
Common mistake Confusing .T with a reshape
What it looks likeExpecting A.T to keep the shape (2, 3).
Why it failsTranspose swaps the two dimensions, so a (2, 3) tensor becomes (3, 2).
Do this insteadAfter transposing, read .shape again and expect the two numbers in reverse order.
Common mistake Multiplying tensors whose inner dimensions disagree
What it looks likeCalling A.matmul(A) where A has shape (2, 3). The inner dimensions are 3 and 2.
Why it failsThe columns of the first tensor must match the rows of the second, and 3 does not equal 2.
Do this insteadUse A.matmul(A.T) instead, where the inner dimensions are 3 and 3.
Common mistake Ignoring .shape when a later operation fails, and instead editing the arithmetic
Finding the First Wrong Line
When an output differs from what you expected, the most efficient approach is to move forward through the program one operation at a time and check the shape and values after each. The first line where the observed result departs from your prediction is the failure location. Everything after that point may be a consequence of that line rather than a separate cause.
A colleague runs this program and reports that the final line fails. Study the lines in order and identify the first line where the result differs from what the code should produce. Lines: (1) A = torch.tensor([[1, 2, 3], [4, 5, 6]]); (2) print(A.shape); (3) B = A.reshape(3, 2); (4) C = A.T; (5) D = A.matmul(A). Which line is the first failure, and why?
Hints
- Start at line 1 and predict the shape of A before reading the output of later lines.
- Check the inner dimensions of the call on line 5 by comparing the columns of A with the rows of A.
- Lines 3 and 4 are valid: 3 times 2 equals 6, and transposing swaps the dimensions. Line 5 is the candidate.
Without running the code, write down the shape of A.reshape(2, 3).T and the shape of A.matmul(A.T.reshape(3, 2)) for the starting tensor A of shape (2, 3). Then run the code and compare your predictions with the printed shapes.
Hints
A.reshape(2, 3)keeps the shape (2, 3) because the requested total is six.- Transposing a (2, 3) tensor gives (3, 2).
- Check whether the inner dimensions of the final product agree before predicting its shape.
Summary of Reshape, Transpose, and Matmul
- 1Reshape regroups a fixed sequence of values into a new shape; the total element count must stay the same and the value order is kept.
- 2Transpose with .T swaps the two dimensions of a two-dimensional tensor, so rows become columns and columns become rows.
- 3Matmul with .matmul() requires the inner dimensions to agree, and each output entry combines one row of the first tensor with one column of the second.
- 4Check .shape after each line, and treat the first line whose result departs from your prediction as the failure location.
At a glance
- Reshape regroups a fixed sequence of six values into a new shape without reordering or recalculating them, and the total element count must match.
- Transpose with .T swaps the two dimensions, turning a (2, 3) tensor into a (3, 2) tensor whose rows are the original columns.
- Matmul requires the inner dimensions to agree; for A of shape (2, 3) and A.T of shape (3, 2), the product has shape (2, 2) with entries 14, 32, 32, and 77.
- When output is unexpected, check the shape and values after each line; the first departure from your prediction marks where the problem begins.