← AgenticGHX · Learn
Transformers · Intuition series · Lab 2

Embedding Lab

The explainer used numbers we made up to behave like embeddings. This lab uses the real thing: 10,000 words, 200 dimensions each, learned from actual text. You'll poke them in Google's Embedding Projector and watch them do things you didn't expect.

0 / 9 exercises
start →

Before you start

Open the Embedding Projector in a second window and put it side by side with this page — you'll be switching constantly. In the DATA panel on the left, choose Word2Vec 10K from the dropdown. That's 10,000 common English words, each one a 200-number vector learned from a large text corpus.

Open the Embedding Projector ↗
Orient yourself first. Four regions: DATA (top left — pick the dataset), the projection tabs UMAP / T-SNE / PCA / CUSTOM (bottom left), the big 3-D view in the middle, and the inspector on the right (search box + nearest-neighbour list). Drag the view to rotate. If a word you try isn't found, switch the dataset to Word2Vec All — it has a much bigger vocabulary.

Warm-up · get your bearings in 3-D

The explainer's 17 words, in 3-D. Drag to rotate, click a word to pin its nearest neighbours. Warm up here before the Projector.

drag to rotate · hover a word for its neighbours
Royalty & people Animals Food Feelings
How to use this lab Every exercise asks you to write down a prediction before you look. Don't skip that — it's the whole point. Being wrong is what makes the lesson stick; quietly agreeing with an answer you were shown teaches you nothing. The reveal button stays locked until you've committed to a guess.
1

Nearest neighbours: distance really is meaning

core8 min
Goal: see that "similar meaning = nearby vector" isn't a metaphor — it's a number you can read off the screen.
✍️ Predict first
Name three words you expect to be nearest neighbours of water.

Do this

  1. In the search box on the right, type water and click the matching result.
  2. The inspector now lists its nearest points with a distance number beside each.
  3. Read the top 10. Then try a few more — click to copy:
What you should see

water pulls up things like drinking, salt, fresh, supply, gas, air — not just synonyms, but the whole situation water appears in. three sits with other numbers, red with other colours, london with other cities.

Nobody told the model that "three" is a number. It read a lot of text, noticed that three and four get used in near-identical sentences, and placed them next to each other. Category structure fell out of raw co-occurrence.

The distance number matters. That's cosine distance — smaller means more similar. This is the actual quantity production systems use for search and recommendations, computed on all 200 dimensions. Not on the picture.

2

The antonym trap

core8 min
Goal: find out what "similar" actually means to an embedding — it's not what you assume.
✍️ Predict first — commit before you look
Will good and bad be close together or far apart?

Do this

  1. Search good. Look down the neighbour list for bad.
  2. Now try these opposite pairs the same way: hot/cold, big/small, up/down, increase/decrease.
  3. Note roughly where each antonym ranks in its partner's neighbour list.
What you should see

Antonyms are extremely close — often in each other's top 10. Most people predict the opposite, and being wrong here is the most useful thing in this lab.

Why: embeddings learn from company kept. Think about the sentences these words appear in: "the food was good" / "the food was bad." "turn the heat up" / "turn the heat down." Antonyms are grammatically interchangeable and appear in near-identical contexts, so distributional learning puts them almost on top of each other.

So the axis embeddings capture is relatedness — same topic, same slot in a sentence — not sameness of meaning and definitely not sentiment. This is a real, load-bearing limitation: naive embedding search for "great product" will happily surface "terrible product."

The lesson "Similar" in embedding-space means appears in similar contexts. Usually that lines up with meaning. For antonyms it spectacularly doesn't. Any system you build on embeddings inherits this — sentiment needs a separate model or a fine-tuned embedding, not raw cosine similarity.
3

One word, many meanings — and only one vector

core10 min
Goal: discover the exact limitation that made transformers necessary.
✍️ Predict first
The word bank has two unrelated meanings (river edge / financial). What will its neighbour list look like?

Do this

  1. Search bank and read the neighbours carefully. Tally how many are financial vs. geographic.
  2. Repeat for these ambiguous words — click to copy:
  • For each, ask: can you see both senses in the list, or has one sense won?
What you should see

One blended list. bank typically leans heavily financial (that sense dominates the training corpus) with a few geographic words mixed in. apple mixes fruit and company. rock mixes stone and music.

