// part 4 of 8

Part 4

SelfPatch

DINO teaches a network what a whole picture is. SelfPatch adds a second lesson, one for every patch: look at the eight patches around you, keep the four that look most like you, and learn to predict a summary of them. This part takes that lesson apart: the gap it fills (4.1), which neighbours count (4.2), how a small attention head turns them into one target (4.3), how the patch loss joins DINO's loss (4.4), what the model costs in numbers (4.5), one training step from end to end (4.6), what the paper reports and why our study measures something else (4.7), and the real neighbours of the released model (4.8). Fact

4.1 The gap DINO leaves

Assumes: patch tokens and the class token (Part 2), and DINO's loss over pairs of crops (Part 3). Gives: why SelfPatch adds a loss for every patch, and the evidence its authors give.

When a 224-pixel crop passes through the backbone, 196 patch tokens come out, one per 16 by 16 square of the crop. DINO's loss reads none of them directly. Its projection head is attached to one extra token, the class token, whose job is to gather information from the whole sequence. Fact

The SelfPatch authors point out what this leaves out: a Vision Transformer also produces an output for every patch, yet image-level methods such as DINO train only the class token's output. They argue that, as a result, such networks may fail to capture meaningful relations among patches, and that a positive pair made of two augmented views of one image is architecture-agnostic: it would train any network the same way and does not fully use the patch outputs that a Transformer has. Fact

Think about what reaches a patch token during DINO's training. The loss produces a gradient for the class token's output only. The patch tokens that leave the last block receive no gradient at all. The patch tokens inside the network receive some, through the attention that the class token pays to them in the blocks above, but only as much as the class token happens to look at them, and only towards whatever helps the summary of the whole crop. Two patches of the same dog get no direct instruction to resemble each other. Toy

DINO: one target per crop SelfPatch: one more target per patch class token image loss image-level token image loss patch loss patch tokens: no target of their own patch tokens: each has a target (196 in a 224-pixel crop) (built from its neighbours)
Where the losses reach. DINO's loss reads one vector per crop. SelfPatch keeps that image-level loss and adds a target for every patch token, built by the teacher from the patch's neighbours (the blue dots), with a second loss that compares each patch with its own target. Fact

What evidence do the authors give that the gap matters? Three kinds. A picture: in their Fig. 1 they take some patches of a ViT-S/16 trained with DINO and, for each one, keep the 10 % of patches that it attends to most in the last block. Those patches are not semantically related to the patch that asks, which their introduction calls collapsed self-attention maps; with DINO + SelfPatch the selections improve, which they take as evidence of better patch-level representations. Scores: their method improves DINO on three dense tasks, each measured with labels after pre-training (4.7). And an ablation, an experiment that changes one part at a time: they switch the patch loss off while keeping everything else, the new aggregation module of 4.3 included. With the patch loss's weight λ = 0 the DAVIS score is 55.3, about DINO's 55.1, and with λ = 0.1 it is 57.0, so the gain comes from the patch loss itself. Every ablation of the paper pre-trains a small ViT-Ti/16, a smaller Vision Transformer than ViT-S/16 with the same 16 by 16 patches, on COCO and scores DAVIS 2017 video segmentation by label propagation, which uses labelled masks. Fact

Why should this matter to a study that finds objects without labels? The decoder of Part 6 finds objects by comparing the features of patches with one another, so it depends on exactly the patch-level outputs that DINO trains only through the class token. SelfPatch gives every patch a lesson of its own; our study, in Part 5, asks how that lesson should choose the patches it learns from. Toy

4.2 Neighbours as positives

Assumes: cosine similarity (Part 1), the 14 by 14 grid of patches (Part 2), and the teacher (Part 3). Gives: the window, the cosine, the top k, the wrap at the border, and the positive set P(i).

SelfPatch's idea fits in one sentence: similar neighbouring patches are treated as positive examples, because adjacent patches often share a common semantic context. A patch of fur usually sits next to more fur, and a patch of door next to more door. So the lesson for each patch is: your token should resemble the tokens of the neighbours that look like you. Fact

Three words carry the method. The anchor is the patch whose lesson is being built; every patch takes a turn as the anchor. Its candidates are the 8 patches around it, the other cells of the 3 by 3 window centred on it. Its positives are the candidates that the rule keeps, and the anchor's lesson is built from them only. Fact

How similar is similar? SelfPatch measures it by the cosine of two patches' tokens: 1 when their 384 numbers point the same way, 0 when they are unrelated. The paper's Eq. (3) writes the cosine on the tokens of the online network, the paper's name for the student; the official code, which our trainer runs, computes it on the teacher's tokens, without gradient, inside the teacher's forward pass. The teacher is the slow average of the student from Part 3, so the choice of positives changes slowly from step to step. Fact

The official rule then keeps each anchor's 4 most similar candidates as its positives, so k = 4. Any selection rule, this one included, can be written in one form: it keeps the candidates whose similarity reaches a threshold θ (the Greek letter theta), P(i) = {j ∈ N(i) : sij ≥ θi}. The official rule sets θi to the 4th largest of the anchor's own 8 similarities, so it keeps exactly 4. Our earlier selector study, told in Part 5, changed only how θ is set. Fact

What about an anchor on the border of the grid? It has fewer than 8 real neighbours. The official code answers with a wrap-around: the window continues on the opposite edge, as if the grid were drawn on a doughnut, so a patch on the left border counts patches on the right border as neighbours and every anchor has exactly 8 candidates. The paper speaks of the 8 adjacent patches and does not mention the wrap; it comes from the code. Fact

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 anchor ordinary neighbour wrapped neighbour left edge continues on the right edge; top row continues on the bottom row
The window wraps around the border. On the 6 by 6 grid of a local crop, anchor 0 in the top-left corner has the candidates 1, 5, 6, 7, 11, 30, 31 and 35. Only 1, 6 and 7 touch it inside the picture; the other five come from the far edges. Fact

On the 14 by 14 grid of a global crop, the top-left anchor 0 has the candidates 1, 13, 14, 15, 27, 182, 183 and 195, while an inner anchor such as 15 has the ordinary ring 0, 1, 2, 14, 16, 28, 29 and 30. How often does the wrap matter? A 224-pixel crop has 196 × 8 = 1,568 anchor-to-candidate links, and 164 of them wrap: 10.5 %. A 96-pixel crop has 36 × 8 = 288 links, and 68 of them wrap: 23.6 %, because a larger share of a small grid's cells lies on its border. On any G by G grid the count is 12G − 4: each of the 4 corner anchors has 5 wrapped candidates and each of the 4(G − 2) other border anchors has 3, and 20 + 12G − 24 = 12G − 4. Fact

