AI & Data Science

Vector Embeddings untuk Semantic Search โ€” Models, Similarity & Dimensionality Reduction

Tutorial lengkap Vector Embeddings untuk semantic search โ€” konsep, model, similarity metrics, dimensionality reduction, evaluasi, dan deployment

1. Pengenalan Vector Embeddings

Vector Embeddings adalah representasi data (teks, gambar, audio) dalam bentuk vektor angka berdimensi tinggi yang menangkap makna atau fitur dari data tersebut. Data dengan makna serupa akan memiliki vektor yang berdekatan dalam ruang embedding.

Diagram: Embedding Space
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                  EMBEDDING SPACE (2D projection)                 โ”‚
โ”‚                                                                  โ”‚
โ”‚     โ€ข mobil sport                                               โ”‚
โ”‚        โ€ข mobil sedan                    โ€ข kucing                โ”‚
โ”‚                                          โ€ข anjing               โ”‚
โ”‚     โ€ข motor                                          โ€ข ikan     โ”‚
โ”‚                                                                  โ”‚
โ”‚                                                                  โ”‚
โ”‚                    โ€ข laptop                                      โ”‚
โ”‚                    โ€ข komputer                                    โ”‚
โ”‚                    โ€ข smartphone                                  โ”‚
โ”‚                                                                  โ”‚
โ”‚  Objek dengan makna serupa โ†’ berdekatan di ruang embedding      โ”‚
โ”‚  Objek berbeda makna โ†’ berjauhan                                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Mengapa Embeddings Penting?

AplikasiPenjelasan
Semantic SearchCari berdasarkan makna, bukan keyword
RecommendationTemukan item serupa berdasarkan kemiripan vektor
ClusteringKelompokkan data berdasarkan kesamaan
RAGRetrieval untuk LLM berdasarkan kemiripan semantik
Anomaly DetectionTemukan data yang vektor-nya jauh dari norma
ClassificationGunakan embeddings sebagai fitur untuk classifier

2. Embedding Models

ModelDimensiProviderBahasa IDHarga
text-embedding-3-small1536OpenAIโœ… Bagus$0.02/1M tokens
text-embedding-3-large3072OpenAIโœ… Sangat bagus$0.13/1M tokens
all-MiniLM-L6-v2384Sentence Transformersโš ๏ธ CukupGratis (lokal)
multilingual-e5-large1024Microsoftโœ… BagusGratis (lokal)
embed-english-v3.01024CohereโŒ EN only$0.1/1M tokens
gecko768Googleโœ… Bagusvia Vertex AI

3. Text Embeddings dengan Python

Python โ€” Text Embeddings
# =============================================
# Text Embeddings
# =============================================

# ----- 1. OpenAI Embeddings -----
from openai import OpenAI
client = OpenAI()

response = client.embeddings.create(
    model="text-embedding-3-small",
    input="Belajar vector embeddings untuk semantic search"
)
vector = response.data[0].embedding
print(f"Dimensi: {len(vector)}")  # 1536
print(f"5 elemen pertama: {vector[:5]}")

# Batch embedding
texts = [
    "Machine learning adalah subset AI",
    "Deep learning menggunakan neural network",
    "Resep nasi goreng enak dan mudah",
    "Jadwal pertandingan sepak bola"
]
response = client.embeddings.create(
    model="text-embedding-3-small",
    input=texts
)
embeddings = [item.embedding for item in response.data]

# ----- 2. Hugging Face (Gratis, Lokal) -----
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("all-MiniLM-L6-v2")  # 384 dimensi
embeddings = model.encode(texts)
print(f"Shape: {embeddings.shape}")  # (4, 384)

# Multilingual untuk bahasa Indonesia
model_multi = SentenceTransformer("intfloat/multilingual-e5-large")
embeddings_id = model_multi.encode([
    "Apa itu machine learning?",
    "Machine learning adalah cabang AI",
    "Resep masakan Indonesia"
])
print(f"Shape: {embeddings_id.shape}")  # (3, 1024)

Perbandingan Metrik Similarity

