The problem
A transformer reads a sequence of vectors. To read an image, the ViT (Vision Transformer; Dosovitskiy et al., 2021) cuts it into square patches, flattens each patch into a vector, and treats the patches as tokens, like words in a sentence. You will write the cutting and the embedding.
For images of shape (batch, height, width, channels) and patch size (dividing and ):
- Cut each image into patches of pixels, in row-major order: left to right, then top to bottom.
- Flatten each patch into numbers, in the order
patch[row, col, channel]. - Project with a learned matrix of shape : each patch becomes a vector of numbers.
- Prepend the learned class embedding (shape ) and add the position embeddings (shape ).
Example. A toy image of pixels, one channel, with the pixels numbered row by row, and :
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15There are patches of numbers each. In row-major order:
[0, 1, 4, 5](top-left),[2, 3, 6, 7](top-right),[8, 9, 12, 13](bottom-left),[10, 11, 14, 15](bottom-right). The result ofpatchifyhas shape .A real image of pixels with 3 channels and gives patches of numbers, and 197 tokens with the class token.
Cutting without loops
With one reshape and one transpose:
x.reshape(B, H // P, P, W // P, P, C): the axes are now (batch, patch row, pixel row inside the patch, patch column, pixel column inside the patch, channel).transpose(0, 1, 3, 2, 4, 5): bring the two patch-grid axes together, then the two pixel axes: (batch, patch row, patch column, pixel row, pixel column, channel).reshape(B, N, P * P * C): flatten the grid into a list of patches and each patch into a vector.
What to implement
patchify(images, P): shape .vit_embed(images, P, E, cls, pos): shape .
Requirements
- No Python loops.
- Raise
ValueErrorif does not divide and .