From Pixels and Words to Semantic Search
On this page84
A beginner-first tutorial on representations, pixels, features, embeddings, image and text encoders, shared vector spaces, and measured CLIP, SigLIP, and DINO experiments.
Article details
- Status
- Building Publicly
- Subcategory
- ClusterLens
- Last reviewed
- 2 Sept 2026
- Prerequisites
- None; the article starts from pixels and vectors
IMG_1042.jpg
DSC_8821.jpg
20260814_173411.jpg
1. What is a representation?
IMG_1042.jpg
1920 × 1080
JPEG
captured at 14:32
a red sports car on a road
raw pixels: [241, 36, 42, 239, 35, 40, ...]
colour histogram: [0.42, 0.18, 0.14, ...]
learned vector: [0.12, -0.34, 0.81, ...]
| Representation | Preserves | Discards or hides |
|---|---|---|
| filename | file identity and perhaps human labels | most visual content |
| metadata | size, time, camera, format | subject and appearance |
| caption | concepts expressible in language | exact pixels and fine layout |
| raw pixels | nearly all decoded visual measurements | robust semantic relationships |
| histogram | colour distribution | object position and shape |
| embedding | relationships learned during training | details the objective did not reward |
A representation is not neutral. Its construction decides which differences later algorithms can observe.
Interactive representation switcher
Choose a description of the same red-car photograph.
Excellent for exact file identity. It says nothing reliable about a car unless a person named it helpfully.
Detailed measurements of colour at fixed positions. A tiny translation changes thousands of corresponding coordinates.
Human-chosen measurements. Easier to interpret, but limited by what the designer anticipated.
A learned feature vector. Its usefulness is inspected through neighbours and tasks, not by naming each coordinate.
A comparison that exposes the choice
2. How a computer initially sees an image
Interactive lesson · from image file to model input
1. The file and the visible picture are not the same thing
A JPEG file stores compressed data. A decoder turns that data into the pixel grid that a screen can display.
What to remember: decoding gives us coloured pixels. It has not yet discovered objects or meaning.
2. Zoom in on one pixel
Select the top-left square. Its address is row 1, column 1. Its colour is stored as three numbers in the order red, green, blue.
row 1, column 1
This pixel = RGB(255, 0, 0)
0 means none of that colour. 255 means the maximum amount.Why 0–255? Each channel commonly uses 8 bits. Eight bits can describe 256 levels: the integers from 0 through 255.
3. Repeat the recipe for every square
Now inspect all four addresses. White is not a special word to the computer; it is simply maximum red, maximum green, and maximum blue together.
The complete decoded image is therefore a grid in which every location holds a three-number RGB recipe.
4. Separate the colour recipe into three layers
Another way to view the same data is to collect all red values into one grid, all green values into another, and all blue values into a third. These are called channels.
The three channel grids still describe exactly the same picture. We have only reorganized the numbers.
5. “Shape” is just a count of the axes
An array’s shape tells us how many positions exist along each direction. It does not describe circles or rectangles inside the photograph.
So [2, 2, 3] means “two rows, two columns, and three colour values at every location.”
6. A model may ask for the axes in a different order
Image files and many image libraries use height–width–channels. Deep-learning libraries often move channels to the front. No information changes; the drawers are merely rearranged.
The leading 1 says that this batch contains one image. A batch of 32 images would begin with 32.
7. Finally, prepare the numbers for the model
Models are usually trained with smaller numeric ranges. A simple scaling step divides each channel by 255.
A model may then apply its own training mean and standard deviation. That recipe must match the recipe used when the model learned.
Important: after all seven steps we still have prepared pixels—not meaning and not an embedding. The encoder must learn useful visual patterns from these numbers.
Scaling and normalization are different operations
Step 1: scaling changes the numeric range
Scaling rule
channel is the stored 0–255 value; scaled is the corresponding 0–1 value.
Worked scaling example
The amount of colour did not change. Only its numeric representation changed: 204/255 and 0.80 describe the same intensity.
Step 2: normalization adds the training context
Normalization rule
Subtracting the mean centres the data. Dividing by the standard deviation expresses the result in units of typical variation.
Worked normalization example
The positive result says this channel is 1.2 standard deviations above the training mean.
At this point we still have prepared pixel values. We do not yet have a semantic embedding.
3. Why not search using raw pixels?
Run the one-pixel experiment
Interactive experiment · same appearance, different coordinates
Inspect one fixed addressrow 4, column 2
match: difference 0
The copy occupies the same coordinates, so every comparison lines up.
The same failure appears in real photographs
| Candidate | Human judgement | Raw-pixel problem |
|---|---|---|
| exact copy | same image | works well |
| JPEG copy | same apparent image | compression changes values |
| one-pixel shift | same subject and scene | coordinate alignment breaks |
| brighter copy | same subject and layout | most intensities change |
| crop | same subject may remain | dimensions and positions change |
| different red object | different subject | matching colour can look deceptively close |
Tiny dry run
Distance from original to shifted copy
Distance from original to aligned gray pattern
A detailed representation is not automatically a useful similarity representation.
4. From an image to features—and then to an embedding
Feature-extraction workbench
Interactive experiment · turn one image into measurements
Start with the decoded photograph.
The photograph is still a pixel grid. No feature measurements have been selected yet.
One image becomes one ordered list
The order is part of the contract. Coordinate 1 always means redness in this toy representation; swapping coordinates would change the meaning.
A vector is also a point
Visualizing a two-feature representation
Ferrari and apple agree strongly on redness. Ferrari and Porsche agree strongly on edge density. Which pair is “nearer” depends on which measurements and weights define the space.
Similar objects are represented by nearby points; dissimilar objects are represented by distant points.
Worked comparison
| Object | Redness | Brightness | Edge density | Roundness |
|---|---|---|---|---|
| Ferrari | 0.82 | 0.64 | 0.71 | 0.31 |
| red apple | 0.88 | 0.60 | 0.22 | 0.91 |
| blue Porsche | 0.12 | 0.61 | 0.69 | 0.30 |
Weighted squared distance
j selects a feature, wj controls its importance, and the squared difference measures disagreement on that feature.
From hand-designed features to learned embeddings
| Hand-designed feature vector | Learned embedding |
|---|---|
| a person defines redness or edge density | training discovers useful mixtures of evidence |
| coordinates usually have explicit names | meaning is distributed across many coordinates |
| designed for anticipated variations | can learn invariances from examples |
| quality depends on human rules | quality depends on data, objective, architecture, and training |
How can we visualize a 512-dimensional embedding?
Five rules to carry forward
5. What is an embedding?
The encoder contract
image is the prepared pixel tensor, f is the encoder, θ is everything the encoder learned, and z is the resulting embedding.
Every embedding is a vector; not every vector is an embedding
| Representation | Where do the numbers come from? | What shapes proximity? |
|---|---|---|
| raw pixels | image decoder | matching values at fixed coordinates |
| colour histogram | human-written counting rule | similar colour proportions |
| hand feature vector | human-selected measurements | chosen features and weights |
| random vector | random generator | nothing useful by design |
| learned embedding | trained encoder | training data and objective |
How training creates meaning
Conceptual training pressure
Real objectives have precise formulas. This version exposes their purpose: penalize a geometry that disagrees with the relationships supplied by training.
Same images, different objective, different embedding
Why individual dimensions are hard to name
Interactive proof · coordinates can change while geometry survives
car A coordinates[0.80, 0.20]
car B coordinates[0.70, 0.30]
distance A ↔ B0.141
The coordinates describe the points relative to the current axes. Car A and car B are close.
What does embedding dimension mean?
Interactive experiment · embedding capacity and storage
128 dimensions can be a compact representation, but adequacy depends on the model, data, and task—not the number alone.
Raw vector-storage estimate
This estimates only raw vectors. Index structures, identifiers, metadata, allocator overhead, and replicas require additional space.
How do we know whether an embedding is good?
| Test | Keep fixed | Change | Desired observation |
|---|---|---|---|
| translation | subject and scene | move image a few pixels | embedding changes little |
| brightness | subject and layout | lighten or darken | neighbourhood stays useful |
| viewpoint | object identity | camera angle | same object/class remains nearby |
| negative pair | colour or background | subject | different subjects stay separable |
| duplicate test | apparent image | compression/resize | duplicate remains very near |
| collapse test | nothing | many unrelated images | embeddings do not all become identical |
Complete neighbourhood dry run
| Rank | Subject-trained space | Colour-trained space |
|---|---|---|
| 1 | Porsche | red apple |
| 2 | Lamborghini | red shoe |
| 3 | race car | fire truck |
| 4 | sports coupe | red rose |
| 5 | blue Ferrari | red Ferrari toy |
Five-nearest-neighbour accuracy
If 84 of 100 hidden images receive the correct neighbour vote, accuracy is 84/100 = 0.84, or 84%.
An embedding does not contain universal meaning. It contains geometry learned under a particular training contract, and that geometry earns trust through experiments.
6. How an image becomes an embedding
Stage 1: create the exact input the model expects
| Operation | What happens | Why it matters |
|---|---|---|
| decode | compressed bytes become RGB pixels | different decoders must agree on colour and orientation |
| apply orientation | EXIF rotation or mirroring is resolved | a sideways image is a different pixel arrangement |
| convert colour | grayscale, RGBA, or CMYK becomes expected RGB | the model expects a fixed channel contract |
| resize | image is scaled toward the model’s input size | neural layers expect compatible spatial dimensions |
| crop or pad | final width and height are produced | cropping can remove evidence; padding adds context |
| scale and normalize | channel values follow the training recipe | wrong statistics shift every downstream activation |
| add batch axis | one or more images are grouped | model input commonly begins with batch size |
Example input shape
This tensor contains 1 × 3 × 224 × 224 = 150,528 prepared channel values.
Stage 2A: the convolutional path
Dry run: scan a vertical-edge filter
Runnable convolution · slide one learned filter over an image
6×6 input
3×3 filter
4×4 feature map
large value = edge detectedOne convolution response
The result 3 is written into the feature map at the window's current position. A real layer learns many filters rather than receiving this hand-written one.
Step through a CNN encoder
CNN dry run · local filters become one whole-image vector
1. Begin with prepared pixels
At this point the model has RGB values arranged by location. It has not yet produced learned visual features.
2. Many filters scan the same input
One learned filter produces one output channel. A layer with 64 filters produces 64 feature maps, each responding differently across space.
3. An activation changes which responses continue
In this teaching example, ReLU replaces negative responses with zero and keeps positive responses. Non-linearity lets stacked layers represent more than one giant linear transformation. Modern CNNs may use other activations.
4. Pooling or strided layers reduce spatial size
This 2×2 max-pooling example turns a 4×4 map into a 2×2 map. Downsampling lowers computation and makes small movements less disruptive, but it also discards exact location.
5. Collapse all remaining locations into one embedding
7 × 7 each
pooling →
projection →
The last spatial grid disappears only near the end. The resulting 512 values summarize evidence from the whole image and can be compared with other embeddings from the same model.
From one filter to a hierarchy
| Stage | Tensor shape | Intuition |
|---|---|---|
| input | [1, 3, 224, 224] | three colour channels |
| early feature maps | [1, 64, 112, 112] | many local response maps |
| middle feature maps | [1, 256, 28, 28] | richer evidence over larger context |
| late feature maps | [1, 1024, 7, 7] | 1,024 channels at 49 spatial locations |
| global pooling | [1, 1024] | one value per channel |
Pooling removes the remaining spatial grid
Global average pooling
Repeat this for every channel. A 7×7×1,024 feature tensor then becomes a vector with 1,024 values.
Stage 2B: the Vision Transformer path
Patch count
Each RGB patch initially contains 16 × 16 × 3 = 768 channel values before its learned linear projection.
Vision Transformer dry run · one image becomes communicating tokens
1. Draw a patch grid over the image
The teaching picture uses 4×4 = 16 patches so we can see them. A 224px image with 16px patches has 196.
2. Flatten and project every patch
[.21, −.08, .44, …]
All raw values from one patch are mixed into a token vector. The projection weights are learned during training.
3. Tell the model where every token came from
[.21, −.08, …]+position 7
[.03, .11, …]=position-aware token
[.24, .03, …]
Without position information, the same set of patches in a different arrangement would look indistinguishable to basic self-attention.
4. Self-attention lets patches exchange evidence
Attention computes data-dependent mixtures. The body token may use wheel and window evidence more strongly than unrelated sky evidence.
5. Produce one vector for the whole image
Architectures may use a special summary token, average patch tokens, or another pooling rule. A projection then produces the requested embedding dimension.
CNN and Vision Transformer: different route, same contract
| Question | CNN | Vision Transformer |
|---|---|---|
| first local unit | sliding receptive field | non-overlapping image patch |
| core mixing operation | convolution | self-attention plus feed-forward layers |
| position handling | built into spatial grid | explicit or learned positional information |
| spatial intermediate | feature maps | patch tokens |
| whole-image summary | global pooling or head | summary token, mean pooling, or head |
| final result | fixed-length vector | fixed-length vector |
Stage 3: projection chooses the embedding dimension
Stage 4: L2 normalization places the vector on a unit sphere
Step 1 · calculate vector length
Step 2 · divide every coordinate by the length
The direction is unchanged, but the new vector's length is 1. This makes dot product equivalent to cosine similarity.
Complete end-to-end shape dry run
| Step | Representation | Shape or size |
|---|---|---|
| 1 | JPEG file | compressed bytes; no tensor shape yet |
| 2 | decoded RGB image | [H, W, 3] |
| 3 | prepared model batch | [1, 3, 224, 224] |
| 4 | 196 projected patch tokens plus one summary token | [1, 197, 768] |
| 5 | contextualized tokens after transformer blocks | [1, 197, 768] |
| 6 | selected or pooled summary | [1, 768] |
| 7 | learned output projection | [1, 512] |
| 8 | L2-normalized embedding | [1, 512], each row has length 1 |
What can invalidate an existing embedding?
Output contract
The array is useful because training shaped its relationships, not because these illustrative numbers can be interpreted one at a time.
7. How text becomes an embedding
a red sports car
characters are not tokens
tokens are not token IDs
token IDs are not token vectors
token vectors are not yet the final sentence embedding
Step through a text encoder
Interactive transformation · sentence → embedding
1. Start with a character string
The application holds a sequence of Unicode characters. Spaces and punctuation are part of that sequence; a model has not yet decided what counts as a useful unit.
At this point: we have text that a program can store, but no learned representation of its meaning.
2. The tokenizer splits the string into known pieces
A tokenizer applies a fixed vocabulary and a fixed splitting recipe. The pieces may be complete words, punctuation, characters, or reusable subwords.
The split above is illustrative. A real tokenizer may produce different pieces. The non-negotiable rule is that the tokenizer must match the model weights.
3. Vocabulary lookup replaces every token with an integer ID
An ID is an address in a vocabulary table. ID 736 is not a measurement of “redness,” and a larger ID does not mean more importance.
4. Each ID selects one learned token vector
Imagine a giant spreadsheet: one row per vocabulary item and one learned vector per row. The ID chooses a row.
Real token vectors may have hundreds of coordinates. The four values here exist only so we can see the operation.
5. Position information preserves word order
A bag containing dog bites person has the same words as person bites dog. Their meaning differs because order differs.
[−.4, .8, .1, .5]
+
position 2 vectorsecond content token[ .1, .0, .2,−.1]
=
model input at position 2red-at-position-2[−.3, .8, .3, .4]
The model now knows both which token it received and where that token occurred.
6. Transformer layers make every token contextual
Self-attention lets each token gather information from other positions. The vector for bank can therefore change according to its neighbours.
The original lookup vector was the same. The contextual output vector is different because the surrounding evidence is different.
7. Convert a sequence of vectors into one search vector
Now we have an embedding: one fixed-length vector representing the complete sentence for the model’s training objective.
Why not keep one token per word?
known word: car
new compound: hypercar
misspelling: hypercarr
inflection: cars
another language: voiture
| Input | One possible illustrative split | What reuse buys us |
|---|---|---|
car | car | common word stays compact |
cars | car + s | plural reuses the base |
sportscar | sport + scar | uncommon compound remains representable |
unsearchable | un + search + able | prefixes and suffixes are shared |
A tiny self-attention dry run
query from "bank" asks: which positions are useful to me?
key from every token answers: what kind of information do I contain?
value from every token carries: the information that can be mixed
Interactive self-attention · update the token “bank”
Choose a sentence, then run the attention head. Watch where the evidence comes from.
Ready: the query from “bank” has not compared itself with the four keys yet.
One-head value mixture for the river sentence
The 60% river contribution dominates this teaching head, while bank retains some of its original information and flooded adds supporting evidence.
Pooling: how many token vectors become one vector
6 tokens × 768 values per token
| Pooling choice | Operation | Consequence |
|---|---|---|
| special summary token | use one designated token’s final vector | training teaches that position to collect sentence information |
| end token | use the final end-of-text representation | the end token can attend to the preceding sequence |
| mean pooling | average valid token vectors | every valid position contributes directly |
Complete text tensor ledger
what the numbers currently represent
how many axes the array has
what each axis counts
which axis appeared or disappeared
How to read a text tensor shape
Read the axes as counts. A shape of [1, 77, 768] means one sentence, 77 reserved positions, and 768 values describing every position.
Interactive tensor ledger · follow every axis
1. Tokenize, add boundary tokens, then pad the unused positions
Our miniature encoder always reserves eight positions. This sentence uses six; two positions remain as padding.
The mask says which positions contain real sequence information. A `1` participates; a `0` is ignored by attention and pooling.
2. Vocabulary lookup adds the hidden-feature axis
Every token ID selects a row from the learned embedding table. Our tiny table returns four values per token.
The new final axis does not mean four more tokens. It means every one of the eight positions now owns a four-number feature vector.
3. Transformer layers change values, not the tensor shape
Self-attention and feed-forward layers let valid token positions exchange information. Compare the `red` row before and after context:
[−.40, .80, .10, .50]knows the token identity
transformer →
contextual vectorred in “red sports car”[−.12, .91, .48, .36]now includes evidence from sports and car
The two padded positions are still present in the rectangular tensor, but the mask prevents them from contributing as meaningful context.
4. Pooling removes the sequence-length axis
Retrieval needs one vector for the complete sentence, not eight vectors. The model’s trained pooling rule collapses the valid positions.
ignores masked pads →
The batch axis remains because we still have one sentence. The hidden width remains four because pooling combines positions, not feature coordinates.
5. Projection changes the feature width
The encoder’s internal summary does not have to match the retrieval dimension. A learned projection matrix remixes four hidden features into three teaching-space coordinates.
[.31, .72, −.18, .44]
×
learned projection[4 × 3]weights learned during training
=
retrieval vector[1 × 3][.60, .80, .20]
The real model may perform `[1, 768] × [768, 512] → [1, 512]`. The operation changes the coordinate system and width; it does not create another token axis.
6. L2 normalization changes vector length, not dimension
The projected vector `[.60, .80, .20]` has length:
Length before normalization
Final result: one sentence became one unit-length point in the model’s retrieval space.
Translate the miniature ledger to a real model
| Stage | Example production shape | What changed? |
|---|---|---|
| token IDs | [1, 77] | one sentence occupies 77 reserved token positions |
| token lookup | [1, 77, 768] | lookup adds 768 learned features to every position |
| transformer output | [1, 77, 768] | contextual values change; shape remains unchanged |
| pooled summary | [1, 768] | pooling removes the 77-position sequence axis |
| projected vector | [1, 512] | projection changes hidden width from 768 to 512 |
| normalized embedding | [1, 512] | values rescale to unit length; shape remains unchanged |
Why is the first number always 1 here?
sentence A = "a red sports car"
sentence B = "waves on a beach"
sentence C = "a photographed invoice"
row 0 → embedding for sentence A
row 1 → embedding for sentence B
row 2 → embedding for sentence C
Padding, masking, and truncation are separate ideas
Four failure experiments worth running
8. How images and text enter one shared space
image → image encoder → image vector
text → text encoder → text vector
Equal dimensions do not imply compatible meaning
car image → [1, 0]
"a car" → [0, 1]
Equal length, incompatible axes
The image model and text model may have invented unrelated coordinate systems. Matching array length only makes the multiplication legal; it does not make the result meaningful.
matching images and captions should point in similar directions; mismatching images and captions should point in different directions.
The training material is made of pairs
Read a contrastive similarity matrix
| Image | sports-car text | beach text | invoice text |
|---|---|---|---|
| Ferrari image | 0.18 | 0.42 | 0.11 |
| Beach image | 0.33 | 0.25 | 0.37 |
| Invoice image | 0.29 | 0.31 | 0.22 |
What one contrastive training step is trying to change
correct caption: sports car 0.91
wrong caption: beach 0.12
wrong caption: invoice 0.04
Row-wise contrastive comparison
The temperature τ controls how sharply small similarity differences affect the competition. The correct pair is trained to receive most of the probability mass.
Controlled dry run · temperature and softmax
At a low temperature, a modest score advantage becomes a decisive probability advantage.
matching image and caption directions → closer
competing mismatched directions → farther apart
Run one conceptual alignment step
The left and right halves begin as unrelated coordinate systems. Run the step to align each known pair.
Pairs begin in unrelated illustrative positions.
Why the captions determine what the model can learn
a red car
a wet road
mountains
sunset light
two people
a red sports car
a vehicle on a mountain road
a photograph taken at sunset
an expensive automobile
What the shared space enables
text query → text encoder ─┐
├─ compare directions → rank images
stored image → image encoder┘
"a photo of a car"
"a photo of a beach"
"a photo of an invoice"
Compatibility checklist
9. Creating and inspecting embeddings in practice
Build a tiny controlled dataset
T1 = "a red sports car" expected: A or B
T2 = "waves on a sandy beach" expected: C
T3 = "a photographed receipt" expected: D
T4 = "a blue bicycle" expected: none strongly
Stage 1: load one model contract
model, image_preprocess, tokenizer = load_compatible_model(
name="chosen-model",
revision="exact-weight-revision",
)
model.eval()
Stage 2: preprocess without confusing input tensors and embeddings
image_tensor = image_preprocess(image).unsqueeze(0)
token_ids = tokenizer(["a red sports car"])
print(image_tensor.shape) # [1, 3, 224, 224], for this example model
print(token_ids.shape) # [1, 77], for this example tokenizer
image_tensor = normalized pixels
token_ids = integer vocabulary addresses
Stage 3: run inference, then normalize the outputs
with no_grad():
image_features = model.encode_image(image_tensor)
text_features = model.encode_text(token_ids)
image_embedding = image_features / image_features.norm(dim=-1, keepdim=True)
text_embedding = text_features / text_features.norm(dim=-1, keepdim=True)
Inspect the contract before inspecting quality
image tensor shape: [1, 3, 224, 224]
token ID shape: [1, 77]
image feature shape: [1, 512]
text feature shape: [1, 512]
image feature dtype: float32
image embedding norm: 1.0000
text embedding norm: 1.0000
all values finite: true
| Check | Failure it can expose |
|---|---|
| input shape | wrong crop, channel order, or missing batch dimension |
| output shape | wrong projection head or model variant |
| dtype/device | accidental precision or device mismatch |
| finite values | overflow, invalid input, or numerical failure |
| norm near 1 | missing or incorrect row normalization |
Stage 4: embed a batch and build the complete score matrix
I shape = [4, 512]
T shape = [4, 512]
All image–text comparisons in one operation
Every row is one image. Every column is one text probe. Cell S(i,j) is their cosine similarity when both matrices are row-normalized.
scores = image_embeddings @ text_embeddings.T
| image ↓ / query → | sports car | beach | receipt | bicycle |
|---|---|---|---|---|
| A · red car | 0.86 | 0.14 | 0.05 | 0.19 |
| B · recompressed A | 0.84 | 0.13 | 0.06 | 0.18 |
| C · beach | 0.10 | 0.91 | 0.08 | 0.12 |
| D · invoice | 0.03 | 0.09 | 0.88 | 0.04 |
correct pairs outrank controls
altered copy stays near the original
unrelated subjects separate
unsupported query lacks a convincing match
Stage 5: run invariance experiments
| Variant | What changed | Question |
|---|---|---|
| JPEG recompression | bytes and fine noise | does semantic identity survive? |
| resize and restore | sampling detail | is scale handling robust? |
| mild brightness change | channel values | is content stronger than illumination? |
| tight crop | composition and context | does the model still recognize the subject? |
| horizontal flip | spatial orientation | does direction matter to this model? |
similarity(original, variant)
rank for "a red sports car"
rank for an unrelated control prompt
Stage 6: prove batching does not change individual results
single = encode_images([A])[0]
batched = encode_images([A, B, C, D])[0]
delta = abs(single - batched).max()
Stage 7: cache vectors with enough identity to invalidate them
IMG_1042.jpg → [0.12, −0.34, ...]
image path
file size
modification time or content hash
model name
weight revision
preprocessing revision
embedding dimension
dtype
normalization rule
vector bytes
A practical debugging table
| Symptom | Likely cause | First check |
|---|---|---|
| every result has almost the same score | missing normalization or collapsed/incorrect output | norms, variance, correct projection |
| text search is nonsense but image similarity works | incompatible tokenizer or text encoder | exact model/tokenizer revision |
| colours are consistently wrong | RGB/BGR channel mistake | decoded channel order |
| results change between identical runs | model left in training mode | eval(), dropout, deterministic settings |
| cached and fresh vectors disagree | source/model/preprocessing changed | cache identity fields |
| GPU memory keeps growing | gradients or outputs retained | inference/no-gradient context |
| correct result ranks first but all scores are low | score calibration differs | evaluate ranks before inventing a threshold |
10. What semantic search is actually doing
Encode stored objects and a query into one compatible learned space, measure their geometric similarity, and return the highest-scoring eligible objects.
Timeline A: indexing the collection
Timeline B: answering one query
Try a miniature semantic search
Interactive retrieval · one index, three queries
Change the query. The stored image vectors stay fixed; only the query vector and scores change.
Car images point most nearly in the query direction, so they rank first.
Complete numerical dry run
Ferrari [0.98, 0.10]
Porsche [0.95, 0.15]
Beach [0.10, 0.99]
Invoice [0.02, 0.80]
Query embedding
This teaching query points mostly along the first axis, where the car vectors also point.
Similarity rule
Multiply corresponding coordinates, then add every product.
Ferrari score
Porsche score
Beach score
1. Ferrari 0.9626
2. Porsche 0.9395
3. Beach 0.2158
4. Invoice lower still
Cosine, dot product, and Euclidean distance
Cosine similarity
cosine similarity = dot product
Unit-vector equivalence
On the unit sphere, maximizing dot product and minimizing Euclidean distance produce the same ordering. This equivalence disappears when normalization assumptions change.
Top K and thresholds answer different questions
return the ten highest scores, even if every candidate is poor.
reject candidates below this chosen boundary.
Metadata filtering changes the eligible search space
"sunset beach"
date: 2025
folder: /vacation
pre-filter:
metadata → eligible vectors → vector search
post-filter:
vector search → candidates → metadata filter
Keyword search and semantic search solve different failures
| Query need | Keyword/OCR/metadata search | Semantic vector search |
|---|---|---|
exact filename IMG_1042.jpg | excellent | inappropriate |
invoice number AC-49217 | excellent if OCR indexed it | may lose exact digits |
red car on a mountain road | only if annotated with those words | useful when content is visible |
| camera model and date | excellent structured filter | not the embedding’s job |
| paraphrase or broad concept | brittle without matching words | often robust |
semantic similarity
+ exact filename or OCR match
+ metadata/business rules
+ optional reranker
Exact search versus approximate search
N × D coordinate products per query
Did retrieval include the true nearest neighbours, or did approximation miss them before accurate scoring?
Evaluate search as a retrieval system
| Metric | Question |
|---|---|
| Recall@K | did the top K contain the relevant items? |
| Precision@K | how many returned items were relevant? |
| Mean reciprocal rank | how early did the first relevant item appear? |
| latency percentiles | how slow are typical and worst-case queries? |
| index freshness | do changed files receive updated vectors? |
objects
scenes
colours
text inside images
fine-grained models
people and activities
negation
rare concepts
cropped or low-quality images
11. Experimental proof: run the representations
Numbers produced by cached model weights over named, checksummed inputs.
Controlled dry runSmall arithmetic or synthetic examples whose values were chosen to expose one operation.
Conceptual diagramA visual explanation of mechanism; it is not a benchmark result.












