파이토치에서 임베딩 벡터를 사용하는 방법은 크게 두 가지가 있다.
임베딩층을 만들어 훈련 데이터로부터 처음부터 임베딩 벡터를 학습하는 방법
미리 사전에 훈련된 임베딩 벡터들을 가져와 사용하는 방법
nn.Embedding()은 전자에 해당한다.
임베딩 층의 입력으로 사용하기 위해서 입력 시퀀스의 각 단어들은 모두 정수 인코딩이 되어있어야 한다.
어떤 단어 → 단어에 부여된 고유한 정수값 → 임베딩 층 통과 → 밀집 벡터
임베딩 층은 입력 정수에 대해 밀집벡터로 맵핑하고 이 밀집벡터는 인공신경망이 학습과정에서 가중치가 학습되는 것과 같은 방식으로 훈련된다. 훈련과정에서 단어는 모델이 풀고자하는 작업에 맞는 값으로 업데이트된다. 그리고 이 밀집벡터를 임베딩벡터라고 부른다.
정수를 밀집벡터(임베팅벡터)로 맵핑한다는 것은 특정 단어와 맵핑되는 정수를 인덱스로 가지는 테이블로부터 임베딩 벡터 값을 가져오는 룩업테이블이라고 볼 수 있다. 모든 단어는 고유한 임베딩 벡터를 가진다.
룩업테이블 과정 구현해보기
임의의 문장으로부터 단어 집합을 만들고 각 단어에 정수를 부여한다.
train_data = 'you need to know how to code'
# 중복을 제거한 단어들의 집합인 단어 집합 생성.
word_set = set(train_data.split())
# 단어 집합의 각 단어에 고유한 정수 맵핑.
vocab = {word: i+2 for i, word in enumerate(word_set)}
vocab['<unk>'] = 0
vocab['<pad>'] = 1
print(vocab)
{'code': 2, 'you': 3, 'know': 4, 'to': 5, 'need': 6, 'how': 7, '<unk>': 0, '<pad>': 1}
단어집합의 크기를 행으로 가지는 임베딩 테이블을 3차원으로 구현한다.
# 단어 집합의 크기만큼의 행을 가지는 테이블 생성.
embedding_table = torch.FloatTensor([
[ 0.0, 0.0, 0.0], #<unk>
[ 0.0, 0.0, 0.0], #<pad>
[ 0.2, 0.9, 0.3], #you
[ 0.1, 0.5, 0.7], #need
[ 0.2, 0.1, 0.8], #to
[ 0.4, 0.1, 0.1], #know
[ 0.1, 0.8, 0.9], #how
[ 0.6, 0.1, 0.1]]) #code
임의의 문장에 대해서 룩업 테이블을 통해 임베딩 벡터를 가지고 온다.
sample = 'you need to run'.split()
idxes = []
# 각 단어를 정수로 변환
for word in sample:
try:
idxes.append(vocab[word])
# 단어 집합에 없는 단어일 경우 <unk>로 대체된다.
except KeyError:
idxes.append(vocab['<unk>'])
idxes = torch.LongTensor(idxes)
# 각 정수를 인덱스로 임베딩 테이블에서 값을 가져온다.
lookup_result = embedding_table[idxes, :]
print(lookup_result)
tensor([[0.1000, 0.5000, 0.7000], #you [0.1000, 0.8000, 0.9000], #need [0.4000, 0.1000, 0.1000], #to [0.0000, 0.0000, 0.0000]]) #run,<unk>