There is exactly one row in the table for "bank." The model cannot give you two — so it stores a single compromise vector, roughly a frequency-weighted average of every sense, sitting in a slightly incoherent place that belongs fully to neither meaning.

Notice the rarer sense often gets crushed. If 90% of "bank" occurrences are financial, the vector parks itself in finance-land and river-bank is a faint pull.

The lesson — this is the bridge to transformers What you just found is the ceiling of static embeddings (word2vec, GloVe): one vector per word, forever, regardless of sentence. Attention is the fix. A transformer starts from this same lookup, then reshapes the vector using the surrounding words, so "bank" in "I fished from the river bank" ends up somewhere different from "bank" in "I opened a bank account." That's a contextual embedding — and it's precisely the demo in section 8 of the explainer.
4

The map lies: PCA vs t-SNE vs UMAP

core15 min
Goal: learn to distrust the pretty picture — and know exactly which number to trust instead.
✍️ Predict first
You run t-SNE twice on the same unchanged data. How similar will the two pictures look?

Warm-up · a space small enough to fact-check

Only 3 dimensions here, so the truth is checkable — something you can never do at 200. Pick two words (or click them in the cloud) and rotate: watch how far apart they look versus how far apart they are.

Clicking a word in the cloud sets Word A.

True distance · all 3 dims
Looks like · on screen
Understated by

Hit Find the most misleading angle, then Flatten to a 2-D plot. No depth cues, no way to tell — exactly what a t-SNE or UMAP plot hands you. Two words on top of each other, genuinely far apart. Now scale it up: the Projector squashes 200 dimensions into 3, and there's no button that reveals the truth.

Do this

  1. Pick any word and note its top neighbour and the exact distance number from the inspector. Write it down — this is your ground truth.
  2. Click the PCA tab. Find your two words. Note how far apart they look, and read the "Total variance described" percentage the panel reports.
  3. Click T-SNE. Let it run a few hundred iterations. Find your words again — do they look equally close?
  4. Now hit re-run on t-SNE (or change perplexity and re-run). Watch the whole layout rearrange.
  5. Click UMAP. A third, different picture of the same unchanged vectors.
What you should see

Three methods, three different pictures — and t-SNE gives you a different layout every time you run it, because it starts from a random initialisation. The vectors never changed. Only the shadow did.

The PCA variance number is the honest one to stare at: squashing 200 dimensions into 3 typically retains only tens of a percent of the variance. You are looking at a small fraction of the information and calling it the data.

The critical trap: in t-SNE and UMAP, distance between clusters is not meaningful. Both are designed to preserve local neighbourhoods and will happily distort global distances to make a readable picture. Two clusters drawn far apart may not be far apart. Cluster sizes and empty space between blobs are largely artefacts.

The lesson — the single most misused chart in ML Dimensionality reduction is for your eyes, not for your measurements. Never read similarity off a t-SNE or UMAP plot. If you need to know how close two things are, compute cosine similarity on the full vector — the number in the inspector. Use the picture to form hypotheses; use cosine to test them. People publish conclusions based on UMAP proximity all the time, and it's frequently wrong.
5

Directions carry meaning

core12 min
Goal: see why king − man + woman ≈ queen works, using the Projector's most powerful feature.
✍️ Predict first
If you build an axis running from man to woman, where will king, queen, actor and actress land along it?

Do this

  1. Click the CUSTOM tab in the projections panel.
  2. For the horizontal axis, type man in the left box and woman in the right box.
  3. The whole space reorients along that direction. Use the search box to locate: king, queen, uncle, aunt, actor, actress, boy, girl, father, mother.
  4. Now swap in different axes and look again:
  • smalllarge
  • pastfuture
  • cheapexpensive
What you should see

The pairs line up. king/uncle/actor/father sit toward the "man" end; queen/aunt/actress/mother sit toward the "woman" end — and each pair is separated by roughly the same displacement.

That's the key insight: the space encodes concepts not only as positions but as directions. There is a consistent "gender" direction, and adding it to king lands you near queen. That's literally what king − man + woman ≈ queen is doing — subtract to isolate the direction, add it somewhere else.

The same holds for size, time, and price axes. A single direction, reusable across many word pairs.

Honest caveat: analogy arithmetic is weaker than the famous demos suggest. It works well for a handful of relations (gender, capital-of, plural) and poorly for most others, and the standard evaluation excludes the input words from the answer — which quietly does a lot of the work. Treat it as a real but narrow property, not magic.
6