MetrikRangeKelebihanKekurangan
Cosine Similarity[-1, 1]Scale-invariant, paling umumIgnore magnitude
Euclidean (L2)[0, โˆž)Intuitif, cepatDipengaruhi dimensi tinggi
Dot Product(-โˆž, โˆž)Cepat, untuk normalized vectorsTidak scale-invariant
Manhattan (L1)[0, โˆž)Robust terhadap outlierKurang akurat untuk high-dim
Python โ€” Batch Similarity Search
# =============================================
# Efficient Batch Similarity Search
# =============================================
import numpy as np

def batch_cosine_search(query_emb, doc_embeddings, top_k=5):
    """Vectorized cosine similarity โ€” sangat cepat."""
    # Normalize
    query_norm = query_emb / np.linalg.norm(query_emb)
    doc_norms = doc_embeddings / np.linalg.norm(doc_embeddings, axis=1, keepdims=True)
    
    # Dot product (sama dengan cosine karena sudah normalized)
    scores = np.dot(doc_norms, query_norm)
    
    # Top-K
    top_indices = np.argsort(scores)[::-1][:top_k]
    return [(i, scores[i]) for i in top_indices]

# Contoh dengan 1 juta dokumen (simulasi)
import time
n_docs = 1_000_000
dim = 384

# Simulate embeddings
doc_embeddings = np.random.randn(n_docs, dim).astype(np.float32)
query = np.random.randn(dim).astype(np.float32)

start = time.time()
results = batch_cosine_search(query, doc_embeddings, top_k=10)
elapsed = time.time() - start
print(f"Search 1M docs: {elapsed:.3f} seconds")
print(f"Top result: index={results[0][0]}, score={results[0][1]:.4f}")

4. Similarity Metrics

Setelah mendapatkan vektor, kita perlu mengukur kemiripan antar vektor. Ada beberapa metrik yang umum digunakan.

Diagram: Similarity Metrics
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                SIMILARITY METRICS                                โ”‚
โ”‚                                                                  โ”‚
โ”‚  1. Cosine Similarity (paling umum)                            โ”‚
โ”‚     cos(A,B) = (AยทB) / (|A| ร— |B|)                            โ”‚
โ”‚     Range: [-1, 1]  โ†’ 1=sama persis, 0=berbeda total          โ”‚
โ”‚                                                                  โ”‚
โ”‚  2. Euclidean Distance (L2)                                     โ”‚
โ”‚     d = โˆš(ฮฃ(a-b)ยฒ)                                             โ”‚
โ”‚     Semakin kecil = semakin mirip                              โ”‚
โ”‚                                                                  โ”‚
โ”‚  3. Dot Product                                                 โ”‚
โ”‚     score = AยทB = ฮฃ(aร—b)                                       โ”‚
โ”‚     Cocok untuk normalized vectors                              โ”‚
โ”‚                                                                  โ”‚
โ”‚  4. Manhattan Distance (L1)                                     โ”‚
โ”‚     d = ฮฃ|a-b|                                                  โ”‚
โ”‚     Lebih robust terhadap outlier                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
Python โ€” Similarity Calculation
# =============================================
# Similarity Metrics
# =============================================
import numpy as np
from numpy.linalg import norm

def cosine_similarity(a, b):
    return np.dot(a, b) / (norm(a) * norm(b))

def euclidean_distance(a, b):
    return norm(a - b)

def dot_product(a, b):
    return np.dot(a, b)

# Contoh penggunaan
texts = [
    "Saya suka belajar AI",          # 0
    "AI sangat menarik dipelajari",   # 1
    "Resep nasi goreng spesial",      # 2
]

embeddings = model.encode(texts)

# Hitung similarity
for i in range(len(texts)):
    for j in range(i+1, len(texts)):
        sim = cosine_similarity(embeddings[i], embeddings[j])
        print(f"'{texts[i][:30]}' vs '{texts[j][:30]}': {sim:.3f}")

# Output:
# 'Saya suka belajar AI' vs 'AI sangat menarik dipelajari': 0.821
# 'Saya suka belajar AI' vs 'Resep nasi goreng spesial': 0.142
# 'AI sangat menarik dipelajari' vs 'Resep nasi goreng spesial': 0.098
Python โ€” Semantic Search Engine
# =============================================
# Semantic Search Engine
# =============================================
import numpy as np
from sentence_transformers import SentenceTransformer

