단어 임베딩 Word2Vec, Negative sampling, Subsampling

쓰여진 날: by Creative Commons Licence

Issue

Word2vec은 인공신경망을 이용한 기존의 워드 임베딜 기법보다 확실히 발전된 방법이었습니다. 더 빠른 학습시간, 더 많은 단어의 학습 등 임베딩 기법을 실질적으로 퍼트린 방법입니다. 그렇지만, 이런 형태의 word2vec 이 처음 나온 만큼 여전히 개선되어야할 점이 있었습니다. 비효율적인 메모리 관리, 더 빨라질 수 있는 학습 속도와 여전히 큰 weight 레이어가 그런 것들이었고 구글 팀은 다음 논문인 Distributed representations of words and phrases and their compositionality 에서 Negative sampling, sub sampling 과 같은 방법으로 이 문제점들을 개선합니다.

Negatie sampling

말 그대로 Negative 값을 샘플링하는 것입니다. 임베딩이 된 단어는 30010000의 행렬이고 여기에 넣는 어떤 인풋은 100001의 행렬이죠. 이 인풋행렬은 우리가 원하는 하나의 단에에서만 1값을 가지고 나머지 9999는 0인 one-hot 벡터입니다. 이 둘의 곱으로 나온 행렬은 3001의 행렬입니다. 그런데 결국 이건 임베딩행렬에서 인풋에 해당하는 Column을 선택하는 것과 같습니다. 3001 행렬을 얻으려 300,000개의 값 299개의 0과 모두 곱하는 건 매우 비효율적입니다. 실질적으로 이런 부분은 텐서플로나 케라스 같은 프레임워크에서는 행렬을 곱하기보단 바로 해당 row를 끄집어내는 방식으로 효율적이게 구현되어 있습니다. 임베딩 행렬을 lookup 테이블로 쓰는 것이죠.

말 그대로 Negative 값을 샘플링하는 것입니다. 임베딩이 된 단어는 30010000의 행렬이고 여기에 넣는 어떤 인풋은 100001의 행렬이죠. 이것을 한번 학습할 때 10000개의 단어에 대해 softmax를 구하며 웨이트를 업데이트합니다. 하나의 단어에 대해 나머지 9999개의 모든 단어들도 함께 학습하는 것도 비효율적으로 보이지 않나요? “꽃”이란 단어에 대해 “나비”를 예측하는 과정을 학습할 때, 굉장히 상관없어 보이는 “전등”, “손톱 때”와 같은 단어들까지 학습을 하는 거니까요. 어떤 단어는 은근슬쩍 업데이트하지 않아도 큰 차이는 없을 것이라고 예상되죠. 이것이 Negative sampling의 아이디어입니다. “전등”, “손톱 때” 와 같은 단어는 target 값이 0인 negative 값이고 “나비”는 target이 1인 positive 값입니다. 이제 negative sampling이 어떤 건지 대략 감이 옵니다. Target이 negative인 단어들을 샘플링하는 과정입니다. 4개의 negative값을 선택해 이것들에 대해서만 positive 값과 함께 학습합니다. 몇 개의 negative를 샘플링할지는 모델에 따라 다르겠죠. 논문에서 작은 데이터에서는 5~20개, 큰 데이터에서는 2~5개의 negative를 함께 학습하는 실험을 보여주었습니다. 여기서 중요한 건 이 샘플링을 어떻게 할 것인지 입니다. 그냥 정말 무작위로 negtive를 샘플링 하는 건 학자답지 않죠. 논문에서 제시한 방법은 샘플링 될 단어의 빈도수에 따라 가중치를 주는 방식입니다. 많이 나타나는 단어일수록 negative sampling될 확률도 높죠. 바로 이렇게요. 각 단어의 빈도수를 3/4 승 한 다음, 그것을 모두 더한 값으로 나누는 방법입니다. $x^{\frac{3}{4}}$ 의 그래프를 보면 이해가 좀 더 쉽습니다.

이론적으로 증명이 되지는 않았지만, 잘 작동하는 모델이고 많은 연구자들이 사용하고 있다네요.

Subsampling

Negative sampling은 계산량을 획기적으로 줄였다면, Subsampling은 텍스트 자체가 가진 문제를 다룬 방법입니다. 텍스트를 보면 영어에서는 the, a 와 같은 단어들이 자주 등장하는데 이것들로 얻을 수 있는 정보는 다른 단어들보다 많다고 할 수 없죠. 한국어에서는 잘 생각나지 않는데 ㅋㅋㅋ ㅠㅜ 와 같은 것들이 있겠네요. 이렇게 매우 자주 등장하지만 별 쓸모는 없는 단어가 문제인 것입니다. 이런 문제를 다루는 것이 Subsampling 입니다. 학습 데이터의 각 단어는 어떤 확률에 의해 제거 당할 운명에 놓입니다. 여기서도 확률은 단어의 빈도수에 따라 결정이 되겠지요. 하지만 여기서는 많이 등장하는 하는 단어일수록 제거될 확률이 높아집니다. 논문에서 제시한 단어를 보존할 확률은 여기서도 역시 확률은 실험을 통해 가장 잘 작동한다고 나타난 값입니다.

Negative sampling과 Subsampling 에서 단어를 선택할, 보존할 확률이 성능에 큰 영향을 끼칩니다. 케라스와 같은 프레임워크에는 논문에서 실험을 통해 알려진 확률 값들이 쓰이겠지만, 개인적으로는 이건 어디까지나 영어 텍스트에 적용된 실험으로 한국어에는 다른 확률이 쓰여야한다고 생각합니다. 이미 한글 NLP를 하시는 분들은 그렇게 하고 있지 않을까 싶네요.