The experiment contract
Three models, three different promises
———
Experiment A: which changes should an embedding ignore?
original
├── JPEG quality 35
├── shrink to 64 × 64, then restore
├── brightness × 0.65
├── centre crop to 70%, then restore
└── horizontal flip
—
Experiment B: can neighbours recover unseen labels?
CLIP
SigLIP
DINO
Experiment C: text supervision can be tested directly
The experiment caught a real SigLIP preprocessing bug
SigLIP image 5-NN accuracy: 85.0%
SigLIP text zero-shot accuracy: 10.6%
padding = longest prompt in this batch—zero-shot accuracypadding = fixed 64 positions—zero-shot accuracyExperiment D: what is lost when we reduce dimensions?
—
Experiment E: choose a threshold and watch the errors move
—
Failure gallery: inspect what an average hides
Timing is evidence about this machine, not every machine
Inspect the reproducibility ledger and a raw result excerpt
Loading measured artifact…
.venv/bin/python scripts/semantic_search_evidence.py \
--models clip siglip dino \
--samples-per-class 50 \
--seed 20260901 \
--offline
What creates the semantics?
| Component | What it does | What it does not do |
|---|---|---|
| tokenizer/preprocessor | creates the expected model input | decide semantic neighbours |
| embedding model | learns the geometry from data and objective | store or retrieve the collection |
| normalization and metric | define how directions are compared | create meaning from arbitrary vectors |
| database | stores vectors and metadata | make incompatible spaces compatible |
| exact or ANN index | retrieves likely neighbours | decide what the model learned |
| filters and rerankers | enforce product context and refine order | repair every representation failure |
Semantic search places a query and stored objects on a learned map, then returns eligible objects nearest to the query. The model defines the map; the retrieval system navigates it; evaluation tells us whether that map is useful for our task.
Beginner checkpoint
Primary references