Bias audit: the mirror problem

core15 min
Goal: measure a real social bias yourself, and understand where it comes from and what it breaks.
✍️ Predict first
On that same manwoman axis, where will engineer, nurse, scientist and secretary fall?

Do this

  1. Keep the CUSTOM projection with manwoman.
  2. Search for each occupation and note which side it sits on:
  1. Try a second axis to probe a different bias — for example richpoor, and look at where country and city names land.
  2. Write down one association you think is unfair, and one you think is just accurate description of the world.
What you should see

A clear, uncomfortable split. engineer, doctor, scientist, captain lean toward "man"; nurse, secretary, teacher, dancer lean toward "woman." You didn't tell the model anything about gender roles — you built an axis from two words and the occupations sorted themselves.

Where it comes from: the corpus. The model read enormous amounts of human-written text in which nurses are described as "she" and engineers as "he." It has no beliefs; it's a statistical mirror of what people wrote. The bias is a faithful measurement of the training data, which is exactly what makes it dangerous — it's real, learned, and invisible until you go looking.

Why it matters in production: put this embedding inside a résumé search or a job-ad targeter, and it will rank a woman's engineering CV lower for reasons no one coded and no one can see in the logs. Bias here isn't abstract — it propagates into every downstream system that consumes the vectors.

Take it further Most widely used embeddings are trained on overwhelmingly English, Western, internet text. Check how well your own languages, place names and personal names are represented — try searching for Ghanaian cities or names and see whether the neighbourhoods make sense compared to, say, European ones. Sparse or incoherent neighbourhoods are a representation gap, and they're a strong argument for locally trained or fine-tuned models. Discussion question: if you were shipping a product on these vectors, what would you test before launch, and what would you do about what you found?
7

Cosine vs Euclidean — why text always picks cosine

core8 min
Goal: understand the metric choice you'll make in every vector database you ever configure.
✍️ Predict first
Switching the distance metric from cosine to Euclidean will change the neighbour list…

Do this

  1. Search a word and note its top 10 neighbours.
  2. In the inspector, switch the metric between COSINE and EUCLIDEAN. Compare the lists.
  3. Now find the Sphereize data checkbox in the DATA panel and tick it. Compare the two metrics again.
What you should see

Mostly the same words, somewhat reordered — and after you tick Sphereize, the two metrics agree far more closely.

Why: cosine measures the angle between vectors and ignores their length. Euclidean measures straight-line distance, so length counts. In word embeddings, vector length correlates with things like word frequency — not meaning. Using Euclidean lets "how common is this word" leak into "how similar is this word."

"Sphereize" normalises every vector to unit length. Once all vectors sit on the same sphere, ranking by cosine and ranking by Euclidean become equivalent — which is exactly why production systems normalise their embeddings and then use a plain dot product.

Practical rule For text embeddings, use cosine (or normalise, then dot product). It's the default in every vector DB — Pinecone, FAISS, pgvector — for this reason. Direction is meaning; magnitude is mostly an artefact.
8

Not just words: embeddings of images

core10 min
Goal: see that "meaning → geometry" has nothing to do with language.
✍️ Predict first
In a space of handwritten digits, which digit pairs will sit closest / overlap most?

Do this

  1. In the DATA dropdown, switch to MNIST with images — 784-dimensional vectors of handwritten digits.
  2. Use Color by label so each digit gets its own colour.
  3. Run UMAP or T-SNE and look at where clusters touch or bleed into each other.
  4. Click points in an overlap region and look at the actual images.
What you should see

Ten reasonably clean clusters — with predictable trouble spots: 4 and 9 bleed together, as do 3, 5 and 8, and 1 and 7. Click into the overlaps and you'll find genuinely ambiguous handwriting.

No words anywhere. Same trick: pixels in, vectors out, and similar things land near each other. The geometry now encodes visual similarity instead of semantic similarity.

The useful part: where clusters touch is where a classifier makes its mistakes. The confusion matrix you'd get from a trained model is visible in the geometry before you train anything. This is a real debugging technique — embed your data, look at what overlaps, and you've found your hard cases.

The lesson Anything you can turn into a vector gets this whole toolkit: nearest-neighbour search, clustering, outlier detection. Words, images, audio, users, products, proteins, transactions. That's why embeddings show up in every corner of ML — and it's section 9 of the explainer, now with real data.
9

