yusiwen's picture
feat: add Word2Vec (CBOW + Skip-gram + Negative Sampling)
55d37a9 unverified
Raw
History Blame Contribute Delete
2.21 kB
"""
Word2Vec evaluation: find similar words and visualise embedding space.
After training, the embedding matrix encodes semantic relationships:
similar words have similar vectors (measured by cosine similarity).
Examples of learned relationships:
- "dog" ≈ "cat" (animals)
- "good" ≈ "great" (positive adjectives)
- "run" ≈ "running" (morphological variants)
"""
import torch
import torch.nn.functional as F
def load_vectors(path="nlp/word2vec/skipgram.pt"):
"""Load trained embeddings and vocabulary."""
data = torch.load(path, map_location="cpu")
return data["embeddings"], data["id_to_word"]
def cosine_similarities(query_vec, all_vecs):
"""Compute cosine similarity between query and all vectors."""
query_vec = query_vec / query_vec.norm()
all_vecs = all_vecs / all_vecs.norm(dim=1, keepdim=True)
return all_vecs @ query_vec
def find_similar(word, embeddings, id_to_word, word_to_id, top_k=10):
"""Find the top_k most similar words to the query word."""
if word not in word_to_id:
print(f" '{word}' not in vocabulary")
return
idx = word_to_id[word]
query_vec = embeddings[idx]
sims = cosine_similarities(query_vec, embeddings)
# Get top-k (excluding the word itself).
values, indices = sims.topk(top_k + 1)
print(f"\n Similar to '{word}':")
for i in range(1, top_k + 1):
similar_word = id_to_word[indices[i].item()]
print(f" {similar_word:<12} {values[i].item():.4f}")
def evaluate():
embeddings, id_to_word = load_vectors()
# Build reverse mapping.
word_to_id = {w: i for i, w in enumerate(id_to_word)}
vocab_size, embed_dim = embeddings.shape
print(f"Embeddings: {vocab_size} words × {embed_dim} dims\n")
# Test words (choose common English words from PTB).
test_words = [
"company", "market", "year",
"good", "new", "last",
"government", "bank", "president",
"increase", "decrease", "change",
"large", "small", "important",
"work", "study", "help",
]
for word in test_words:
find_similar(word, embeddings, id_to_word, word_to_id)
if __name__ == "__main__":
evaluate()