Embeddings Explained: How AI Understands Meaning
Back to all articles
Machine Learning
28 min read7 min read

Embeddings Explained: How AI Understands Meaning

Master embeddings from scratch. Learn what they are, how they work, and how to use them effectively in your AI applications.

Debasish Maji
Debasish Maji
AI Engineering Lead
March 5, 2026
EmbeddingsVector SearchSemantic SearchNLP

What Are Embeddings?

Embeddings are the foundation of how AI understands meaning. They convert things (words, sentences, images) into lists of numbers (vectors) that capture their essence.

The magic: similar things get similar vectors.

Code
"king"  → [0.2, 0.8, 0.1, ...]
"queen" → [0.25, 0.78, 0.15, ...]  // Similar vectors!
"banana" → [0.9, 0.1, 0.7, ...]    // Different vector
•••

Why Embeddings Matter

Computers Only Understand Numbers

A computer can't directly understand "dog" or "cat". But it CAN compare numbers:

  • Is 5 close to 6? Yes.
  • Is 5 close to 1000? No.

Embeddings convert meaning into numbers so computers can:

  • Measure similarity between concepts
  • Find related items
  • Understand analogies
  • Power search, recommendations, and AI

The Alternative: One-Hot Encoding

Without embeddings, we might use one-hot encoding:

Code
Vocabulary: [cat, dog, fish, bird, car, ...]

"cat" → [1, 0, 0, 0, 0, ...]
"dog" → [0, 1, 0, 0, 0, ...]
"fish" → [0, 0, 1, 0, 0, ...]

Problems:

  • No similarity: distance(cat, dog) = distance(cat, car)
  • Huge vectors: vocabulary of 100K words = 100K-dimensional vectors
  • No meaning captured
•••

Part 2: How Embeddings Capture Meaning

The Word2Vec Revelation

Word2Vec (2013) discovered that training on simple tasks produces meaningful embeddings.

Training task: Predict a word from its neighbors

Code
Sentence: "The cat sat on the mat"

Given: ["The", "sat", "on", "the"]
Predict: "cat"

After training on millions of sentences, the model learns:

  • Words in similar contexts get similar embeddings
  • "dog" and "cat" appear in similar contexts → similar embeddings
  • Relationships are captured as vector directions

The Famous Analogy

Code
king - man + woman ≈ queen
Code
Vector arithmetic:
[0.2, 0.8, 0.1, 0.5]     // king
- [0.1, 0.3, 0.1, 0.8]   // man
+ [0.15, 0.35, 0.15, 0.2] // woman
= [0.25, 0.85, 0.15, -0.1] // ≈ queen

Why this works:

  • "king" and "queen" share royalty features
  • "man" and "woman" differ by gender features
  • Subtracting "man" removes male features
  • Adding "woman" adds female features
  • Result: royalty + female = queen
•••

Part 3: Types of Embeddings

Word Embeddings

One vector per word. Same embedding regardless of context.

Python
from gensim.models import Word2Vec

model = Word2Vec(sentences, vector_size=100, window=5)
vector = model.wv['cat']  # 100-dimensional vector

Problem: "bank" has the same embedding whether it's a river bank or a money bank.

Contextual Embeddings (BERT, GPT)

Different vectors based on context.

Code
"I went to the bank to deposit money"
                 ↓
             bank → [0.2, 0.5, 0.1, ...]  (financial meaning)

"I sat by the river bank"
                    ↓
                bank → [0.8, 0.1, 0.7, ...]  (geographical meaning)

Sentence Embeddings

One vector for an entire sentence.

Python
from sentence_transformers import SentenceTransformer

model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode([
    "I love programming",
    "Coding is my passion",
    "The weather is nice"
])

# embeddings[0] and embeddings[1] will be similar
# embeddings[2] will be different

Image Embeddings

Same concept, but for images. A trained model (like CLIP) converts images to vectors.

Code
Photo of cat → [0.1, 0.8, 0.3, ...]
Photo of dog → [0.15, 0.75, 0.35, ...]  // Similar (both pets)
Photo of car → [0.9, 0.1, 0.2, ...]     // Different
•••

Part 4: Measuring Similarity

Cosine Similarity

The most common similarity measure. Measures the angle between vectors.

Code
B
                 ╱
                ╱
               ╱ θ (small angle = similar)
              ╱
    A ───────

cosine_similarity = cos(θ) = (A · B) / (|A| × |B|)

Range: -1 (opposite) to 1 (identical)
Python
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

a = np.array([1, 2, 3])
b = np.array([1, 2, 4])
c = np.array([-1, -2, -3])

print(cosine_similarity([a], [b]))  # 0.99 (very similar)
print(cosine_similarity([a], [c]))  # -1.0 (opposite)

Euclidean Distance

Measures straight-line distance between points.

Code
B●
     │╲
     │  ╲ distance
     │    ╲
    A●──────

distance = √((x₁-x₂)² + (y₁-y₂)² + ...)

When to use which:

  • Cosine: When direction matters (text similarity)
  • Euclidean: When magnitude matters (some image tasks)
