Files
koriweb d8a80f6272 chore(wiki): dangling 링크 canonical 정규화 (768파일/1200건)
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해
끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은
과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업.
도구: Datacollect/scripts/link_reconcile_apply.mjs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:24:15 +09:00

187 lines
6.5 KiB
Markdown

---
id: wiki-2026-0508-stem-analysis
title: Stem Analysis
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Stemming, Word Stemming, 형태소 어간추출]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [nlp, stemming, lemmatization, text-preprocessing]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: python
framework: nltk-spacy-stanza
---
# Stem Analysis
## 매 한 줄
> **"매 stem = word 의 morphological root, 매 prefix/suffix 제거"**. Porter (1980) → Snowball → Lancaster 의 evolution. 2026 LLM era 에선 매 BPE/SentencePiece tokenizer 가 자연스럽게 흡수 — stemming explicit 사용 매 classical IR/sparse search 만.
## 매 핵심
### 매 stem vs lemma
- **Stem**: 매 surface-level chop ("running" → "run", "studies" → "studi"). Heuristic, 매 invalid word OK.
- **Lemma**: 매 dictionary form ("ran" → "run", "better" → "good"). POS-aware, 매 valid word.
- **Tokenization** (BPE/WordPiece/SentencePiece): 매 LLM era 의 default — sub-word 의 학습된 segmentation.
### 매 algorithms
- **Porter Stemmer** (1980, Martin Porter): 매 5-step rule cascade — English 의 de-facto.
- **Snowball / Porter2** (2002): 매 multi-language framework — Porter 의 cleaner re-design.
- **Lancaster (Paice/Husk)**: 매 aggressive — 매 over-stemming 위험.
- **Lovins** (1968): 매 first published, 매 longest-match 의 single pass.
- **Korean (Hannanum/Mecab/Khaiii)**: 매 morphological analyzer — 매 stemming 보다 morpheme segmentation 이 적합.
### 매 응용
1. **Classical IR / BM25**: Elasticsearch / OpenSearch analyzer chain — 매 Snowball default.
2. **Sparse retrieval (SPLADE)**: 매 hybrid 의 sparse leg.
3. **Topic modeling (LDA)**: 매 vocabulary 의 collapse.
4. **Feature engineering (legacy ML)**: TF-IDF + classifier.
5. **Domain search 의 keyword expansion**: 매 e-commerce, legal, medical.
## 💻 패턴
### Porter / Snowball (NLTK)
```python
from nltk.stem import PorterStemmer, SnowballStemmer
porter = PorterStemmer()
snow = SnowballStemmer("english")
words = ["running", "ran", "runs", "studies", "studying", "easily", "fairly"]
for w in words:
print(w, "->", porter.stem(w), "/", snow.stem(w))
# running -> run / run
# studies -> studi / studi
# easily -> easili / easili (heuristic, not a real word)
```
### Lemmatization (spaCy, POS-aware)
```python
import spacy
nlp = spacy.load("en_core_web_lg") # 2026: spacy 4.x
doc = nlp("The runners ran more easily than the studies suggested.")
for tok in doc:
print(tok.text, tok.lemma_, tok.pos_)
# runners runner NOUN
# ran run VERB
# easily easily ADV
# studies study NOUN
```
### Korean morphological analysis (Mecab)
```python
# 매 Korean: stemming X — morpheme segmentation 적합
from konlpy.tag import Mecab
mecab = Mecab()
text = "어제 친구들과 영화관에 갔었습니다"
print(mecab.morphs(text))
# ['어제', '친구', '들', '과', '영화관', '에', '가', '었', '습니다']
print(mecab.pos(text))
# [('어제', 'MAG'), ('친구', 'NNG'), ('들', 'XSN'), ...]
```
### Elasticsearch analyzer chain (2026 OpenSearch 3.x)
```json
PUT /products
{
"settings": {
"analysis": {
"analyzer": {
"english_stem": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "english_stop", "english_stemmer"]
}
},
"filter": {
"english_stemmer": { "type": "stemmer", "language": "english" }
}
}
}
}
```
### Stemming + BM25 retrieval
```python
from rank_bm25 import BM25Okapi
from nltk.stem import SnowballStemmer
import re
stem = SnowballStemmer("english").stem
def tokenize(text):
return [stem(t) for t in re.findall(r"\w+", text.lower())]
corpus = ["The cat is running", "Cats run fast", "Dogs bark loudly"]
tokenized = [tokenize(d) for d in corpus]
bm25 = BM25Okapi(tokenized)
query = tokenize("running cats")
print(bm25.get_scores(query))
# Cat/cats + run/running stems collapse → relevant docs score higher
```
### Modern hybrid: BPE token (LLM-era default)
```python
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("meta-llama/Llama-3.3-70B-Instruct")
print(tok.tokenize("running runners studies"))
# ['Ġrunning', 'Ġrunners', 'Ġstudies'] — 매 sub-word, 매 stemming 의 implicit
# 매 LLM 은 매 surface form 의 학습 — explicit stemming 의 X 필요.
```
### Over-stemming detection
```python
from nltk.stem import LancasterStemmer
lan = LancasterStemmer()
# 매 Lancaster aggressive 의 example
print(lan.stem("organization")) # 'org' — 매 too aggressive
print(lan.stem("organic")) # 'org' — 매 false conflation
# 매 Snowball preferred over Lancaster 의 production.
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| 매 LLM-based search (dense / RAG) | 매 stemming X — embedding 이 흡수 |
| BM25 / lexical search | Snowball stemmer 기본 |
| Topic modeling / 매 sparse features | Snowball + 매 stopword |
| 매 한국어 / 일본어 / 중국어 | 매 morphological analyzer (Mecab, Khaiii) |
| Aggressive 의 conflation 필요 | Lancaster — 매 over-stem 주의 |
**기본값**: 매 Snowball (English/multi-lang) + spaCy lemmatizer (POS 가 중요한 경우). 매 dense retrieval 시 stemming X.
## 🔗 Graph
- 부모: [[Information Retrieval]]
- 변형: [[Tokenization]] · [[BPE]] · [[SentencePiece]]
- 응용: [[BM25]] · [[Elasticsearch]] · [[TF-IDF]]
- Adjacent: [[Morphological-Analysis]]
## 🤖 LLM 활용
**언제**: 매 legacy IR pipeline, hybrid (sparse+dense) retrieval 의 sparse leg, domain-specific keyword expansion (legal/medical).
**언제 X**: 매 modern dense retrieval (E5, BGE, Voyage 3), LLM RAG — 매 BPE tokenizer 가 흡수. 매 explicit stemming 의 over-engineering.
## ❌ 안티패턴
- **Stemming dense embeddings 전**: 매 embedding model 이 surface form 의 학습 — stemming 이 정보 파괴.
- **Lancaster 의 production**: 매 over-stemming 의 false-positive 폭증.
- **English stemmer 매 한국어 적용**: 매 nonsense 결과 — language-specific analyzer 필수.
- **Lemma 의 POS X**: "saw" (verb→see / noun→saw) 의 ambiguity — POS tag 없이 lemmatize 의 부정확.
## 🧪 검증 / 중복
- Verified (Porter 1980 paper, Snowball stemmer.tartarus.org, NLTK/spaCy/Stanza 2026 docs).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — stemming algorithms + LLM era 의 위치 정리 |