class SemanticSearchEngine:
    def __init__(self, model_name="all-MiniLM-L6-v2"):
        self.model = SentenceTransformer(model_name)
        self.documents = []
        self.embeddings = None
    
    def add_documents(self, docs):
        self.documents.extend(docs)
        new_embeddings = self.model.encode(docs, show_progress_bar=True)
        if self.embeddings is None:
            self.embeddings = new_embeddings
        else:
            self.embeddings = np.vstack([self.embeddings, new_embeddings])
        print(f"Added {len(docs)} docs. Total: {len(self.documents)}")
    
    def search(self, query, top_k=5, threshold=0.3):
        query_embedding = self.model.encode([query])[0]
        
        # Cosine similarity
        similarities = np.dot(self.embeddings, query_embedding) / (
            np.linalg.norm(self.embeddings, axis=1) * np.linalg.norm(query_embedding)
        )
        
        # Sort by similarity
        top_indices = np.argsort(similarities)[::-1][:top_k]
        
        results = []
        for idx in top_indices:
            score = similarities[idx]
            if score >= threshold:
                results.append({
                    "document": self.documents[idx],
                    "score": float(score),
                    "index": int(idx)
                })
        return results

# Usage
engine = SemanticSearchEngine()
engine.add_documents([
    "Python adalah bahasa pemrograman populer untuk data science",
    "Machine learning menggunakan data untuk membuat prediksi",
    "Deep learning adalah subset dari machine learning",
    "NLP memproses bahasa manusia dengan AI",
    "Computer vision mendeteksi objek dalam gambar",
    "Resep nasi goreng dengan bumbu sederhana",
    "Cara membuat kue brownies coklat",
    "Prediksi harga saham menggunakan LSTM",
])

results = engine.search("cara belajar artificial intelligence", top_k=3)
for r in results:
    print(f"[{r['score']:.3f}] {r['document']}")

6. Dimensionality Reduction

Python โ€” t-SNE & UMAP Visualization
# =============================================
# Dimensionality Reduction untuk Visualisasi
# =============================================
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
import numpy as np

# Embeddings (384 dimensi) โ†’ 2D
tsne = TSNE(n_components=2, random_state=42, perplexity=30)
embeddings_2d = tsne.fit_transform(embeddings)

# Visualisasi
fig, ax = plt.subplots(figsize=(10, 8))
categories = ["AI", "AI", "Food", "Food", "AI", "Food", "AI"]
colors = {"AI": "blue", "Food": "red"}

for i, (x, y) in enumerate(embeddings_2d):
    cat = categories[i]
    ax.scatter(x, y, c=colors[cat], s=100)
    ax.annotate(texts[i][:20], (x, y), fontsize=8)

ax.set_title("t-SNE Visualization of Embeddings")
plt.savefig("embeddings_tsne.png", dpi=150)

# ----- UMAP (lebih cepat dan stabil) -----
# pip install umap-learn
import umap

reducer = umap.UMAP(n_components=2, random_state=42)
embeddings_2d = reducer.fit_transform(embeddings)

# ----- PCA (tercepat, linear) -----
from sklearn.decomposition import PCA

pca = PCA(n_components=2)
embeddings_2d_pca = pca.fit_transform(embeddings)
print(f"Explained variance: {pca.explained_variance_ratio_.sum():.2%}")

7. Image & Multimodal Embeddings

Python โ€” Image Embeddings dengan CLIP
# =============================================
# Image & Multimodal Embeddings (CLIP)
# =============================================
from sentence_transformers import SentenceTransformer
from PIL import Image
import torch

# CLIP: bisa embed teks DAN gambar dalam ruang yang sama
model = SentenceTransformer("clip-ViT-B-32")

# Embed gambar
image = Image.open("gambar/kucing.jpg")
image_embedding = model.encode(image)

# Embed teks
text_embedding = model.encode(["foto seekor kucing"])

# Similarity antara gambar dan teks!
from sentence_transformers.util import cos_sim
similarity = cos_sim(image_embedding, text_embedding)
print(f"Image-Text similarity: {similarity:.3f}")

