--- id: wiki-2026-0508-latent-dirichlet-allocation title: Latent Dirichlet Allocation category: 10_Wiki/Topics status: verified canonical_id: self aliases: [LDA, Topic Model, Latent Dirichlet] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [nlp, topic-modeling, unsupervised, bayesian, gensim] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: python framework: gensim --- # Latent Dirichlet Allocation ## 매 한 줄 > **"매 문서 = topic 의 mixture, topic = word 의 mixture"**. Blei 2003 의 generative bayesian model. 2026 현재는 BERTopic 류 embedding 기반에 점유율 양보 중이지만, 해석 가능성/저비용에서 여전히 baseline. ## 매 핵심 ### 매 Generative story 1. 각 topic k 에 대해 word distribution `φ_k ~ Dir(β)` 생성. 2. 각 문서 d 에 대해 topic distribution `θ_d ~ Dir(α)`. 3. 단어 위치마다: topic `z ~ Mult(θ_d)` 뽑고, word `w ~ Mult(φ_z)`. ### 매 추론 (inference) - **Variational Bayes** (Blei): 빠르지만 근사 거침. - **Collapsed Gibbs sampling**: gensim 기본, sample-based 정확. - 2026: 대부분 Online VB (gensim `LdaModel`) 또는 Mallet wrapper. ### 매 vs alternatives - **NMF**: matrix factorization, sparse, deterministic. 짧은 텍스트에 종종 우세. - **BERTopic**: sentence-transformer + UMAP + HDBSCAN. semantic, but heavy. - **Top2Vec**: doc2vec 기반. ## 💻 패턴 ### gensim LDA 기본 ```python from gensim import corpora, models texts = [doc.split() for doc in raw_docs] dictionary = corpora.Dictionary(texts) dictionary.filter_extremes(no_below=5, no_above=0.5) corpus = [dictionary.doc2bow(t) for t in texts] lda = models.LdaModel(corpus, num_topics=20, id2word=dictionary, passes=10, alpha="auto", eta="auto") for topic_id, words in lda.print_topics(): print(topic_id, words) ``` ### Coherence 기반 K 선택 ```python from gensim.models.coherencemodel import CoherenceModel scores = {} for k in [10, 15, 20, 30, 50]: m = models.LdaModel(corpus, num_topics=k, id2word=dictionary, passes=5) cm = CoherenceModel(model=m, texts=texts, dictionary=dictionary, coherence="c_v") scores[k] = cm.get_coherence() best_k = max(scores, key=scores.get) ``` ### sklearn LatentDirichletAllocation ```python from sklearn.feature_extraction.text import CountVectorizer from sklearn.decomposition import LatentDirichletAllocation cv = CountVectorizer(max_df=0.5, min_df=5, stop_words="english") X = cv.fit_transform(raw_docs) lda = LatentDirichletAllocation(n_components=20, learning_method="online", random_state=0).fit(X) doc_topic = lda.transform(X) # (n_docs, 20) ``` ### 새 문서 inference ```python new_bow = dictionary.doc2bow(new_doc.split()) topic_dist = lda.get_document_topics(new_bow, minimum_probability=0.01) ``` ### pyLDAvis 시각화 ```python import pyLDAvis.gensim_models vis = pyLDAvis.gensim_models.prepare(lda, corpus, dictionary) pyLDAvis.save_html(vis, "lda.html") ``` ### BERTopic (LDA 후속) ```python from bertopic import BERTopic topic_model = BERTopic(language="english", min_topic_size=10) topics, probs = topic_model.fit_transform(raw_docs) topic_model.get_topic_info() ``` ## 매 결정 기준 | 상황 | 모델 | |---|---| | 긴 문서, 해석 가능성 우선 | LDA | | 짧은 텍스트 (tweet) | NMF / BTM | | Semantic clustering 필요 | BERTopic | | 실시간 streaming | Online LDA | | GPU 없음, 수백만 문서 | gensim LDA + multicore | **기본값**: gensim `LdaMulticore`, K = 20-50, coherence c_v 로 튜닝. ## 🔗 Graph - Adjacent: [[TF-IDF]], [[Word-Embeddings]] ## 🤖 LLM 활용 **언제**: 대규모 코퍼스 빠른 EDA, 해석 가능한 topic label, BERTopic 비용 부담스러울 때. **언제 X**: 짧은 텍스트, semantic 차이 중요, 다국어 mix. ## ❌ 안티패턴 - **불용어 미제거**: top word 가 the/of 로 도배. - **K 임의 고정**: coherence/perplexity 없이 20 박는 것. - **단일 단어 토큰화**: bigram 무시 → "machine learning" 분리. - **너무 짧은 문서**: 트윗에 표준 LDA → 노이즈. ## 🧪 검증 / 중복 - Blei, Ng, Jordan 2003 (JMLR). - gensim, sklearn, Mallet 공식 문서. - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — gensim/sklearn 패턴, BERTopic 비교, coherence 튜닝 |