02_word_embeddings.py

Download
python 234 lines 6.5 KB
  1"""
  202. Word2Vec과 GloVe - 단어 임베딩 예제
  3
  4단어 임베딩 학습과 활용
  5"""
  6
  7import numpy as np
  8
  9print("=" * 60)
 10print("단어 임베딩")
 11print("=" * 60)
 12
 13
 14# ============================================
 15# 1. 코사인 유사도
 16# ============================================
 17print("\n[1] 코사인 유사도")
 18print("-" * 40)
 19
 20def cosine_similarity(v1, v2):
 21    """두 벡터의 코사인 유사도"""
 22    dot = np.dot(v1, v2)
 23    norm = np.linalg.norm(v1) * np.linalg.norm(v2)
 24    return dot / norm if norm > 0 else 0
 25
 26# 예시 벡터
 27vec_king = np.array([0.5, 0.3, 0.8, 0.1])
 28vec_queen = np.array([0.5, 0.4, 0.7, 0.2])
 29vec_apple = np.array([-0.2, 0.9, 0.1, 0.5])
 30
 31print(f"king-queen 유사도: {cosine_similarity(vec_king, vec_queen):.4f}")
 32print(f"king-apple 유사도: {cosine_similarity(vec_king, vec_apple):.4f}")
 33
 34
 35# ============================================
 36# 2. 간단한 임베딩 레이어 (PyTorch)
 37# ============================================
 38print("\n[2] PyTorch 임베딩 레이어")
 39print("-" * 40)
 40
 41try:
 42    import torch
 43    import torch.nn as nn
 44
 45    # 임베딩 레이어
 46    vocab_size = 100
 47    embed_dim = 64
 48    embedding = nn.Embedding(vocab_size, embed_dim)
 49
 50    # 입력: 단어 인덱스
 51    input_ids = torch.tensor([1, 5, 10, 20])
 52    embedded = embedding(input_ids)
 53
 54    print(f"입력 shape: {input_ids.shape}")
 55    print(f"출력 shape: {embedded.shape}")
 56    print(f"임베딩 가중치 shape: {embedding.weight.shape}")
 57
 58except ImportError:
 59    print("PyTorch 미설치")
 60
 61
 62# ============================================
 63# 3. Gensim Word2Vec
 64# ============================================
 65print("\n[3] Gensim Word2Vec")
 66print("-" * 40)
 67
 68try:
 69    from gensim.models import Word2Vec
 70
 71    # 샘플 코퍼스
 72    sentences = [
 73        ["i", "love", "machine", "learning"],
 74        ["machine", "learning", "is", "fun"],
 75        ["deep", "learning", "is", "great"],
 76        ["i", "love", "deep", "learning"],
 77        ["neural", "networks", "are", "powerful"],
 78        ["deep", "neural", "networks", "learn", "features"],
 79    ]
 80
 81    # Word2Vec 학습
 82    model = Word2Vec(
 83        sentences,
 84        vector_size=50,    # 임베딩 차원
 85        window=3,          # 컨텍스트 윈도우
 86        min_count=1,       # 최소 빈도
 87        sg=1,              # Skip-gram (0=CBOW)
 88        epochs=100
 89    )
 90
 91    # 유사 단어
 92    print("'learning' 유사 단어:")
 93    similar = model.wv.most_similar("learning", topn=3)
 94    for word, score in similar:
 95        print(f"  {word}: {score:.4f}")
 96
 97    # 벡터 가져오기
 98    vec = model.wv["learning"]
 99    print(f"\n'learning' 벡터 shape: {vec.shape}")
