1.도입

기존의 word2vec은 어휘량이 많아져서 말뭉치가 커지면 계산량이 많아서 시간이 오래걸린다는 단점이 있었다.

그래서 속도를 개선하는 것을 목적으로 한다.

 

어휘량이 많아서 계산량이 많고 시간이 오래걸린다는 문제점을 개선하기 위해서 두 가지를 추가한다.

 

첫번째, embedding layer

 

두번째, negative sampling

 

마지막으로 위 두가지를 추가한 word2vec을 이용하여 ptb dataset을 가지고 평가해본다.

 

2.embedding layer

입력층의 원-핫 표현과 관련한 문제점으로 메모리 낭비가 심하다. 데이터가 100만개면 100만 dimesion을 가진 벡터를 입력으로 한다.

그리고 입력층 가중치에서 행벡터가 임베딩이랑 같기때문에 굳이 원-핫 벡터와 곱해서 계산량을 늘릴 필요가 없다.

 

기존: 거대한 벡터와 가중치 행렬을 곱하는 것 -> 아이디어: 가중치 매개변수로부터 단어 id에 해당하는 행벡터를 추출하는 계층을 만들자.

 

여기서 행벡터를 추출하는 계층 = embedding layer이다.

즉, embedding layer에 word embedding = distributed representation = dense vector을 저장하는 것이다.

 

 

 

결론적으로 matmul layer을 embedding layer로 바꿔서 메모리낭비를 막고 시간문제도 해결할 수 있게 됐다.

 

추가. for문보다는 넘파이의 내장 메소드를 사용하는 것이 더 빠르다.

 

 

3.negative sampling

출력층의 가중치와 곱하는 계산량과 softmax에서의 계산량이 문제가 된다.

간단하게 100만개의 데이터를 입력한다고 생각했을때, 두 부분에서 계산량이 폭발적으로 늘어난다는 것을 알 수 있다. 그리고 이는 곧 시간상의 문제로 이어지게 된다.

 

자, 그래서 negative sampling이란, multi class classification을 binary class classification문제로 바꾸는 것이다.

그러면  출력층은 원래 multi class의 수만큼 있었는데 이제는 1개로 바뀌게 된다. 

또한 출력층 가중치와 hidden layer의 내적도 한번만 이뤄지게 된다.

 

조금 눈여겨볼 것은 softmax with cross entropy가 sigmoid with cross entropy로 변하게 된다. 그리고 loss를 l이라고 하면 각 파라메터를 x,y...로 미분해서 gradient를 구할 때, dl/dx를 바로 못구하니깐 dx/dy를 구해서 dl/dx를 구할 수 있다.

 

l = -(tlog(y) + (1-t)log(1-y)) 이걸 미분하면 된다. 이렇게 하면 sigmoid의 역전파가 정답과 예측의 오차인 y - t 가 된다.

(이때, y는 sigmoid함수다.)

 

이를 전체적으로 그려보면 이렇게 된다.

 

 

 

multi class문제를 binary class문제로 다루려면 정답과 오답에 대해 각각 바르게 분류할 수 있어야 합니다!!

따라서 pos sample, neg sample을 함께 넣어서 loss를 모두 합해서 학습합니다. 이때, neg sample의 label은 0입니다.

그런데, 우리가 모든 단어를 학습하는 게 아니고 제한된 수의 단어를 학습하기 때문에 단어의 빈도수를 보여주는 확률분포표를 사용하여 빈도수가 높은 단어들을 대상으로 sampling을 해야합니다. 빈도수가 적은 단어로 학습을 하게 되면 당연히 학습이 잘되지 않겠죠? 자주 나오는 단어들에 대해서 이상한 워드 임베딩이 완성될 것 입니다.

 

정리하면 말뭉치에서 확률 분포를 만들고 np.random.choice를 사용해서 네가티브 샘플링을 합니다.

 

 

문제점을 해결하기 위해서 2가지 개선 방법 embedding layer, negative sampling을 구현했고 실제로 공개된 데이터셋에서 사용하여 개선된 성능을 확인했다.

 

4.실전에서는 어떻게 쓸까?

항상 데이터셋에 학습을 하지 않아도 transfer learning을 사용하면 된다. 위키백과, 구글의 뉴스와 같은 큰 데이터셋에서 이미 학습을 마친 모델의 embedding layer을 사용하면 좋은 결과를 빠른 시간에 가질 수 있게 도와준다. 

 

그리고 단어들의 벡터를 bag-of-words, rnn을 사용하여 문장을 벡터로 표현할 수도 있다.

 

이를 사용하여 자연어를 벡터로 변화하고 나면 모델에 넣어서 텍스트 분류 , 감정분석, 문서 클러스터링, 등등에 사용할 수 있다.

 

좀 더 자세히 얘기해보면 문의 메일을 긍정/부정으로 나누어서 불만을 가진 사용자의 정보를 사용해서 문제점을 보완할 수 있다.

 

5.평가방법?

두가지로 생각해볼 수 있다. embedding layer을 사용하는 어플리케이션의 정확도를 평가하는 것이나 embedding layer 자체를 평가하는 것이다. 전자는 두 단계의 학습을 수행한 후 평가를 하고, 후자는 "사람이 단어 사이의 유사한 정도를 수동적으로 규정"하고 그것을 "word2vec에 의한 코사인 유사도 점수"로 비교한다.

 

데이터의 양이 많고

말뭉치에 상황에 적절한 모델 사용

적당한 임베딩 벡터 차원 수

skip-gram을 사용

위의 4가지 특징을 보일때 좋은 성능을 보였다.

 

 

총정리.

시간 문제를 개선하기 위해서 idx를 사용하는 embedding layer을 추가했고, multi class -> binary class로 바꿔서 negative sampling을 사용했다. pos sample, neg sample을 함께 사용해서 Loss를 합해줘서 구해줬다. 이를 모두 구현해보았고, 이를 통해 속도가 개선된 word2vec을 얻을 수 있었다. 이를 통해 다양한 곳에 활용할 수 있는데 transfer learning을 통해 이미 완성된 word2vec을 사용할 수 있고 이를 통해 자연어를 벡터로 변환하고 여러 어플리케이션에서 활용할 수 있다. 성능을 높이기 위해서는 데이터가 많아야하고 상황에 맞는 적절한 모델 사용, 적당한 임베딩 벡터 차원 수를 정해주면 된다 끗!

 

+ Recent posts