4.1 임베딩이란?
임베딩 embedding
- 컴퓨터는 수치 연산만 가능하기 때문에 자연어를 숫자나 벡터 형태로 변환하는 일련의 과정.
- 단어나 문장을 수치화해 벡터 공간으로 표현하는 과정
- 말뭉치의 의미에 따라 벡터화하기 때문에 문법적인 정보가 포함
임베딩의 기법
- 문장 임베딩
문장 전체를 벡터로 표현하는 방법
1. 장점: 전체 문장의 흐름을 파악해 벡터로 변환하기 때문에 문맥적 의미를 지님
- 단어 임베딩에 비해 품질이 좋고, 상용 시스템에 많이 사용됨
2. 단점: 임베딩하기 위해 많은 문장 데이터가 필요하며 학습하는 데 비용이 많이 들어감
- 단어 임베딩
개별 단어를 벡터로 표현하는 방법
1. 장점: 학습 방법이 간단하여 실무에서 많이 사용됨
2. 단점: 동음이의어에 대한 구분을 하지 않기 때문에 의미가 다르더라도 단어의 형태가 같다면 동일한 벡터값으로 표현
4.2 단어 임베딩
- 말뭉치에서 각각의 단어를 벡터로 변환하는 기법
- 의미와 문법적 정보를 지니고 있으며, 단어를 표현하는 방법에 따라 다양한 모델 존재
" 토크나이징을 통해 추출된 토큰들을 어떻게 단어 임베딩할지.."
4.2.1 원-핫 인코딩 one-hot encoding
- 단어를 숫자 벡터로 변환하는 가장 기본적인 방법
- 요소들 중 단 하나의 값만 1이고 나머지 요솟값은 0인 인코딩을 의미
- 원-핫 인코딩으로 나온 결과를 원-핫 벡터라고 하며, 전체 요소 중 단 하나의 값만 1이기 때문에 희소sparse 벡터라고 함
- 원-핫 인코딩
from konlpy.tag import Komoran
import numpy as np
komoran = Komeran()
text = "오늘 날씨는 구름이 많아요."
# 명사만 추출
nouns = komoran.nouns(text)
print(nouns)
# 단어 사전 구축 및 단어별 인덱스 부여
dics = {}
for word in nouns:
if word not in dics.keys():
dics[word] = len(dics)
print(dics)
# 원-핫 인코딩
nb_classes = len(dics)
targets = list(dics.values())
one_hot_targets = np.eyes(nb.classes)[targets]
print(one_hot_targets)
- 원-핫 인코딩 예제 결과
['오늘', '날씨', '구름']
{'오늘':0, '날씨':1, '구름':2}
[[1.0.0.]
[0.1.0.]
[0.0.1.]]
- 원-핫 인코딩 특징
1. 간단한 구현 방법에 비해 좋은 성능을 가지고 있어 많은 사람이 사용중
2. 단순히 단어의 순서에 의한 인덱스값을 기반으로 인코딩된 값이기 때문에 단어의 의미나 유사한 단어와의 관계를 담고 있지 않음
3. 단어 사전의 크기가 커짐에 따라 원-핫 벡터의 차원도 커지게 되는데, 이때 메모리 낭비나 계산의 복잡도가 커짐
: 대부분 요소가 0의 값을 가지고 있으므로 비효율적
4.2.2 희소 표현과 분산 표현
- 희소 표현의 경우 각각의 차원이 독립적인 정보를 지니고 있어 사람이 이해하기에 직관적인 장점 ↔ 단어 사전의 크기가 커질수록 메모리 낭비와 계산 복잡도가 커지는 단점 + 단어 간의 연관성이 전혀 없어 의미를 담을 수 없음
- 자연어 처리를 잘하기 위해서는? 기본 토큰이 되는 단어의 의미와 주변 단어 간의 관계가 단어 임베딩에 표현되어야 함
→ 이를 해결하기 위해 각 단어 간의 유사성을 잘 표현하면서도 벡터 공간을 절약할 수 있는 방법을 고안 : 분산 표현 distributed representation
- 분산표현
하나의 차원에 다양한 정보를 가지고 있음.
데이터 손실을 최소화하면서 벡터 차원이 압축되는 효과
우리가 원하는 차원에 데이터를 최대한 밀집시킬 수 있어 밀집 표현 dense representation 이라 부르기도 함.
(밀집 표현으로 만들어진 벡터를 밀집 벡터 dense vector 라고 함)
- 분산 표현의 장점
1. 임베딩 벡터의 차원을 데이터 손실을 최소화하면서 압축할 수 있음. : 입력 데이터의 차원이 너무 높아지면 신경망 모델의 학습이 어려워지는 차원의 저주 curse of dimensionality 문제가 발생함
2. 임베딩 벡터에는 단어의 의미, 주변 단어 간의 관계 등 많은 정보가 내포되어 있어 일반화 능력이 뛰어남.
4.2.3 Word2Vec
" 원-핫 인코딩의 경우 구현은 간단하지만, 챗봇의 경우 많은 단어를 처리하면서 단어 간 유사도를 계산할 수 있어야 좋은 성능이 나오는데.. 원-핫 인코딩은 이걸 못 한다는 단점이 있다."
" 따라서 분산 표현 형태 단어 임베딩 모델을 사용할 건데.. 신경망 기반 단어 임베딩의 대표적인 방법인 Word2Vec 모델을 알아보자"
Word2Vec
- 2013년 구글에서 발표했으며 가장 많이 사용하고 있는 단어 임베딩 모델
- 기존 신경망 기반의 단어 임베딩 모델에 비해 구조상 차이는 크게 없지만 계산량을 획기적으로 줄여 빠른 학습을 가능하게 했다!
- CBOW continuous bag-of-words 와 skip-gram 두 가지 모델로 제안
CBOW 모델
- 맥락이라 표현되는 주변 단어들을 이용해 타깃 단어를 예측하는 신경망 모델
- 신경망의 입력을 주변 단어들로 구성하고 출력을 타깃 단어로 설정해 학습된 가중치 데이터를 임베딩 벡터로 활용
- 타깃 단어의 손실만 계산하면 되기 때문에 학습 속도가 빠른 장점
skip-gram 모델
- CBOW 모델과 반대로 하나의 타깃 단어를 이용해 주변 단어들을 예측하는 신경망 모델
- 입출력이 CBOW 모델과 반대여서 예측해야하는 맥락이 더 많아짐 : 단어 분산 표현력이 우수해 CBOW 모델에 비해 임베딩 품질이 우수
- Word2Vec 모델 학습 예제
from gensim.models import Word2Vec
from konlpy.tag import Komoran
import time
# 네이버 영화 리뷰 데이터 읽어옴
def read_review_data(filename):
with open(filename, 'r') as f:
data = [line.split('\t') for line in f.read().splitlines()]
data = data[1:] # 헤더 제거
return data
# 학습 시간 측정 시작
start = time.time()
# 리뷰 파일 읽어오기
print('1) 말뭉치 데이터 읽기 시작')
review_data = read_review_data('./ratings.txt')
print(len(review_data)) # 리뷰 데이터 전체 개수
print('1) 말뭉치 데이터 읽기 완료 : ', time.time() - start)
# 문장 단위로 명사만 추출해 학습 입력 데이터로 만듦
print('2) 형태소에서 명사만 추출 시작')
komoran = Komoran()
docs = [komoran.nouns(sentence[1]) for sentense in review_data]
print('2) 형태소에서 명사만 추출 완료 : ', time.time() - start)
# Word2Vec 모델 학습
print('3) Word2Vec 모델 학습 시작')
komoran = Komoran()
docs = [komoran.nouns(sentence[1]) for sentense in review_data]
print('3) Word2Vec 모델 학습 완료 : ', time.time() - start)
# 모델 저장
print('4) 학습된 모델 저장 시작')
model.save('nvml.model')
print('4) 학습된 모델 저장 완료 : ', time.time() - start)
# 학습된 말뭉치 수, 코퍼스 내 전체 단어 수
print("corpus_count : ", model.corpus_count)
print("courpus_total_words : ", model.corpus_total_words)