Neighbour similarity and the top k

s(i, j) = fθ(i)(x)⊤ fθ(j)(x) / (‖fθ(i)(x)‖2 ‖fθ(j)(x)‖2) for each j in N(i);   P(i) = the k candidates with the largest s(i, j) = {j ∈ N(i) : s(i, j) ≥ θi}, with θi the k-th largest

The paper's Eq. (3), in its own notation, and its top-k rule, written last in the threshold form that any selection rule can take. Fact

i
the anchor: one of the 196 patches of a 224-pixel crop, or of the 36 of a 96-pixel crop Fact
N(i)
its window: the 8 other cells of the 3 by 3 square around it, wrapped at the border Fact
x
the crop that the anchor and its window lie in
fθ(j)(x)
the token of patch j of the crop: a vector of 384 numbers. The subscript θ stands for the weights of the network that the paper writes here, the online network, its name for the student. The official code, which our trainer runs, reads the teacher's token f̃j in its place (a tilde marks the teacher), without gradient, and so does the worked example below. This θ is not the threshold θi further down. Fact
a⊤b
the dot product of two vectors: multiply them number by number and add; the ⊤, a transpose, is how the paper writes it
‖·‖2
the usual length of a vector, which the subscript names: the square root of the sum of its squared numbers
s(i, j)
the cosine of the two tokens: one number from −1 to 1 Fact
k
how many candidates to keep: 4 Fact
θi
the anchor's threshold: the k-th largest of its 8 cosines, one number Fact
P(i)
the positives: a set of k patch indices

Take an anchor whose toy token has three numbers, a = (1, 2, 2), and its 8 neighbours, listed in reading order from up-left to down-right. Every vector here has length 3 (for a: √(1 + 4 + 4) = √9 = 3), so each cosine is the dot product divided by 3 × 3 = 9. For the up-left neighbour (2, 1, 2): a · n = 1 × 2 + 2 × 1 + 2 × 2 = 8, and s = 8/9 = 0.8889. Toy

The toy anchor (1, 2, 2) against its 8 neighbours
PlaceTokena · nCosineRankKept, k = 4
up-left(2, 1, 2)80.88891yes
up(0, 0, 3)60.66673yes
up-right(3, 0, 0)30.33335no
left(−1, 2, 2)70.77782yes
right(2, −1, 2)40.44444yes
down-left(1, −2, 2)10.11116no
down(2, 1, −2)007no
down-right(−3, 0, 0)−3−0.33338no

Ranked from the largest: up-left 0.8889, left 0.7778, up 0.6667, right 0.4444, up-right 0.3333, down-left 0.1111, down 0 and down-right −0.3333. With k = 4 the anchor keeps up-left, left, up and right. The threshold is the 4th largest cosine, θ = 0.4444, and the same four are exactly the candidates with s ≥ θ: the form P(i) = {j : s ≥ θ} that every selection rule shares. Toy

The real model does the same with 384 numbers per token. For anchor 34 of the followed photograph, on the dog's nose, the released SelfPatch weights keep patches 47, 48, 33 and 35, the patches below-left, below, left and right of it, and drop 20, 21, 49 and 19, the three above and the one below-right. Lab 4E in 4.8 shows their cosines and lets you choose any anchor of eight photographs. Real

No gradient passes through this step. The cosines are computed from the teacher's tokens, which the loss never trains, and keeping the top k is a yes-or-no choice: nudging a cosine a little either changes nothing or swaps one candidate in or out, so it has no slope to follow. The selection steers training only through the targets it builds (4.3, 4.4), and it changes only when the teacher's tokens change, which they do slowly, by the averaging of Part 3. Fact

The rule never changes during training; what changes is what it reads. Early in a run from random weights the tokens say little about objects, and an anchor's 4 most similar neighbours are close to a random draw. As the teacher's tokens come to separate the objects, the 4 that are kept come from the anchor's own object more and more often, and the targets built from them get cleaner: better tokens give better positives, which give better targets, which give better tokens. The toy below shows the first half of that loop. Toy

0.60.70.80.91 00.511.52 s, how well the toy tokens separate the object share of the top 4 on the anchor's object chance
Toy: a disc-shaped object of 60 cells on the 14 by 14 grid; every token is s times its object's direction plus random noise of length about 1, in 16 dimensions. For the 64 anchors whose window holds both the object and the background, the line gives the share of their top 4 that lie on their own object, averaged over 8 random draws. At s = 0 the tokens carry no object and the share is about the chance level, 0.6719 (dashed); from s = 1.375 on it is 1. No network is trained here: s stands for how well a teacher's tokens separate the objects, which training raises. Toy

The wrapped window

Which of an anchor's 8 neighbours become its positives, and what happens at the border?

Toy

What you are looking at: the sample scene, your own picture or a photograph of the course, cut into the 14 by 14 grid of a 224-pixel crop. At rest the anchor is the patch at row 6, column 6 (counting from 0). Click any patch to make it the anchor. The thick outline marks the anchor; the outlined cells around it are its 8 candidates, the orange ones are the k most similar, its positives, and the table ranks all 8 from most to least similar. The k slider sets how many are kept; the official rule keeps 4. Pick a border patch to see its wrapped neighbours on the far edge, and switch the wrap off to see the border without it.

Real model versus this toy: the real similarity is the cosine of two teacher tokens of 384 numbers, each the output of 12 Transformer blocks. Here each patch is described by 8 hand-made numbers (its average colour, how much its brightness varies, where it sits, and which way its brightness changes), so the ranking only roughly resembles a trained teacher's, and the toy's cosines all sit close to 1: only their order matters. The rule itself is the real one: keep the k largest of the 8. Lab 4E in 4.8 runs the same rule on real tokens. Fact

4.3 The aggregation head

Assumes: attention with queries, keys and values, LayerNorm and the MLP (Part 2), and softmax (Part 1). Gives: how 4 positives become one target, the query token's share, and why a learned summary.

An anchor now has 4 positives: 4 tokens of 384 numbers each. The student will be asked to predict one target per anchor, so the 4 tokens must become one. A plain average would be the simplest merge. SelfPatch uses a small learned network instead, the aggregation module, which summarises a set of tokens into one token. Fact

