자연어 처리 개요¶
자연어 처리(Natural Language Processing, NLP)는 인간 언어를 컴퓨터가 이해하고 생성할 수 있도록 하는 인공지능 분야다. 텍스트 분류, 감성 분석, 기계 번역, 질의응답 등 다양한 응용에 활용됨.
핵심 개념¶
텍스트 표현¶
| 방법 | 설명 | 장점 | 단점 |
|---|---|---|---|
| Bag of Words | 단어 출현 빈도 벡터 | 간단 | 순서 무시, 희소 |
| TF-IDF | 빈도 x 역문서빈도 | 중요 단어 강조 | 순서 무시 |
| Word2Vec | 분산 표현 (CBOW/Skip-gram) | 의미 유사도 | 다의어 미처리 |
| GloVe | 전역 동시출현 행렬 분해 | 전역 통계 활용 | 다의어 미처리 |
| FastText | 서브워드 임베딩 | OOV 처리 | 벡터 크기 |
| ELMo | 문맥 의존 임베딩 (BiLSTM) | 다의어 처리 | 느림 |
| BERT | Transformer 양방향 | SOTA, 전이학습 | 계산량 |
토큰화 (Tokenization)¶
| 방법 | 예시 | 특징 |
|---|---|---|
| 단어 단위 | "playing" → "playing" | OOV 문제 |
| BPE (Byte Pair Encoding) | "playing" → "play", "##ing" | GPT 계열 |
| WordPiece | "playing" → "play", "##ing" | BERT |
| SentencePiece | 언어 무관 | 다국어 |
알고리즘 분류 체계¶
NLP Tasks & Methods
├── Text Classification
│ ├── Traditional: Naive Bayes, SVM, Logistic
│ ├── Neural: CNN, LSTM, Transformer
│ └── Pre-trained: BERT, RoBERTa, DeBERTa
├── Sequence Labeling
│ ├── NER (Named Entity Recognition)
│ ├── POS Tagging
│ └── Methods: CRF, BiLSTM-CRF, BERT+CRF
├── Text Generation
│ ├── Language Models: GPT, LLaMA
│ ├── Seq2Seq: T5, BART
│ └── Decoding: Greedy, Beam, Sampling
├── Information Extraction
│ ├── Relation Extraction
│ ├── Event Extraction
│ └── Knowledge Graph Construction
├── Semantic Analysis
│ ├── Sentiment Analysis
│ ├── Aspect-Based SA
│ └── Emotion Detection
├── Topic Modeling
│ ├── LDA (Latent Dirichlet Allocation)
│ ├── NMF
│ └── BERTopic
├── Question Answering
│ ├── Extractive QA (BERT)
│ ├── Generative QA (T5, GPT)
│ └── RAG (Retrieval-Augmented Generation)
├── Machine Translation
│ ├── Seq2Seq + Attention
│ └── Transformer (mBART, NLLB)
└── Summarization
├── Extractive
└── Abstractive (BART, T5)
텍스트 분류 (Text Classification)¶
BERT 기반 분류¶
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import Trainer, TrainingArguments
import torch
# 모델 로드
model_name = "klue/bert-base" # 한국어
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
model_name,
num_labels=3
)
# 토큰화
def tokenize_function(examples):
return tokenizer(
examples["text"],
padding="max_length",
truncation=True,
max_length=256
)
tokenized_datasets = dataset.map(tokenize_function, batched=True)
# 학습 설정
training_args = TrainingArguments(
output_dir="./results",
num_train_epochs=3,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
warmup_steps=500,
weight_decay=0.01,
logging_dir="./logs",
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["test"],
)
trainer.train()
참고 논문: - Devlin, J. et al. (2019). "BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding". NAACL. - Liu, Y. et al. (2019). "RoBERTa: A Robustly Optimized BERT Pretraining Approach". arXiv.
개체명 인식 (NER)¶
시퀀스 레이블링 태스크로 텍스트에서 인명, 지명, 기관명 등을 추출.
BIO 태깅: - B-PER: Person 시작 - I-PER: Person 내부 - O: 엔티티 아님
from transformers import AutoTokenizer, AutoModelForTokenClassification
from transformers import pipeline
# NER 파이프라인
ner_pipeline = pipeline(
"ner",
model="klue/bert-base", # Fine-tuned NER model
aggregation_strategy="simple"
)
text = "삼성전자 이재용 회장이 서울에서 기자회견을 열었다."
entities = ner_pipeline(text)
# 결과: [{'entity_group': 'ORG', 'word': '삼성전자', ...}, ...]
감성 분석 (Sentiment Analysis)¶
문서 수준 감성¶
from transformers import pipeline
# 감성 분석
sentiment_analyzer = pipeline(
"sentiment-analysis",
model="nlptown/bert-base-multilingual-uncased-sentiment"
)
result = sentiment_analyzer("이 제품 정말 좋아요!")
# {'label': '5 stars', 'score': 0.85}
속성 기반 감성 분석 (ABSA)¶
특정 속성(aspect)에 대한 감성 추출:
"이 식당은 음식은 맛있는데 서비스가 별로다" - 음식: 긍정 - 서비스: 부정
토픽 모델링¶
LDA (Latent Dirichlet Allocation)¶
문서 집합에서 잠재 토픽 발견:
from sklearn.decomposition import LatentDirichletAllocation
from sklearn.feature_extraction.text import CountVectorizer
# 문서-단어 행렬
vectorizer = CountVectorizer(max_df=0.95, min_df=2, max_features=1000)
doc_term_matrix = vectorizer.fit_transform(documents)
# LDA
lda = LatentDirichletAllocation(
n_components=10, # 토픽 수
random_state=42
)
lda.fit(doc_term_matrix)
# 토픽별 주요 단어
feature_names = vectorizer.get_feature_names_out()
for topic_idx, topic in enumerate(lda.components_):
top_words = [feature_names[i] for i in topic.argsort()[:-10:-1]]
print(f"Topic {topic_idx}: {', '.join(top_words)}")
BERTopic¶
BERT 임베딩 기반 토픽 모델링:
from bertopic import BERTopic
topic_model = BERTopic(language="multilingual")
topics, probs = topic_model.fit_transform(documents)
# 토픽 정보
topic_model.get_topic_info()
topic_model.visualize_topics()
참고 논문: - Blei, D.M. et al. (2003). "Latent Dirichlet Allocation". JMLR. - Grootendorst, M. (2022). "BERTopic: Neural Topic Modeling with a Class-based TF-IDF". arXiv.
LLM 시대의 NLP¶
Prompt Engineering¶
LLM을 활용한 Zero-shot / Few-shot 학습:
from openai import OpenAI
client = OpenAI()
# Zero-shot 분류
prompt = """다음 리뷰의 감성을 분류하세요: 긍정, 부정, 중립
리뷰: "배송은 빨랐는데 제품 품질이 실망스럽네요"
감성:"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
RAG (Retrieval-Augmented Generation)¶
외부 지식을 검색하여 LLM 응답 품질 향상:
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# 벡터 스토어 생성
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(documents, embeddings)
# RAG 체인
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(),
chain_type="stuff",
retriever=vectorstore.as_retriever(search_kwargs={"k": 3})
)
answer = qa_chain.run("질문 내용")
참고 논문: - Lewis, P. et al. (2020). "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks". NeurIPS.
한국어 NLP¶
주요 모델¶
| 모델 | 기관 | 특징 |
|---|---|---|
| KoBERT | SKT | BERT 한국어 |
| KoELECTRA | 개인 | ELECTRA 한국어 |
| KLUE-BERT | KLUE | 벤치마크와 함께 공개 |
| KoGPT | 카카오 | GPT 한국어 |
| HyperCLOVA | 네이버 | 대규모 한국어 LLM |
형태소 분석¶
from konlpy.tag import Okt, Mecab
okt = Okt()
text = "자연어 처리는 재미있습니다."
# 형태소 분석
print(okt.morphs(text)) # ['자연어', '처리', '는', '재미있습니다', '.']
print(okt.pos(text)) # [('자연어', 'Noun'), ('처리', 'Noun'), ...]
print(okt.nouns(text)) # ['자연어', '처리']
평가 지표¶
| 태스크 | 지표 |
|---|---|
| 분류 | Accuracy, F1, AUC-ROC |
| NER | Entity-level F1 |
| 생성 | BLEU, ROUGE, BERTScore |
| QA | Exact Match, F1 |
| 번역 | BLEU, COMET |
참고 문헌¶
교과서¶
- Jurafsky, D. & Martin, J.H. (2023). "Speech and Language Processing" (3rd ed). (무료 온라인)
- Goldberg, Y. (2017). "Neural Network Methods for Natural Language Processing". Morgan & Claypool.
핵심 논문¶
- Vaswani, A. et al. (2017). "Attention Is All You Need". NeurIPS.
- Devlin, J. et al. (2019). "BERT". NAACL.
- Brown, T. et al. (2020). "Language Models are Few-Shot Learners". NeurIPS.
라이브러리¶
- Hugging Face Transformers: https://huggingface.co/transformers
- spaCy: https://spacy.io/
- KoNLPy: https://konlpy.org/