[PyTorch] 자연어 처리와 임베딩 (Embedding)
Posted: Updated:
AI 스터디를 하며 ‘파이토치 트랜스포머를 활용한 자연어 처리와 컴퓨터비전 심층학습’ 교재를 정리한 글입니다.
임베딩 (Embedding)
텍스트 벡터화 (Text Vectorization)
컴퓨터가 텍스트를 이해하도록 하기 위해 텍스트를 숫자로 변환하는 과정
벡터가 입력 텍스트의 의미를 내포하지 않아 의미적으로 유사한 문장이라도 벡터가 유사하지 않을 수 있음
- 원-핫 인코딩(One-Hot Encoding): 문서에 등장하는 각 단어를 고유한 값으로 매핑하여 해당하는 위치를 1로 표시, 나머지는 0으로 표시
- 빈도 벡터화(Count Vectorization): 문서에서 단어의 수를 세어 해당 단어의 빈도를 벡터로 표현
희소성(Sparsity) 문제
벡터의 대부분이 0으로 채워지는 희소 벡터가 되면 저장 공간, 계산 자원을 낭비할 수 있음
고차원 데이터에서 데이터 분포가 더 희소해서 차원의 저주(Curse of Dimensionality) 라고도 함
코퍼스의 토큰 대비 입력 문장의 토큰 수가 적으므로 컴퓨팅 비용이 증가
워드 임베딩 (Word Embedding)
단어를 고정 길이의 실수 벡터로 표현하는 방법
단어의 의미를 벡터 공간에서 다른 단어와의 상대적 위치로 표현하여 단어 간 관계 추론
ex) 워드 투 벡터(Word2Vec), 패스트 텍스트(fastText)
동적 임베딩 (Dynamic Embedding)
다의어나 문맥 정보를 효과적으로 다루기 위해 인공 신경망을 활용한 기법
언어 모델(Language Model)
입력된 문장으로 각 문장을 생성할 수 있는 확률을 계산하는 모델
자동 번역, 음성 인식, 텍스트 요약 등에 활용
자기회귀 언어 모델(Autoregressive Language Model)
문장 전체를 예측하지 않고 하나의 토큰 단위로 예측하는 방식
입력 문장들의 조건부 확률을 이용해 다음 단어 예측
이전에 등장한 모든 토큰 정보를 고려하여 문백 정보를 파악해 다음 단어 생성
조건부 확률
\[P(w_t \mid w_1, w_2, \dots, w_{t-1}) = \frac{P(w_1, w_2, \dots, w_t)}{P(w_1, w_2, \dots, w_{t-1})}\]이전 단어들의 시퀀스가 주어졌을 때 다음 단어의 확률을 계산하는 것
한 사건이 일어날 확률을 다른 사건들의 조건부 확률을 이용해 계산하는 조건부 확률의 연쇄법칙을 활용
문장 전체의 확률 = 첫 번째 단어의 확률($P(w_1)$) * 각 단어가 이전 단어들의 조건부 확률에 따라 발생할 확률
통계적 언어 모델(Statistical Language Model)
언어의 통계적 구조를 이용해 문장이나 단어의 시퀀스 생성 또는 분석
시퀀스에 대한 확률 분포를 추정해 문장의 문맥을 파악해 다음에 등장할 단어 확률 예측
기존 학습한 텍스트 데이터에서 패턴을 찾아 확률 분포 생성
새로운 문장 생성, 다양한 종류의 텍스트 데이터 학습 가능
대규모 자연어 데이터 처리에 효과적
마르코프 체인(Markov Chain)
빈도 기반 조건부 확률 모델 중 하나
이전 상태와 현재 상태 간 전이 확률로 다음 상태 예측
(등장 횟수: ‘안녕하세요’ 1,000번, ‘안녕하세요 만나서’ 700번, ‘안녕하세요 반갑습니다’ 100번)
단점
- 단어의 순서와 빈도만 고려하므로 문맥을 파악하지 못하면 결과가 좋지 않을 수 있음
- 데이터 희소성 문제: 한 번도 등장한 적 없는 단어, 문장에 대한 예측이 어려움
N-gram
기초적인 통계적 언어 모델
텍스트에서 N개의 연속된 단어 시퀀스를 하나의 단위로 취급해 특정 단어 시퀀스가 등장할 확률 추정
N이 1일 때는 유니그램(Unigram), 2일 때는 바이그램(Bigram), 3일 때는 트라이그램(Trigram), 4 이상일 경우 N-gram
N 값을 조절해 모델 성능 조절 가능
구현이 상대적으로 쉬우며 작은 규모의 데이터셋에서 연속된 문자열 패턴 분석 시 효과적
자주 등장하는 연속된 단어나 구를 추출해 분석하여 관용적 표현 파악 가능
시퀀스에서 연속된 단어를 추출하므로 순서가 중요한 작업에 활용
N-gram의 조건부 확률
\[P(w_t \mid w_{t-1}, w_{t-2}, \dots, w_{t-N+1})\]N-1개의 토큰만 고려해 확률 계산
$w_t$: 예측하려는 단어
$w_{t-1}$부터 $w_{t-N+1}$: 예측에 사용되는 이전 단어들
import nltk
def ngrams(sentence, n): #nltk의 ngrams와 동일
words = sentence.split()
ngrams = zip(*[words[i:] for i in range(n)])
return list(ngrams)
sentence = "안녕하세요 만나서 진심으로 반가워요"
unigram = ngrams(sentence, 1)
bigram = ngrams(sentence, 2)
trigram = ngrams(sentence, 3)
print(unigram)
print(bigram)
print(trigram)
unigram = nltk.ngrams(sentence.split(), 1)
bigram = nltk.ngrams(sentence.split(), 2)
trigram = nltk.ngrams(sentence.split(), 3)
print(list(unigram))
print(list(bigram))
print(list(trigram))
출력
[('안녕하세요',), ('만나서',), ('진심으로',), ('반가워요',)]
[('안녕하세요', '만나서'), ('만나서', '진심으로'), ('진심으로', '반가워요')]
[('안녕하세요', '만나서', '진심으로'), ('만나서', '진심으로', '반가워요')]
[('안녕하세요',), ('만나서',), ('진심으로',), ('반가워요',)]
[('안녕하세요', '만나서'), ('만나서', '진심으로'), ('진심으로', '반가워요')]
[('안녕하세요', '만나서', '진심으로'), ('만나서', '진심으로', '반가워요')]
댓글남기기