Recall the attention of Part 2: every token asks a question with its query, and every token answers with its key and value. Class attention, a design the paper borrows from Touvron et al.'s CaiT, keeps the answering and drops most of the asking: only one token asks. That token is the query token, 384 numbers that the network learns, drawn at the start from a truncated normal distribution with standard deviation 0.02: small random numbers around 0, from a bell curve whose far tails are cut off. It attends to itself and to the set it summarises, and its answer is the summary. Fact

The module stacks 2 class-attention blocks, without LayerScale, a further idea of the same CaiT paper that the supplement says SelfPatch leaves out; the official code's block carries the name but holds no such parameters. Each is a Transformer block in which only the query token is updated: attention with 6 heads, whose result is added back onto the query token, then an MLP four times as wide as the token, added back the same way. In the first block the learned query token asks; in the second, the first block's summary asks, and the positives answer again. A final LayerNorm rescales the result. The module has 3,550,080 parameters. Fact

teacher's aggregation module query token positive 1 positive 2 positive 3 positive 4 anchor left out class attention block 1 class attention block 2 target one per anchor asks asks result positives answer
Four positives in, one target out. The learned query token asks the first class-attention block; it attends to itself and to the 4 positives, which answer with their keys and values. The first block's summary asks the second block, which reads the same positives again. After a final LayerNorm the result is the anchor's target, 384 numbers. The anchor's own token is not in the set. Blue marks what the teacher computes, orange the positives. Fact

Three details matter later. The target is built from the positives only, with the anchor's own token left out, so an anchor never learns from itself. The order of the positives does not matter: the module adds no position embedding of its own, although the tokens still carry their positions from the backbone. And the same module, run on all of a crop's tokens, makes the crop's image-level token, which takes the place of DINO's class token, because SelfPatch's backbone has none. Fact

How much of a target comes from the query token itself? Each anchor's set is its 4 positives plus the query token, a sequence of 5. Attention turns the scores into shares that add up to 1, so if all 5 scores were equal each token, the query token included, would get 1/5 = 0.2. In general, at equal scores the query token keeps 1 / (d + 1) of the attention when it summarises d tokens: 0.5 for a single positive and 0.11 for all 8. Fact

The query token is the same for every anchor, so the fewer positives an anchor has, the more its target leans towards one shared vector. Under the official rule every anchor has 4; Part 5 tells of rules under which an anchor can have 1 or all 8, and this share is one reason that matters. Toy

In the second block the question comes from the first block's summary, so the module can give less say to a neighbour that disagrees with the rest of the set: the cleaning role the paper gives it. The walk below works this out with numbers. Fact

Who trains the module? The student runs the module's query token and its two blocks only to make the image-level token; it never runs them on neighbours. Of the whole module, only the final LayerNorm also touches the student's patch tokens: each patch's own token passes through it on the way to the patch head (4.4). So the student's query token and blocks, the part that weighs the positives, learn only through the image-level loss, while the final LayerNorm also feels the patch loss. The teacher, which builds every patch target with its own copy of the module, is an average of the student's. The part that weighs the positives learns from the whole-picture lesson, never from the patch lesson. Fact

Class attention: a set of positives becomes one target

ỹ(i) = h̃({f̃j : j ∈ P(i)}); in each of the 2 blocks: q = Wq LN(z), kt = Wk LN(xt), vt = Wv LN(xt) for xt in [z, f̃j …];   at = softmaxt(q · kt / √64);   z ← z + Wo Σt at vt;   z ← z + MLP(LN(z)); after the 2 blocks, ỹ(i) = LN(z)

The paper's Eq. (5) for the teacher, with the aggregation module written out as the official code runs it, 2 class-attention blocks and a final LayerNorm, in our architecture document's notation. Fact

z
the asking token: in block 1 the learned query token, in block 2 block 1's output; 384 numbers Fact
f̃j
the teacher's token of positive j: 384 numbers; there are d = 4 of them Fact
LN
LayerNorm, as in Part 2
Wq, Wk, Wv, Wo
learned matrices of 384 by 384 numbers, split into 6 heads of 64; the formula shows one head Fact
at
the share of token t: d + 1 numbers that add up to 1, in each head Fact
ỹ(i)
the anchor's summary before the patch head: 384 numbers Fact

Toy setting: tokens of 2 numbers, one head, no learned matrices (every W is the identity), no LayerNorm and no MLP, and each score is c × (query · token) with c = 5, standing in for the learned matrices and the division by √64. The query token starts at (0, 0). Three positives agree, x1 = (1, 0), x2 = (0.8, 0.6) and x3 = (0.6, 0.8); one points away, x4 = (−0.8, −0.6). Toy

Block 1. The query is (0, 0), so every score is 5 × 0 = 0, and the softmax gives each of the 5 tokens e0 / (5 × e0) = 1/5 = 0.2: the equal-score share 1 / (d + 1) above. The output is the query plus the shared sum, (0, 0) + 0.2 × [(0, 0) + (1, 0) + (0.8, 0.6) + (0.6, 0.8) + (−0.8, −0.6)] = 0.2 × (1.6, 0.8) = (0.32, 0.16). Toy

Block 2 is asked by z = (0.32, 0.16). Its dot products with z, x1, x2, x3 and x4 are 0.128, 0.32, 0.352, 0.32 and −0.352; times c = 5 the scores are 0.64, 1.6, 1.76, 1.6 and −1.76. Their exponentials are 1.8965, 4.953, 5.8124, 4.953 and 0.172, which add up to 17.787, so the shares are 0.1066, 0.2785, 0.3268, 0.2785 and 0.0097. The odd positive's share falls from 0.2 to 0.0097. Toy

The output is z plus the shared sum: (0.32, 0.16) + 0.1066 × (0.32, 0.16) + 0.2785 × (1, 0) + 0.3268 × (0.8, 0.6) + 0.2785 × (0.6, 0.8) + 0.0097 × (−0.8, −0.6) = (1.0533, 0.5901), which points at 29.26°. The plain average of the four, (0.4, 0.2), points at 26.57°, pulled towards the odd one; the three agreeing positives' average, (0.8, 0.4667), points at 30.26°. The real module ends in a LayerNorm, so its direction is what the patch head receives. Toy

