흔한 오해 1
Last updated
Last updated
단어를 벡터로 매끄럽게 표현하는 방법을 살펴보고 있습니다. 이어서 skip-gram 또는 GloVe를 사용하여 원핫 인코딩의 희소 벡터를 차원 축소해 저차원의 덴스 벡터로 표현하는 방법을 다룰 것입니다.
이에 앞서 많은 분이 헷갈리는 부분이 있다면, 이렇게 훈련한 단어 임베딩 벡터를 추후 우리가 다룰 텍스트 분류, 언어 모델, 번역 등의 딥러닝 모델 입력으로 사용하리라 생각한다는 점입니다. 이 임베딩 벡터를 사전 훈련pre-training된 임베딩 벡터라고 부릅니다. word2vec을 통해 얻은 단어 임베딩 벡터가 훌륭하게 단어의 특징을 잘 반영하고 있긴 하지만, 텍스트 분류나 언어 모델, 번역의 문제를 해결하는 최적의 벡터 임베딩이라고는 볼 수 없습니다. 다시 말하면, 텍스트 분류 또는 기계번역을 위한 목적 함수는 분명히 word2vec과 다른 형태로 존재합니다. 따라서 다른 목적 함수를 통해 훈련한 임베딩 벡터는 원래의 목적에 맞지 않을 가능성이 높습니다.
예를 들어 긍정/부정 감성 분류를 위한 텍스트 분류 문제의 경우에는 '행복'이라는 단어가 매우 중요한 특징이 될 것이고, 이를 표현하기 위한 임베딩 벡터가 존재할 것입니다. 하지만 기계번역 문제에서 '행복'이라는 단어는 그저 일반적인 단어에 지나지 않습니다. 이 분류 문제를 위한 '행복'이라는 단어의 임베딩 벡터 값은 긍정/부정 분류 문제의 값과 당연히 달라질 것입니다. 따라서 문제의 특징을 고려하지 않은 단어 임베딩 벡터는 그다지 좋은 방법이 될 수 없습니다.
word2vec을 사용하여 단어를 저차원의 임베딩 벡터로 변환하지 않아도, 문제의 특징에 맞는 단어 임베딩 벡터를 구할 수 있습니다. 파이토치를 비롯한 여러 딥러닝 프레임워크는 임베딩 계층embedding layer이라는 레이어 아키텍처를 제공합니다. 이 계층은 다음과 같이 편차bias가 없는 선형 계층과 같은 형태를 지닙니다.
쉽게 생각하면 $W$ 는 $d\times|V|$ 크기의 2차원 행렬입니다. 따라서 입력으로 원핫 벡터가 주어지면, $W$ 의 특정 행(구현 방법에 따라서는 특정 열)만 반환합니다.
따라서 최종적으로 모델으로부터 구한 손실값에 따라 역전파 및 경사하강법을 수행하면, 자동적으로 임베딩 계층의 가중치weight인 $W$ 의 값을 구할 수 있을 것입니다.
실제 구현에서는 이렇게 큰 임베딩 계층 가중치와 원핫 인코딩 벡터를 곱하는것은 매우 비효율적이므로, 단순히 테이블에서 검색lookup하는 작업을 수행합니다. 따라서 단어를 나타낼 때 (임베딩 계층의 입력으로) 원핫 벡터를 굳이 넘겨줄 필요 없이, 1이 존재하는 단어의 인덱스 정숫값만 입력으로 넘겨주면 임베딩 벡터를 얻을 수 있습니다. 또한 임베딩 계층과의 계산상의 효율성과는 별개로, 원핫 인코딩 벡터를 표현할 때 1이 존재하는 단어의 인덱스 정숫값만 있으면 된다는 것은 자명합니다. 애초에 원핫 인코딩은 n개의 카테고리를 나타내기 위한 방법이기 때문입니다. n차원의 원핫 인코딩 벡터에서 1은 한 개이며, $n-1$ 개의 0으로 채워집니다.
추후 다룰 텍스트 분류나 기계번역 장에서 구현한 내용을 살펴보면, word2vec을 사용하여 단어를 임베딩 벡터로 변환한 후 신경망에 직접 넣는 대신, 앞에서 언급한 것처럼 임베딩 계층을 사용하여 원핫 인코딩 벡터를 입력으로 넣도록 구현했음을 알 수 있습니다.
그래도 사전 훈련된 단어 임베딩 벡터 적용을 고려해볼 만한 몇몇 상황이 있습니다. 예를 들어 준비된 코퍼스의 양이 너무 적고, 이때 외부로부터 많은 양의 말뭉치를 통해 미리 훈련한 단어 임베딩 벡터를 구한다는 특수한 경우를 가정해볼 수 있습니다.
한편으로는 기본 정석대로 먼저 베이스라인baseline 모델을 만든 후, 성능을 끌어올리기 위한 여러 가지 방법들을 시도할 때 사전 훈련된 단어 임베딩 벡터의 사용을 고려해볼 수도 있습니다.
또는 이 책의 마지막 장에서 다룰 전이학습transfer learning에서 살펴볼 고도화된 언어 모델을 통해 사전 훈련하여 접근해볼 수도 있습니다.