Bring your own data

stretch · code30 min
Goal: embed something you care about and explore it. This is where it stops being a demo.

Everything so far used someone else's vectors. Now make your own. Pick a set of 100–300 short texts with some structure you already understand — so you can tell whether the geometry got it right. Good candidates: your community's talk titles, product reviews, support tickets, news headlines, job ads, or sentences in a language you speak.

Step 1 — generate embeddings (Google Colab)

python
!pip install -q sentence-transformers

from sentence_transformers import SentenceTransformer

# 1. Your texts, and a label for each (used to colour the plot)
texts = [
    "How to build an AI agent",
    "Fine-tuning small language models",
    "Designing a community health survey",
    "Mobile money fraud detection",
    # ... aim for 100-300
]
labels = ["agents", "models", "health", "finance"]  # same length as texts

# 2. Embed. This model gives 384-dimensional vectors.
model = SentenceTransformer("all-MiniLM-L6-v2")
vectors = model.encode(texts)
print(vectors.shape)   # (n_texts, 384)

# 3. Write the two files the Projector wants
with open("vectors.tsv", "w") as f:
    for v in vectors:
        f.write("\t".join(f"{x:.6f}" for x in v) + "\n")

with open("metadata.tsv", "w") as f:
    f.write("text\tlabel\n")                    # header REQUIRED for 2+ columns
    for t, l in zip(texts, labels):
        clean = t.replace("\t", " ").replace("\n", " ")
        f.write(f"{clean}\t{l}\n")

from google.colab import files
files.download("vectors.tsv")
files.download("metadata.tsv")

Step 2 — load into the Projector

  1. Click Load in the DATA panel.
  2. Upload vectors.tsv as the vectors and metadata.tsv as the metadata.
  3. Set Color by to your label column.
  4. Explore with everything you learned above.
Two gotchas that break the upload. (1) The metadata file needs a header row only if it has two or more columns — a single-column file must have no header. (2) Row n of vectors.tsv must correspond to row n of metadata.tsv, so never sort one without the other, and strip tabs/newlines out of your text.

Questions to answer about your own data

  • Do the clusters match the labels you assigned — or did the model find a different, better grouping than your categories?
  • Which single item is furthest from everything else, and why? Is it genuinely unusual, or just badly written?
  • Find two items your labels call different but the geometry puts together. Which is right?
  • Pick a query sentence and find its nearest neighbours. Would this be a good search engine for your data? Where does it fail?
Why this is the real exercise That last question is the one that matters professionally. You just built the retrieval half of a RAG system: embed documents, embed the query, return nearest neighbours. Everything else is plumbing. If you understand why the neighbours come back the way they do — and where they come back wrong — you understand the part of the stack most people treat as a black box.

Self-check

10 min

Nine exercises in, these are the points that separate "I saw the demo" from "I can use this." Answer before you read the explanation — being wrong here is cheaper than being wrong in a design review.

Five questions across the nine exercises.
MisconceptionThe axes of the plot mean something.
RealityThey're projected directions with no human-readable name. Read distance and direction, not coordinates.
MisconceptionSimilar vectors mean similar meaning.
RealityThey mean similar context. Antonyms are close. Relatedness ≠ synonymy.
MisconceptionThe model "understands" the words.
RealityIt captured co-occurrence statistics. That's enough to be useful, and it's not comprehension.
MisconceptionA cleaner-looking t-SNE plot means better embeddings.
RealityIt often just means different hyperparameters. Evaluate on a task, not on how tidy the picture is.

Where to go next

You've now seen static embeddings at their limit — one vector per word, senses blurred together, no notion of context. The next question is the one exercise 3 set up: how does attention rebuild these vectors on the fly, per sentence? That's the machinery of a transformer, and it starts exactly where this lab ends.

The lab at a glance
✓ Grounded in published work

Where these ideas come from

Every vector you poked in this lab is real — word2vec, 10,000 words, 200 dimensions, served by Google's Embedding Projector. The behaviour you observed is documented here:

You've now handled real vectors, not a metaphor for them.

Where this sits: the embeddings explainer comes before this lab; one geometry, six jobs is what you build once the geometry is in place.

This is one of the interactive explainers we make at AgenticGHX. If it was useful, the rest — talks, learning tracks, and research out of Ghana — is one tap away.

More from AgenticGHX Learn →