In the teacher, which builds the targets, nothing here gets a gradient: the teacher only averages the student. In the student the module runs for the image-level token, and there the gradient flows through the shares. With o = Σt at vt the attention's output, the gradient of the loss with respect to a score is ∂L/∂lt = at (vt − o) · ∂L/∂o. A token whose value points where the loss wants the output to move gets a larger score after the step, and so a larger share; the shares always add up to 1, so another token's share falls. Toy

Over training the learned matrices decide what agreeing means, and they learn it from the image-level loss alone. Nothing measures the shares of the real module in our runs, so this course has no real curve for them. What the second block can do once its scores follow agreement is drawn below with the toy: the share of the fourth positive in block 2 as it turns away from the other three. Toy

00.10.20.3 090180270360 angle of positive 4 from the other three (degrees) its share in block 2 block 1
Toy: the walk's set with x4 turned by the angle on the horizontal axis from the other three's mean direction. Block 1 always gives it 0.2 (dashed). Block 2 gives it 0.2693 when it agrees with them and 0.0095 when it points the opposite way. The dot is the walk's x4, 186.61° round. Toy

The aggregation head

How does class attention turn a set of positives into one summary, and when does it stop listening to one of them?

Toy

What you are looking at: the shares that class attention gives the query token (blue) and each positive (orange), as bars; the positives and the summary as directions on a circle, beside the plain average (grey, dashed); and a table of every number. With the scores you type, the shares are their softmax: at rest every score is 0 and each token gets 1 / (d + 1). With the scores made by the vectors, as in the walk above, block 1 shares evenly and block 2 listens less to a positive that disagrees. Change d, type a score, or turn positive 4 round the circle.

Real model versus this toy: the real module works on tokens of 384 numbers, with 6 heads of 64, learned matrices for the queries, keys, values and output, a LayerNorm before each step and an MLP in each of its 2 blocks, and its scores are q · k divided by √64 = 8. The toy keeps the shape of the computation, one asking token, softmax shares, the residual and two blocks, on 2 numbers per token. Fact

4.4 The patch loss and the total

Assumes: the projection head and its prototypes, centring and sharpening, the cross-entropy and the stop-gradient (Part 3). Gives: the patch loss, the asymmetry between teacher and student, the total L = Lglobal + 0.1 · Lpatch, and why each piece is there.

The teacher and the student treat an anchor differently, on purpose. The teacher builds the target from the anchor's positives, merged by the aggregation module. The student predicts that target from the anchor's own token, without the aggregation module. This difference is the asymmetry of SelfPatch: own token versus aggregated positives. Fact

teacher: builds the target student: predicts it from the anchor alone 4 positives anchor same crop aggregation module patch head target LayerNorm patch head prediction patch loss no gradient gradient
Own token versus aggregated positives. Both lanes start from the same anchor in the same crop. The teacher (blue) merges the anchor's 4 positives with the aggregation module and turns the result into a target through its patch head. The student (green) sees only the anchor's own token, passes it through a LayerNorm and its own patch head, and predicts the target. The patch loss compares the two; the stop-gradient (the double bar) means that only the student's lane is trained by it. Fact

Why not let both sides use the neighbours? Because pulling the tokens of neighbouring patches together invites collapse (Part 3): the easiest way to make every patch agree with its neighbours is to make every token the same, and a network that outputs one constant token has learned nothing. The authors found that the asymmetry, together with the stop-gradient, avoids the collapse that comes from pulling patch representations together. This course takes that finding from the authors; it does not show why it works. Fact

Two details come from the code. The student's prediction starts from LN(zi): its own token first passes through the aggregation module's final LayerNorm, a step the paper's equation leaves out. And the student's tokens, like the teacher's, are the backbone's last outputs, 196 tokens of 384 numbers for a 224-pixel crop, without a class token and without a final LayerNorm of the backbone. Fact

A target and a prediction are each still 384 numbers. As in Part 3, a projection head turns such a vector into one score per prototype, and a softmax with a temperature turns the scores into a probability distribution. SelfPatch gives the patches a head of their own, the patch head, with the same layers as the image-level head, 384 → 2,048 → 2,048 → 256 → 4,096: it ends in 4,096 prototypes against the image-level head's 65,536. The teacher divides its scores by 0.04 and the student by 0.1, in both heads, and the patch head has its own centre, 4,096 numbers, one per prototype. Fact

The patch loss takes every anchor, compares the teacher's target distribution with the student's prediction by the cross-entropy of Part 3, and averages. Every one of the 10 crops gets patch targets, and each student patch is compared with the target built in the same crop. That is why SelfPatch's teacher processes all 10 crops, while DINO's teacher sees only its 2 global crops. The patch loss is the average of the 10 per-crop losses. Fact

The two losses are then added. The image-level loss Lglobal is DINO's loss of Part 3, now read from the image-level token and still averaged over 18 pairs of crops. The patch loss Lpatch enters with a weight λ (the Greek letter lambda) of 0.1: L = Lglobal + 0.1 × Lpatch. In words: the total loss is the image-level loss plus one tenth of the patch loss. The student's weights move to make this total smaller; the teacher follows by averaging. Fact

The paper writes the distance between the two distributions as a KL divergence, following DINO; the code uses the cross-entropy of Part 3. The two differ only by the teacher's entropy, which has no gradient, so they train the student the same way. Fact

The patch cross-entropy and the total loss

Lpatch = (1/N) Σi H(P̃i, Pi),   P̃i = softmax((g̃′(ỹ(i)) − c′) / τt),   Pi = softmax(g′(LN(fi)) / τs),   H(p, q) = −Σm pm log qm;   L = Lglobal + λ Lpatch

The paper's Eqs. (7) and (8), with its distance D written as the cross-entropy that the official code computes, and with the patch centre, the two temperatures and the student's LayerNorm as the code applies them. Fact

N
the patches of the crop: 196 for a 224-pixel crop, 36 for a 96-pixel one Fact
ỹ(i)
the teacher's summary of anchor i's positives (4.3): 384 numbers Fact
fi
the student's own token of patch i: 384 numbers Fact
g̃′, g′
the patch heads of the teacher and the student: 384 numbers in, 4,096 scores out Fact
c′
the patch centre: 4,096 numbers, a running average of the teacher's patch scores Fact
τt, τs
the temperatures: 0.04 for the teacher, 0.1 for the student Fact
P̃i, Pi
the target and the prediction: 4,096 probabilities each, adding up to 1 Fact
H
the cross-entropy, one number in nats; the paper writes its distance as D Fact
λ
the patch loss's weight: 0.1 Fact

