Tensors and Shapes in PyTorch
The raw text is not passed to the tensor step; only the list of token IDs is.
Why a Prompt Has to Be Converted Before a Model Can Use It
Suppose you want a language model to continue a short piece of text. The concrete goal here is a prompt, the string "Hello, I am", which must be prepared as input for the generate_text_simple function. A model does not read characters the way a person does. Before the model can use the prompt, the text has to pass through two conversions: first into token IDs, and then into a tensor. Each conversion produces something the next stage can consume, and the whole path is a chain in which every stage depends on the one before it.
This article follows that chain one stage at a time. You will see what each stage receives, what it returns, and how the shape of the data changes along the way. By the end you should be able to look at a printed list and a printed shape and say which stage a problem most likely came from.
Tracing the Prompt Through Each Stage
The preparation takes four lines of logic. One line assigns the prompt to a variable. The second encodes it. The third converts the encoded result into a tensor with a batch dimension. The remaining two lines print what the encoding and tensor stages produced, so you can inspect each intermediate result instead of trusting the final output alone.
input_textholds the raw string prompttokenizer.encode(input_text)returns a Python list of integers, not texttorch.tensor(encoded)builds a tensor from that list of IDs- .unsqueeze(0) adds a new leading dimension of size 1, the batch dimension
- The final print reports the shape that the model will receive
The first stage is tokenizer.encode(input_text). Its input is a string and its output is a list of integers. Those integers are the representation the rest of the pipeline works with. The raw text is not passed to the tensor step; only the list of token IDs is. This means that everything downstream depends on what the encoder returned, so the printed list is the first thing to check.
The second stage is torch.tensor(encoded), which converts the Python list of token IDs into a PyTorch tensor. A list of four integers becomes a one-dimensional tensor with four elements. The values stay the same; what changes is that the data now lives in the tensor type that PyTorch operations expect.
The third stage is the call .unsqueeze(0), which adds a new dimension at index 0. This is the batch dimension. The model expects its input to carry a batch dimension, so this step is required even though the token values themselves do not change. Only this final stage adds the batch dimension, which is why its effect appears in the shape printed at the end of the trace.
The diagram is a pipeline, so each stage consumes the output of the previous one. A problem at any stage propagates to every later stage. If the encoder returns the wrong integers, the tensor will faithfully hold the wrong integers. If the tensor is built correctly but the batch dimension is missing, the model receives the right values with the wrong shape.
Reading a Shape as Nested Brackets
A shape tells you how many values sit at each level of nesting. Each number in a shape corresponds to one level of brackets. A shape of $(4,)$ describes a single bracketed group containing four values, such as a flat list of four token IDs. A shape of $(1, 4)$ describes an outer group containing exactly one inner group, and that inner group holds four values. The first number is the outermost level and the last number is the innermost.
| Stage | Shape | Outer level | Inner level |
|---|---|---|---|
| After torch.tensor(encoded) | $(4,)$ | 4 token IDs, no batch wrapper | none |
| After .unsqueeze(0) | $(1, 4)$ | 1 batch entry | 4 token IDs |
How the same four IDs are grouped before and after the batch dimension is added
Reading the shape of an encoded prompt
The encoder returns a list of four integer IDs. What shape does torch.tensor(encoded) produce, and what shape does the model receive after unsqueeze(0)?
- 1Count the elements
The Python list has four integers, so the one-dimensional tensor has one dimension of size 4.
- 2Write the first shape
A one-dimensional tensor with four elements has shape $(4,)$.
- 3Apply unsqueeze(0)
unsqueeze(0)inserts a new dimension at index 0 with size 1. The four IDs are unchanged, but they are now wrapped in one batch entry. - 4Write the second shape
The new shape is $(1, 4)$: a batch dimension of size 1 followed by the sequence of four token IDs.
torch.tensor(encoded) has shape $(4,)$, and after unsqueeze(0) the model input has shape $(1, 4)$.
What unsqueeze(0) Changes and What It Does Not
The method call .unsqueeze(0) adds a new dimension at index 0. Index 0 is the front of the shape, so the new dimension becomes the outermost level of nesting. The token values themselves are not altered and not reordered. The call only changes how those values are grouped. This is why the source describes the step as adding a batch dimension: it wraps the existing sequence so that the model sees a batch containing one item.
encoded_tensor = torch.tensor(encoded)
# shape: (4,)A one-dimensional tensor holding four token IDs directly.
encoded_tensor = torch.tensor(encoded).unsqueeze(0)
# shape: (1, 4)A two-dimensional tensor whose first dimension is the batch of size 1.
Reading the diagram from left to right shows the transformation. The four token IDs survive intact. What changes is that a new outer level of size 1 now encloses them, and that level sits at index 0 because the call specifies 0. Calling unsqueeze with a different index would place the size-1 dimension somewhere else, but the batch dimension described in the source is the one created at index 0.
Tokens as Integers and Vocabulary Lookup
The encoder is the stage that converts text into the integer representation the rest of the pipeline uses. The source states the key contract: tokenizer.encode(input_text) converts a string into a list of integer token IDs. Each integer stands in for a piece of the input. The exact integer values depend on the tokenizer, so the number you see for a given word is a property of that tokenizer rather than something you can derive from the text alone.
Imagine a prompt that encodes to the list [101, 7, 42, 9]. These numbers are hypothetical and chosen only for illustration. The tensor step turns that list into a tensor of shape $(4,)$, and unsqueeze(0) turns it into a tensor of shape $(1, 4)$. Notice that the values 101, 7, 42, and 9 are the same in every stage; only their grouping changes.
Mistakes That Hide the Real Source of a Shape Problem
The source gives a practical way to separate two kinds of failure. Checking the printed encoded list and the printed tensor shape tells you whether the problem is in encoding or in tensor preparation. The following mistakes are the ones most often confused with each other.
Common mistake Assuming the tensor is wrong when the encoded list is already wrong
What it looks likeThe printed list contains unexpected IDs, and the developer starts changing unsqueeze or torch.tensor calls.
Why it failsEach stage consumes the output of the previous one, so a bad encoding propagates into the tensor. The tensor faithfully stores bad values.
Do this insteadPrint the encoded list first. If the integers are wrong, the problem is in the encoding stage, not the tensor stage.
Common mistake Forgetting the batch dimension
What it looks likeThe tensor has shape (4,) and the model is given it directly as input.
Why it failsThe model expects its input to carry a batch dimension, so a one-dimensional tensor does not match what it expects.
Do this insteadApply unsqueeze(0) after torch.tensor(encoded) so the shape becomes (1, 4).
Common mistake Thinking unsqueeze(0) changes the token values
What it looks likeThe developer expects the IDs to be modified or reordered after calling unsqueeze(0).
Why it failsThe call only inserts a new dimension of size 1 at index 0. The values are unchanged.
Do this insteadCompare the elements before and after; they should match, while only the nesting and shape differ.
Common mistake Passing the raw string into the tensor step
What it looks likeCalling torch.tensor on the prompt string instead of the encoded list.
Why it failsThe tensor step receives only the list of token IDs. The text itself is not passed forward.
Do this insteadPass the output of tokenizer.encode(input_text) into torch.tensor.
Predicting the Shape Before Running the Code
What do you think happens?
If the encoded list has four integers, what is the shape of torch.tensor(encoded).unsqueeze(0)?
Reveal answer
(1, 4)
torch.tensor(encoded) produces shape (4,). unsqueeze(0) inserts a new dimension of size 1 at index 0, giving (1, 4).
A colleague reports that the model fails with an input shape error. The printed encoded list looks correct, but the printed shape is (7,) when the model expects a batch dimension. Which stage should you inspect, and what single call would most likely fix the shape?
Hints
- The encoded list is correct, so the encoding stage is not the first suspect.
- A missing leading dimension of size 1 is the signature of a missing
unsqueeze(0).
Pipeline Recap
- 1
tokenizer.encode(input_text)converts a string into a list of integer token IDs, and only that list is passed to the tensor step. - 2
torch.tensor(encoded)turns the Python list into a PyTorch tensor, producing shape $(4,)$ for four IDs. - 3
unsqueeze(0)adds a batch dimension at index 0, producing shape $(1, 4)$ so the model receives input in the form it expects. - 4Printing the encoded list and the tensor shape separates encoding problems from tensor-preparation problems.
Key Takeaways
tokenizer.encode(input_text)converts a string into a list of integer token IDs.torch.tensor(encoded)converts that Python list into a PyTorch tensor without changing the values.unsqueeze(0)adds a batch dimension at index 0, so a shape of (4,) becomes (1, 4).- Each stage consumes the previous stage's output, so checking the printed list and shape locates the source of a mismatch.