파이토치에서 임베딩 벡터를 사용하는 방법은 크게 두 가지가 있다.

임베딩층을 만들어 훈련 데이터로부터 처음부터 임베딩 벡터를 학습하는 방법

미리 사전에 훈련된 임베딩 벡터들을 가져와 사용하는 방법

nn.Embedding()은 전자에 해당한다.

임베딩 층의 입력으로 사용하기 위해서 입력 시퀀스의 각 단어들은 모두 정수 인코딩이 되어있어야 한다.

어떤 단어 → 단어에 부여된 고유한 정수값 → 임베딩 층 통과 → 밀집 벡터

임베딩 층은 입력 정수에 대해 밀집벡터로 맵핑하고 이 밀집벡터는 인공신경망이 학습과정에서 가중치가 학습되는 것과 같은 방식으로 훈련된다. 훈련과정에서 단어는 모델이 풀고자하는 작업에 맞는 값으로 업데이트된다. 그리고 이 밀집벡터를 임베딩벡터라고 부른다.

정수를 밀집벡터(임베팅벡터)로 맵핑한다는 것은 특정 단어와 맵핑되는 정수를 인덱스로 가지는 테이블로부터 임베딩 벡터 값을 가져오는 룩업테이블이라고 볼 수 있다. 모든 단어는 고유한 임베딩 벡터를 가진다.

image.png

룩업테이블 과정 구현해보기

임의의 문장으로부터 단어 집합을 만들고 각 단어에 정수를 부여한다.

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>