Toy setting: one anchor and 4 prototypes in place of 4,096. The teacher's head gives the scores (0.10, 0.04, 0, −0.02) and the centre is 0; the student's head gives (0.20, 0.10, 0, 0.10). Toy

The target. Divided by τt = 0.04 the scores become (2.5, 1, 0, −0.5). Their exponentials are 12.1825, 2.7183, 1 and 0.6065, adding up to 16.5073, so P̃ = (0.738, 0.1647, 0.0606, 0.0367). Most of the target sits on prototype 1: the low temperature sharpens it. Toy

The prediction. Divided by τs = 0.1 the scores become (2, 1, 0, 1). Their exponentials are 7.3891, 2.7183, 1 and 2.7183, adding up to 13.8256, so P = (0.5344, 0.1966, 0.0723, 0.1966), and log P = (−0.6265, −1.6265, −2.6265, −1.6265). Toy

The cross-entropy adds up the target's probabilities times minus the logarithms of the prediction: 0.738 × 0.6265 + 0.1647 × 1.6265 + 0.0606 × 2.6265 + 0.0367 × 1.6265 = 0.4624 + 0.2678 + 0.1591 + 0.0598 = 0.9491 nats. The target's own entropy is 0.8125, so the KL divergence, the paper's D, is 0.9491 − 0.8125 = 0.1366: the same loss minus a number that the student cannot change. Toy

The total. With a toy image-level loss of 3, and this anchor standing for the whole patch loss, L = 3 + 0.1 × 0.9491 = 3.0949: the patch term adds 0.0949. Toy

The gradient of the cross-entropy with respect to the student's scores is (P − P̃) / τs, one number per prototype: here (−2.0356, 0.3194, 0.1175, 1.5987). Gradient descent moves each score against its gradient, so the score of prototype 1, where the target is larger than the prediction, rises, and the score of prototype 4, which the student favours more than the teacher does, falls. The four numbers add up to 0, because both distributions add up to 1. Through the total, the patch term's gradients are scaled by λ = 0.1 and shared out over all the anchors that the loss averages; the teacher's side gets nothing, because its target sits behind the stop-gradient. From the scores the gradient runs back through the patch head into the student's own token and on into the backbone. Toy

Over training both sides move: the student's predictions move towards the targets at every step, and the targets move because the teacher averages the student. With the target held fixed, as in the toy below, gradient descent brings the cross-entropy down towards the target's entropy, 0.8125, its floor: the cross-entropy can never fall below the target's own spread, and only the KL divergence can reach 0. Toy

0.80.840.880.920.96 010203040 step of gradient descent cross-entropy (nats) floor: the target's entropy
Toy: gradient descent with learning rate 0.005 on the student's four scores of the walk, with the target held fixed. The cross-entropy falls from 0.9491 to 0.8156 in 40 steps, towards the floor 0.8125 (dashed). Toy

There is no real curve of SelfPatch's patch loss in this course: our three runs replaced that term with the contrastive term of Part 5, and the bundle holds their telemetry. Fact

4.5 The model in numbers

Assumes: parameters, tensors and shapes (Part 2), and the projection head (Part 3). Gives: what each part of SelfPatch costs, and how much work one optimiser step does.

Every learned number in a network is a parameter. The table counts them for the SelfPatch student as the training code builds it. Fact

The SelfPatch student, part by part
PartWhat it doesParameters
Backbone (ViT-S/16 without a class token)turns a crop into patch tokens21,664,128
Aggregation modulemerges tokens into one: an anchor's target, or the image-level token3,550,080
Image-level projection head384 numbers in, 65,536 scores out22,352,128
Patch projection head384 numbers in, 4,096 scores out6,562,048
The whole student54,128,384

Of the student's 54,128,384 parameters, 54,058,752 are trained by gradient descent. The other 69,632 stay frozen: they are the fixed prototype lengths of the two heads, 65,536 + 4,096. Most of the image-level head sits in its last layer, 16,842,752 parameters, a direction of 256 numbers and a length for each of its 65,536 prototypes; the patch head's last layer holds 1,052,672. The three parts after the backbone hold about 32.5 M parameters, which exist for training only. The teacher is an identical copy with the same 54,128,384 parameters, all changed only by averaging. Fact

Now count the work in one optimiser step. Our runs use a batch of 256 images per step. Each image gives 2 global crops of 196 anchors and 8 local crops of 36 anchors: 680 anchors per image. With 8 candidates each, that is 5,440 candidate links, and 3,136 of them, 57.6 %, come from the two 224-pixel crops. Fact

Anchors and links in one optimiser step at a batch of 256
CountPer imagePer step
Anchors680174,080
Candidate links5,4401,392,640

So one step handles 174,080 anchors and 1,392,640 candidate links, 256 × 680 × 8. Under the official rule each anchor ranks its own 8; the batch rule of our earlier selector study, told in Part 5, took one median over all 1,392,640 of them. Fact

Inside the computer these numbers travel in tensors: blocks of numbers arranged along several axes, with a shape written as sizes joined by ×. For example B × 196 × 384 means B images, 196 tokens per image and 384 numbers per token. The work is shared between several graphics processors, and B is the number of images on one of them: 256 divided by the number of processors. Fact

Tensor shapes in one step, for one crop of each size
What224-pixel crop96-pixel crop
Crops entering the backboneB × 3 × 224 × 224B × 3 × 96 × 96
Tokens leaving the backbone, teacher and student alikeB × 196 × 384B × 36 × 384
The teacher's similarities and the selection mask: for each anchor, one number or one yes-or-no per candidateB × 196 × 8B × 36 × 8
The teacher's aggregation output: the image-level token, then one summary per anchorB × 197 × 384B × 37 × 384
Image-level scores, for every cropB × 1 × 65,536B × 1 × 65,536
Patch scoresB × 196 × 4,096B × 36 × 4,096

The shapes come from our architecture document, which lists them per crop size; in B × 196 × 8 the last size is the 8 candidates of each anchor, and the teacher fills these rows without gradient. The patch term's targets are large: for one micro-batch of 32 images over the ten crops they are 32 × 680 rows of 4,096 numbers of 4 bytes each, about 357 MB, and the student's patch probabilities are about as large. Fact

4.6 One step, from end to end

Assumes: 4.1 to 4.5, and AdamW and the EMA (Part 3). Gives: the order of one training step with its tensor shapes, one picture followed through a whole step of a small network, and the loop by which the model trains itself.