•••

Part 5: Practical Applications

Traditional search: keyword matching Embedding search: meaning matching

Code
Query: "How to fix a broken heart"

Keyword search matches:
  ❌ "Heart surgery procedures" (has "heart")
  ❌ "Fixing car engines" (has "fix")

Embedding search matches:
  ✓ "Dealing with breakup pain" (similar MEANING)
  ✓ "Moving on after a relationship" (similar MEANING)
Python
# Index documents
documents = [
    "Dealing with breakup pain",
    "Heart surgery procedures",
    "Moving on after a relationship"
]
doc_embeddings = model.encode(documents)

# Search
query = "How to fix a broken heart"
query_embedding = model.encode(query)

# Find most similar
similarities = cosine_similarity([query_embedding], doc_embeddings)
most_similar_idx = similarities.argmax()
print(documents[most_similar_idx])  # "Dealing with breakup pain"

RAG (Retrieval Augmented Generation)

Power ChatGPT-like systems with your own data:

Code
1. Embed your documents → store in vector database
2. User asks question
3. Embed question → find similar documents
4. Send question + retrieved documents to LLM
5. LLM generates answer using your documents

Recommendations

Find similar items based on embeddings:

Python
# User liked these movies
liked_movies = ["Inception", "Interstellar", "The Matrix"]
liked_embeddings = [get_embedding(m) for m in liked_movies]

# Average their embeddings to get "user taste"
user_taste = np.mean(liked_embeddings, axis=0)

# Find movies with similar embeddings
all_movie_embeddings = ...
similarities = cosine_similarity([user_taste], all_movie_embeddings)

# Top recommendations
top_indices = similarities.argsort()[0][-5:]
recommendations = [movies[i] for i in top_indices]
•••

Part 6: Vector Databases

Why Vector Databases?

Regular databases: exact matches (WHERE name = "John") Vector databases: similarity search (find vectors near this one)

Code
Regular DB query:    SELECT * FROM users WHERE age = 25
Vector DB query:     Find 10 vectors closest to [0.1, 0.5, 0.3, ...]

Pinecone - Managed, easy to use

Python
import pinecone

pinecone.init(api_key="...")
index = pinecone.Index("my-index")

# Insert
index.upsert([("doc1", embedding1), ("doc2", embedding2)])

# Query
results = index.query(query_embedding, top_k=5)

Weaviate - Open source, feature-rich

Milvus - Open source, scalable

Chroma - Lightweight, good for prototyping

pgvector - PostgreSQL extension (use existing DB)

Approximate Nearest Neighbor (ANN)

Finding exact nearest neighbors is slow for millions of vectors. ANN algorithms trade accuracy for speed:

Code
Exact search:  Compare with ALL vectors (slow but perfect)
ANN search:    Smart indexing (fast but might miss some)

Accuracy trade-off:
  1 million vectors
  Exact:  1000ms, 100% recall
  ANN:    10ms, 95% recall

Common ANN algorithms:

  • HNSW (Hierarchical Navigable Small Worlds)
  • IVF (Inverted File Index)
  • PQ (Product Quantization)
•••

Part 7: Best Practices

Choosing Embedding Models

Use CaseModelDimensions
General textOpenAI text-embedding-3-small1536
Fast & smallall-MiniLM-L6-v2384
Multilingualmultilingual-e5-large1024
ImagesCLIP512
CodeCodeBERT768

Chunking for Documents

Long documents need to be split into chunks before embedding:

Python
# Bad: One embedding for entire document
doc_embedding = embed(long_document)  # Information gets averaged out

# Good: Split into meaningful chunks
chunks = split_into_chunks(long_document, chunk_size=500)
chunk_embeddings = [embed(chunk) for chunk in chunks]

Chunking strategies:

  • Fixed size (500 tokens) with overlap (50 tokens)
  • Sentence-based
  • Paragraph-based
  • Semantic (split at topic changes)

Handling Updates

When documents change, you need to re-embed and re-index:

Python
def update_document(doc_id, new_content):
    # Delete old embeddings
    vector_db.delete(filter={"doc_id": doc_id})
    
    # Create new embeddings
    chunks = chunk_document(new_content)
    embeddings = embed(chunks)
    
    # Insert new embeddings
    for i, (chunk, emb) in enumerate(zip(chunks, embeddings)):
        vector_db.insert(
            id=f"{doc_id}_chunk_{i}",
            vector=emb,
            metadata={"doc_id": doc_id, "text": chunk}
        )
•••

Key Takeaways

  1. 1Embeddings convert meaning to numbers - similar things get similar vectors
  1. 2Contextual embeddings understand context - same word, different contexts, different vectors
  1. 3Cosine similarity measures semantic similarity - most common for text
  1. 4Vector databases enable fast similarity search - essential for production systems
  1. 5Chunking matters for long documents - break into meaningful pieces before embedding
  1. 6Choose the right embedding model - balance quality, speed, and cost for your use case

Found this helpful?

Share it with others who might benefit

TweetShare

Related articles