| """ |
| 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) |
|
|
| |
| 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() |
|
|
| |
| 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 = [ |
| "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() |
|
|