Sections 4.1 to 4.5 took the method apart. This section puts it back together twice: Lab 4B steps through one optimiser step in nine stages, with the real tensor shapes, and Lab 4C follows one picture through a whole step of a small network that keeps the real design. First, the loop that both of them are one turn of. Toy

teacher's tokens every crop, no gradient positives top 4 of 8 by cosine targets aggregation, patch head the student learns loss, gradient, AdamW the teacher follows average of the student no labels anywhere: each target comes from the model's own past
The loop that one training step turns once. The teacher's tokens choose each patch's positives; the positives become targets; the student learns to predict them; the teacher moves a little towards the student; and the next step starts from the teacher's new tokens. Better tokens give better positives, which give better targets, which give better tokens. Toy

Nothing in this loop needs a label. The targets come from the teacher, the teacher is an average of the student's past weights, and the positives come from the teacher's own tokens. What keeps the loop from settling on one answer for every patch is a set of guards: the stop-gradient, so the student cannot move its own targets; the averaging, so the targets change slowly; the asymmetry of 4.4; and the centring and sharpening of Part 3, which SelfPatch applies in both heads. Fact

One training step, stage by stage

What happens, and in what order, when SelfPatch takes one optimiser step?

Toy

What you are looking at: one optimiser step of SelfPatch in 9 stages: the picture, its 10 crops, the teacher's forward pass, the selection of positives, the aggregation targets, the student's forward pass, the losses, the update of the student's weights, and the averaging step that moves the teacher. Next and Prev move one stage; Play steps through them for you. At each stage a diagram shows where the data is, a list gives the tensors produced and their shapes, such as B × 196 × 384 for the tokens of a global crop and B × 1 × 65,536 for the image-level scores, and the pictures follow one crop and one patch. Blue marks the teacher, green the student, orange the positives. The losses stage shows Lglobal over 18 pairs of crops, Lpatch per crop and the total with weight 0.1.

Real model versus this toy: the stages, their order, the tensor shapes, the counts and the settings are the real ones, with B images per processor. What happens to the picture is a toy: the page cuts the crops itself, makes tokens with a fixed random projection, measures similarity on 8 simple numbers per patch, averages the positives where the real model runs its aggregation module, scores 12 toy prototypes in place of 4,096, and moves a few made-up weights. The real student has 54,128,384 parameters. Fact

The SelfPatch paper draws the whole method in its Figure 2: two rows, image-level self-supervision above patch-level self-supervision, and a side panel for choosing positives. The figure below redraws it in this course's colours, green for the student, blue for the teacher and orange for the positives, and keeps the paper's own labels, the online network for the student and the momentum network for the teacher. Fact

SelfPatch, redrawn after Figure 2 of the paper with the paper's notation. Top row: the image-level loss between two views x and x⁺. Bottom row: the patch-level loss, the teacher's positive matching and aggregation against the student's own token. Side panel: the positives P(i) of patch i inside its window N(i). The dashed arrow is the teacher's averaging, and the double bar the stop-gradient. Fact

Read the notation once and the paper's equations become readable: f is the backbone, h the aggregation module, g the image-level projection head and g′ the patch-level one, D the distance, sg the stop-gradient, P(i) the positives of patch i, N the number of patches, x and x⁺ the two views, θ the weights, and a tilde marks the teacher's copies. With it the paper's image-level loss is D(g(y), sg(g̃(ỹ))), its patch loss is (1/N) Σi D(g′(f(i)), sg(g̃′(ỹ(i)))), with each student patch predicting from its own token and the teacher from its aggregated positives, and the total adds them with λ. These are the paper's Eqs. (6) to (8). Fact

The positives listed in the figure's side panel are toy: Lab 4C's small network picked them with random weights on global crop 1 of the drawn sample. That crop covers 65 % of the picture and is flipped left to right, colour-jittered and blurred, as the lab's second stop shows, so the scene appears mirrored. The figure was computed once with the page's own painting of the sample; your browser paints the sample with its canvas, whose pixels can differ slightly, so the lab's live map can list other toy positives. Toy

Lab 4C runs a miniature of this network in your browser and shows its numbers. It keeps the real design: 12 blocks with 6 attention heads each, 196 patches of 768 numbers per 224-pixel crop, the aggregation module and both heads. Only the widths shrink and the weights are random: a token holds 48 numbers where the real one holds 384, and the lab writes each toy width beside the real one. It computes three of the 10 crops. Fact

Its step follows the recipe of our earlier selector study, the runs that kept SelfPatch's loss (Part 5): a peak learning rate of 5e-4, 9,240 steps in 20 epochs, gradient clipping at 3.0, and the first epoch with the prototypes held fixed. Fact

The lab walks through the step in fourteen stops, in four stretches. From pixels to tokens (stops 1 to 4): a real step cuts 10 crops from the picture; a 224-pixel crop is 3 × 224 × 224 numbers, cut into 196 patches of 16 by 16 pixels, 768 numbers each, and the patch embedding turns each patch into a token, 768 → 384, and adds its position row. Fact

Through the backbone (stops 5 and 6): the tokens pass through 12 blocks. In each, every token gathers from the others by attention and passes through the MLP, both results added back onto it. Each block hands the next one the same shape, so a global crop leaves the backbone as 196 × 384 numbers. Fact

Targets, guesses and losses (stops 7 to 11): the teacher runs the network on all 10 crops without gradient. For each patch it keeps the 4 most similar of its 8 neighbours, merges them into a target and makes probabilities at temperature 0.04. The student predicts from the patch's own token at temperature 0.1. Cross-entropy scores each guess, and L = Lglobal + 0.1 × Lpatch. Fact

The update (stops 12 to 14): the backward pass gives each student weight its gradient. Each tensor's gradient is clipped to a length of at most 3.0, AdamW moves the weights, and the teacher averages. Fact

How does the update use the gradient? AdamW keeps two running averages for every weight, its moments: m of the gradient, keeping 0.9 of its old value at each step, and v of the squared gradient, keeping 0.999. Both start at 0, so their first averages are too small, and dividing them by 1 − 0.9t and 1 − 0.999t at step t makes up for it. The step then subtracts the learning rate times m / (√v + ε) from the weight, with ε = 1e-8, so a weight whose gradient keeps the same sign moves by about the learning rate, whatever the gradient's size. Weight decay also pulls the weight matrices towards zero. Fact