# Semantic search gambar
images = [
    Image.open("img/cat.jpg"),
    Image.open("img/dog.jpg"),
    Image.open("img/car.jpg"),
    Image.open("img/laptop.jpg"),
]
image_embeddings = model.encode(images)

query = "hewan peliharaan lucu"
query_embedding = model.encode(query)

similarities = cos_sim(query_embedding, image_embeddings)
print(f"Most similar: image {similarities.argmax()} ({similarities.max():.3f})")

8. Evaluasi Embeddings

Python โ€” Evaluasi Kualitas Embeddings
# =============================================
# Evaluasi Embeddings
# =============================================

# ----- 1. Retrieval Metrics -----
def recall_at_k(relevant_docs, retrieved_docs, k):
    retrieved = set(retrieved_docs[:k])
    relevant = set(relevant_docs)
    return len(retrieved & relevant) / len(relevant)

def precision_at_k(relevant_docs, retrieved_docs, k):
    retrieved = set(retrieved_docs[:k])
    relevant = set(relevant_docs)
    return len(retrieved & relevant) / k

def mrr(relevant_docs, retrieved_docs):
    """Mean Reciprocal Rank"""
    for i, doc in enumerate(retrieved_docs):
        if doc in relevant_docs:
            return 1.0 / (i + 1)
    return 0.0

# Evaluasi
queries = {
    "apa itu AI": [0, 1, 3],       # Indices dokumen relevan
    "resep masakan": [5, 6],        # Indices dokumen relevan
}

for query, relevant in queries.items():
    results = engine.search(query, top_k=5)
    retrieved = [r["index"] for r in results]
    r5 = recall_at_k(relevant, retrieved, 5)
    p3 = precision_at_k(relevant, retrieved, 3)
    print(f"Query: '{query}' โ†’ R@5={r5:.2f}, P@3={p3:.2f}")

# ----- 2. Benchmark datasets -----
# MTEB (Massive Text Embedding Benchmark)
# https://huggingface.co/spaces/mteb/leaderboard
# Bandingkan model pada berbagai task dan bahasa

9. Deployment & Best Practices

๐Ÿ’ก Best Practices Embeddings
  • Konsistensi model โ€” selalu gunakan model yang SAMA untuk index dan query
  • Normalize โ€” normalisasi vektor jika menggunakan cosine similarity
  • Dimensionality โ€” dimensi lebih tinggi = lebih akurat tapi lebih lambat
  • Batch processing โ€” embed dalam batch, bukan satu per satu
  • Caching โ€” cache embedding untuk dokumen yang tidak berubah
  • Evaluation โ€” ukur recall@k dan precision@k secara berkala
  • Multilingual โ€” gunakan model multilingual untuk bahasa Indonesia
  • Hybrid search โ€” gabungkan keyword + semantic search untuk hasil terbaik
๐Ÿ’ก Kapan Menggunakan Embedding yang Mana?
  • Prototyping cepat โ†’ all-MiniLM-L6-v2 (gratis, cepat)
  • Produksi bahasa Inggris โ†’ text-embedding-3-small (murah, bagus)
  • Produksi bahasa Indonesia โ†’ multilingual-e5-large atau text-embedding-3-large
  • Pencarian gambar โ†’ CLIP (text + image dalam satu ruang)
  • Budget unlimited โ†’ Cohere embed-v3 atau text-embedding-3-large

10. Quiz Pemahaman

1. Apa itu vector embedding?

2. Metric apa yang paling umum untuk semantic search?

3. Mengapa model embedding harus konsisten?

4. Apa keunggulan CLIP dibanding model embedding teks biasa?

5. Apa fungsi dimensionality reduction (t-SNE, UMAP)?

Rangkuman

๐Ÿ“ Poin Penting
  • Embeddings โ€” representasi data sebagai vektor berdimensi tinggi
  • Cosine similarity โ€” metric paling umum untuk semantic search
  • Model selection โ€” OpenAI (bayar, bagus) vs Sentence Transformers (gratis, lokal)
  • CLIP โ€” embed teks + gambar dalam satu ruang
  • Konsistensi โ€” selalu gunakan model embedding yang sama
  • Evaluasi โ€” ukur recall@k, precision@k, MRR untuk kualitas retrieval