100
101    # 저장/로드
102    model.save("word2vec_demo.model")
103    loaded = Word2Vec.load("word2vec_demo.model")
104    print("모델 저장/로드 완료")
105
106    # 정리
107    import os
108    os.remove("word2vec_demo.model")
109
110except ImportError:
111    print("gensim 미설치 (pip install gensim)")
112
113
114# ============================================
115# 4. 사전학습 임베딩 사용
116# ============================================
117print("\n[4] 사전학습 임베딩 적용")
118print("-" * 40)
119
120try:
121    import torch
122    import torch.nn as nn
123
124    # 가상의 사전학습 임베딩 (실제로는 GloVe 등 로드)
125    pretrained_embeddings = torch.randn(1000, 100)  # vocab_size=1000, dim=100
126
127    # 임베딩 레이어에 적용
128    embedding = nn.Embedding.from_pretrained(
129        pretrained_embeddings,
130        freeze=False,  # True면 학습 안 함
131        padding_idx=0
132    )
133
134    print(f"사전학습 임베딩 shape: {pretrained_embeddings.shape}")
135    print(f"freeze=False: 파인튜닝 가능")
136
137    # 분류 모델에 적용
138    class TextClassifier(nn.Module):
139        def __init__(self, pretrained_emb, num_classes):
140            super().__init__()
141            self.embedding = nn.Embedding.from_pretrained(pretrained_emb, freeze=False)
142            self.fc = nn.Linear(pretrained_emb.shape[1], num_classes)
143
144        def forward(self, x):
145            embedded = self.embedding(x)  # (batch, seq, embed)
146            pooled = embedded.mean(dim=1)  # 평균 풀링
147            return self.fc(pooled)
148
149    model = TextClassifier(pretrained_embeddings, num_classes=2)
150    print(f"분류 모델 생성 완료")
151
152except ImportError:
153    print("PyTorch 미설치")
154
155
156# ============================================
157# 5. 단어 유추 (Word Analogy)
158# ============================================
159print("\n[5] 단어 유추")
160print("-" * 40)
161
162def word_analogy(word_a, word_b, word_c, embeddings, word2idx, idx2word, topk=3):
163    """
164    a : b = c : ?
165    예: king : queen = man : woman
166    """
167    # 벡터 가져오기
168    vec_a = embeddings[word2idx[word_a]]
169    vec_b = embeddings[word2idx[word_b]]
170    vec_c = embeddings[word2idx[word_c]]
171
172    # 유추 벡터: b - a + c
173    target = vec_b - vec_a + vec_c
174
175    # 유사도 계산
176    similarities = np.dot(embeddings, target) / (
177        np.linalg.norm(embeddings, axis=1) * np.linalg.norm(target)
178    )
179
180    # 상위 k개 (a, b, c 제외)
181    exclude = {word2idx[word_a], word2idx[word_b], word2idx[word_c]}
182    results = []
183    for idx in np.argsort(similarities)[::-1]:
184        if idx not in exclude:
185            results.append((idx2word[idx], similarities[idx]))
186        if len(results) >= topk:
187            break
188
189    return results
190
191# 예시 (가상 데이터)
192vocab = ["king", "queen", "man", "woman", "prince", "princess", "boy", "girl"]
193word2idx = {w: i for i, w in enumerate(vocab)}
194idx2word = {i: w for i, w in enumerate(vocab)}
195
196# 가상 임베딩 (실제로는 학습된 임베딩 사용)
197np.random.seed(42)
198embeddings = np.random.randn(len(vocab), 50)
199# 의미적 관계 시뮬레이션
200embeddings[word2idx["queen"]] = embeddings[word2idx["king"]] + np.array([0.1] * 50)
201embeddings[word2idx["woman"]] = embeddings[word2idx["man"]] + np.array([0.1] * 50)
202
203result = word_analogy("king", "queen", "man", embeddings, word2idx, idx2word)
204print(f"king : queen = man : ?")
205for word, score in result:
206    print(f"  {word}: {score:.4f}")
207
208
209# ============================================
210# 정리
211# ============================================
212print("\n" + "=" * 60)
213print("단어 임베딩 정리")
214print("=" * 60)
215
216summary = """
217핵심 개념:
218    - 분산 표현: 단어를 밀집 벡터로 표현
219    - Word2Vec: Skip-gram, CBOW
220    - GloVe: 동시 출현 통계 기반
221
222사용법:
223    # Gensim Word2Vec
224    model = Word2Vec(sentences, vector_size=100, window=5)
225    similar = model.wv.most_similar("word", topn=5)
226
227    # PyTorch 임베딩
228    embedding = nn.Embedding.from_pretrained(vectors, freeze=False)
229
230단어 연산:
231    king - queen + man ≈ woman
232"""
233print(summary)