In the selector study's recipe the learning rate warms up linearly to 5e-4 over 4,620 steps, then falls along a cosine towards 1e-6 by step 9,240. The last layer of each head, which holds its prototypes, stays fixed for 1 epoch, the first 462 steps; DINO's code notes that this helps training. Fact

Does the step help? The lab runs the student again on the same crops, against the same targets, and shows the loss before and after. Each weight that is not held fixed moves against its own gradient, so a small enough step lowers the loss; a larger one can overshoot, and the lab says which happened. Repeated over many steps, this is how the patch loss teaches: each patch's own token learns to predict what the teacher makes of the neighbours that look like it. Toy

One picture, end to end

What happens to one picture, number by number, from its pixels to the update of the weights?

Toy

What you are looking at: the map at the top is a live copy of the figure above. The current stop's boxes are lit, a click on a box jumps to its stop, and the side panel follows your patch. Below it are the fourteen stops, in order: the picture is numbers; three views of it; cut into 196 patches; 768 numbers become a token; through the 12 blocks; what leaves the backbone; the teacher does the same, without gradient; each patch looks at its 8 neighbours; the teacher merges the 4 positives into a target; the student predicts from its own token; the losses score the guesses; the gradient flows back; AdamW moves the weights; the teacher follows slowly. Prev, Next and Play move between them, and stop 5 has its own block slider. At rest the lab follows the patch at row 5, column 7 of the first global crop (counting from 0); click the grid to follow another. You can also draw new random weights, switch to DINO's wiring (197 tokens with a class token and a final LayerNorm, and no patch loss), switch on stochastic depth, and pick the step t, from 1 to 9,240, whose schedules the update uses.

Real model versus this toy: the wiring, the depth, the 6 heads, the 196 and 36 tokens of a crop and the recipe's settings are the real ones; only the widths shrink. A token has 48 numbers for the real 384, an attention head 8 for 64, the projection heads end in 64 prototypes for the real 65,536 and 4,096, and the weights are random and untrained. The lab computes 3 of the 10 crops, so the image-level loss uses 4 of the 18 pairs and the patch loss averages 3 crops. At every step t the lab starts from the same fresh network, the teacher equal to the student, while a real run at step t carries all its earlier steps. Its recipe is the selector study's; our three runs of Part 5 used another. Whether one step on one picture lowered the loss says nothing about a real run of 9,240 steps. Fact

4.7 SelfPatch's own results, and why they are not our endpoint

Assumes: 4.1 to 4.4. Gives: how SelfPatch was trained and judged, our check of its released checkpoint, and why none of its numbers can answer our question.

SelfPatch pre-trains ViT-S/16 on ImageNet for 200 epochs with a batch of 1,024 images. Its official script starts from random weights and loads no pretrained model: DINO's objective and SelfPatch's are trained together from the first step, with DINO's optimiser and schedule, AdamW with a linear warm-up over 10 epochs and a cosine decay. DINO's rule sets the peak learning rate to 0.0005 × 1,024 / 256 = 0.002. Fact

The patch loss adds about 21 % to the training time per epoch, so the authors train 200 epochs against the 300 of their DINO baseline, a separate public model, to keep the comparison fair; they report that DINO + SelfPatch is 1.24 times faster than DINO in total running time. One caveat: the official script's default is 300 epochs and the command in its instructions sets none, while the paper states 200. Fact

The paper's ablations, the source of every DINO-versus-variant score in 4.1 to 4.4, use less: a small ViT-Ti/16 pre-trained on COCO's training images for 200 epochs at a batch of 256, with 2 global and 2 local crops and 4,096 prototypes in both heads, about 23.7 M image presentations against about 256 M for the main run. Fact

How did the authors show that SelfPatch helps? Through downstream tasks: after the label-free pre-training, the network is put to work on a task with human labels, such as finding and outlining every object, and scored. For COCO the paper fine-tunes a Mask R-CNN detector with an FPN, standard detection networks that this course does not take apart, under the standard 1× schedule, a fixed length of fine-tuning, using COCO's human labels, and scores box and mask average precision (AP), from 0 to 100. For ADE20K it fine-tunes a Semantic FPN, a standard network that gives every pixel a class, on labelled scene photographs and reports mIoU. DAVIS 2017 carries labelled masks from frame to frame of a video with the frozen patch features; its score (J&F)m is the average of a region similarity J and a contour accuracy F. Fact

SelfPatch's downstream results as the paper reports them (points out of 100)
MeasurementHow labels enterDINODINO + SelfPatch
COCO box APMask R-CNN fine-tuned with COCO's labels40.842.1
COCO mask APthe same fine-tuning37.338.5
ADE20K mIoUa segmenter fine-tuned with ADE20K's labels38.341.2
DAVIS 2017 (J&F)mlabel propagation on frozen features60.762.7

DINO here is a public ViT-S/16 trained for 300 epochs, and DINO + SelfPatch is trained for 200. Every number of the table comes from supervised fine-tuning or from label propagation. Fact

Our study measures something else. The label-free decoder of Part 6 reads the frozen tokens of a checkpoint and finds masks without any labels, and only then are the masks scored once against human outlines. A fine-tuned detector's AP and a label-free decoder's score are two kinds of number that cannot be compared, and none of the paper's numbers can tell us whether a rule for choosing positives helps label-free object discovery. Fact

We have checked one of the table's numbers ourselves, as an artefact check. Our re-evaluation of the released SelfPatch Mask R-CNN checkpoint on all 5,000 images of COCO val2017 gave 42.09 box AP, against 42.1 in the paper, and 38.46 mask AP, which rounds to the paper's 38.5. It shows that the released checkpoint, the scoring program, the data and the configuration fit together; it says nothing about whether our rules help label-free segmentation. Fact

Which run made the released DINO + SelfPatch file is an open question: it is a SelfPatch run from scratch of 200 or 300 ImageNet epochs, since the paper's dense-task model has 200 epochs, the instructions' command uses the code's default of 300, and the file carries no record of its epochs. It is not a DINO model fine-tuned with SelfPatch. Fact

Our adapted DINO baseline, also a supervised Mask R-CNN result, scored 36.19 box AP and 33.47 mask AP, below the paper's 40.8 and 37.3: DINO's file would not load into SelfPatch's detection code as it was, and our own adapter is a diagnostic that does not reproduce the paper's DINO row. The gap between 38.46 and 33.47 must not be read as a measured SelfPatch improvement. Fact

4.8 Real neighbours

Assumes: 4.2, and the eight photographs of the course (Start here). Gives: the released model's real window positives on real photographs, and the observation our own rule starts from.

Everything so far used toy numbers. Lab 4E uses real ones: the 196 tokens of a photograph's 224-pixel view under the released DINO + SelfPatch checkpoint, its teacher's weights, computed once by the course's bundle script and stored with 8 bits per number. Click any patch: the lab ranks its 8 window neighbours by their real cosines, keeps the top k, and beside them shows the cosine to every patch of the crop. Real

Real neighbours

Which of its 8 neighbours does a patch keep under the released SelfPatch model, and where in the crop are the patches most like it?

Real

What you are looking at: one of the eight photographs of the course as its 224-pixel view, cut into 14 by 14 patches. At rest the anchor is patch 34 of the followed photograph, on the dog's nose. The lab shows the photograph chosen last on this page, so if you picked another one in a lab above it starts there, and Back to patch 34 keeps the photograph you are on. Its window is outlined: orange for the k kept neighbours, grey dashes for the others, a small corner mark where the window wraps round the border. The middle picture enlarges the window and writes each neighbour's real cosine and rank; the table lists them. The right picture colours every patch of the crop by its cosine to the anchor and outlines, in ink dashes, the 8 most similar patches of the whole crop. Click any patch, choose another photograph, or change k.

Real model versus this toy: the tokens and cosines are the released model's own, read from the bundle; the photograph under them is drawn by your browser from the same image file, so its pixels can differ from those the model saw by a few levels. Storing the tokens with 8 bits per number changes their cosines by a few thousandths at most; each tokens file records its own largest change. Real

On the released model the patches most like an anchor are often outside its window: in our premise tests only 43.6 % of an anchor's 8 most similar patches lie inside its 3 by 3 window, at a mean grid distance of 2.65, and of an anchor's 4 most similar patches in the whole crop, 58.7 % lie inside its window at 224 pixels. A patch's most similar partners are often further away than one step. Fact

Try the map in Lab 4E on the followed photograph. Anchor 34, where the lab starts, is an exception: 7 of its 8 most similar patches lie in its window. Click patch 0 in the top-left corner: only 3 of its 8 do, and the other five lie two to four rows or columns away. Real

That observation is where our rule begins. Part 5 keeps DINO's image-level loss, drops SelfPatch's window and patch loss, and ranks all 195 other patches of a 224-pixel crop to choose positives anywhere in it, with negatives and a contrastive loss: L = Lglobal + λ Lcon. Fact

Glossary of this page

Aggregation module
SelfPatch's small learned network that summarises a set of tokens into one: a learned query token asks two class-attention blocks, and a final LayerNorm rescales the answer. It makes each anchor's target from its positives, and the crop's image-level token from all of its tokens.
Anchor
The patch whose lesson is being built. Every patch of a crop takes a turn as the anchor, and its target is made from its positives.
Asymmetry
The difference SelfPatch builds in between its two networks: the teacher makes each target from the anchor's aggregated positives, while the student predicts it from the anchor's own token alone.
Backward pass
The computation that runs after the loss is measured. It goes back through the network's operations in reverse order and finds, for every adjustable weight, how the loss would change if that weight moved a little: the weight's gradient.
Bias correction
The step of AdamW that divides its two running averages by one minus their keep rate raised to the step number, which makes up for their start at zero.
Candidate
One of the 8 patches in an anchor's 3 by 3 window, among which its positives are chosen.
Centring
Subtracting the centre, a running mean of the teacher's scores, before the teacher's softmax. It stops one prototype from winning for every picture. SelfPatch keeps one centre for each of its two heads.
Class attention
Attention in which only one token asks: the query token attends to itself and to the set it summarises, and it alone is updated. SelfPatch borrows it from the CaiT model of Touvron and colleagues.
Class token
An extra learned token that DINO places in front of the patch tokens. Every block lets it gather information from all the patches, and its output summarises the whole picture. SelfPatch's backbone has none: its aggregation module makes the summary.
GELU
A smooth bend applied to every number between two linear maps: positive numbers pass almost unchanged and negative ones are squashed towards zero.
Gradient
For every weight, the direction and size of the change that would raise the loss fastest. Learning moves each weight a small step the opposite way.
Gradient clipping
Shrinking a gradient that is longer than a set limit down to that length before the weights change, so that one unusual batch cannot move the weights too far.
LayerNorm
A step that shifts and rescales each token so that its numbers have average zero and spread one, followed by a learned scale and shift.
MLP
Short for multilayer perceptron: linear maps with a bend such as GELU between them. In each block it widens every token and narrows it back.
Moment (in AdamW)
One of the two running averages that AdamW keeps for every weight. The first moment, m, averages the weight's recent gradients; the second moment, v, averages their squares. AdamW moves the weight by the learning rate times m divided by the square root of v, so a weight with a steady gradient moves by about the learning rate, whatever the size of its gradient.
Patch head
SelfPatch's projection head for patches, with the same layers as the image-level head and 4,096 prototypes at its end. It turns a patch's target or prediction into one score per prototype.
Positive
A candidate that the selection rule keeps for an anchor; SelfPatch keeps the 4 most similar of the 8. The anchor's target is built from its positives only.
Query token
The single learned token that asks in class attention: 384 numbers, the same for every anchor. Its answer, after the blocks, is the summary.
Residual connection
Adding a step's input back onto its output, so the step only has to learn a change and the original token passes straight through.
Selection mask
For every anchor patch, one yes-or-no mark per candidate neighbour: yes where that neighbour is kept as a positive. It has the same shape as the table of similarities it was made from.
Sharpening
Using a low teacher temperature so that the teacher's probabilities clearly favour a few prototypes.
Stochastic depth
A training trick in which the student randomly skips a block's residual branches (its attention and MLP steps) for some pictures, which adds a little randomness to training.
Tensor
A block of numbers arranged along several axes, such as the tokens of a batch of crops, B × 196 × 384.
Tensor shape
The size of a block of numbers along each of its directions, written with × between the sizes. For a stack of crops it reads: pictures × colour channels × height × width.
Window
The 3 by 3 square of patches centred on an anchor. Its 8 cells other than the anchor are the anchor's candidates; in SelfPatch's code it wraps round the border of the grid.
Wrap-around
The official code's rule at the border of the grid: the window continues on the opposite edge, so every anchor has exactly 8 candidates.