Deep Learning for NLP with PyTorch

#Deep-Learning-for-NLP-with-PyTorch

저자: Robert Guthrie
역자: Don Kim

Word Embeddings: Encoding Lexical Semantics

#Word-Embeddings:-Encoding-Lexical-Semantics

원본: http://pytorch.org/tutorials/beginner/nlp/word_embeddings_tutorial.html

Word embedding은 실수(real numbers)로 꽉 들어찬(dense) vector로, 단어장의 단어 하나마다 한 원소를 갖고 있다. NLP 문제를 다루는 대부분의 경우 우리의 feature는 단어일 것이다! 하지만 컴퓨터로 하여금 어떻게 단어를 표시하게 할 것인가? 단어의 ASCII 표현을 사용할 수도 있겠으나, 그것은 단어가 무엇인지 알려줄 뿐, 어떤 의미를 갖고 있는지는 말해주지 않는다 (아마도 끝글자들을 보고 품사를 안다거나, 대소문자 구분을 통해 뭔가 단어의 성격을 알 수도 있겠으나, 그 조차도 확실하지 않다). 더욱이, 단어들의 표현을 어떤 방식으로 조합할 수 있는 지는 더 어려운 문제이다. @@0@@가 단어장이고 input이 @@1@@차원이라면, 우리는 종종 neural network을 통해서 꽉 찬 output을 받고 싶은데 output의 차원이 몇 되지 않는 경우가 있다 (예를 들어 예측하고자 하는 것이 두 세가지 라벨이라면). 어떻게 하면 엄청나게 큰 차원에서 더 작은 차원으로 dense output을 얻을 수 있을까?

ASCII 표현 대신 one-hot encoding을 사용하면 어떨까? One-hot encoding은 단어 @@2@@를 이렇게 표시하는 거다.

@@3@@

여기서 1은 단어 @@4@@의 위치에 있다. 단어장에 있는 다른 단어들도 어딘가 1인 자리가 있고 나머지는 0인 vector가 된다.

이 표현 방법은 그 크기가 거대하다는 점 외에 또 엄청난 단점이 있는데, 그것은 이 표현이 모든 단어들을 서로 간의 관계를 전혀 고려하지 않고 하나 하나 단어만 독립적으로 표현한다는 점이다. 우리가 여기서 정말로 원하는 것은 단어 간의 유사성(similarity)이다. 왜? 예제를 통해 설명하겠다.

우리는 language model을 구축한다고 가정하고, 아래와 같은 문장을 training 데이터로 받았다.

  • The mathematician ran to the store.
  • The physicist ran to the store.
  • The mathematician solved the open problem.

이제 training 데이터에서 못 봤던 새로운 문장 하나가 들어왔다.

  • The physicist solved the open problem.

우리의 language model이 이 문장에 대해서 괜찮은 결과를 낼 수도 있지만, 다음 두 가지 사실을 이용한다면 훨씬 그 결과가 좋아질 수 있지 않을까.

  • 한 문장에서 mathematician과 physicist는 같은 역할을 하고 있다. 아마도 이 둘은 뭔가 의미적으로 관련이 있을 것 같다.
  • 새로운 문장은 기존 training 데이터에 있는 문장에서 mathematician가 있는 자리에 physicist가 들어온 것이다.

그러면 새로운 문장에서 physicist가 정말로 적합한 단어라고 생각할 수 있을 것 같다. 이것이 여기서 이야기 하고자 하는 유사성이다. 의미적인 유사성(semantic similarity)이지, 비슷한 철자 표현이 아니다. 이것은 우리가 관측한 것과 모르는 것 사이를 연결해서 언어 데이터의 sparsity를 극복하기 위한 기술이다. 물론 위 예제는 "비슷한 문맥에서 등장하는 단어들은 서로 의미적으로 연관되어 있다"는 언어학적인 기본 전제를 필요로 한다. 이를 distributional hypothesis라고 말한다.

Getting Dense Word Embeddings

#Getting-Dense-Word-Embeddings

우리는 이 문제를 어떻게 해결할 수 있을까? 즉, 단어 간의 의미적 유사성을 어떻게 측정하고 코드화할 수 있을까? 우리는 의미에 맞는 성질(semantic attribute)들을 만들어 볼 수도 있겠다. 이미 training 데이터에서 mathematician과 physicist 둘 다 달릴 수 있으므로, "is able to run"이라는 성질에 높은 점수를 주는 것이다.

만약 attribute 하나를 차원 하나에 할당한다면, 우리는 단어 하나에 attribute vector 하나를 아래처럼 연결할 수 있겠다.

@@0@@

이러고 나면 유사성의 정도를 이렇게 계산할 수 있겠다.

@@1@@

하지만 여기서 크기를 1로 normalize하는 것이 흔한 관례이다.

@@2@@

여기서 @@3@@는 두 벡터 사이의 각도이다. 이 방법대로라면, 엄청나게 비슷한 단어들은 similarity 1을 가질테고, 엄청나게 다른 단어들은 similarity -1를 가지게 될 것이다.

처음에 소개했던 sparse한 one-hot 벡터를 방금 소개한 attribute vector의 특별한 경우로 생각할 수 있다. 이 경우 각 단어는 다른 단어들에 대해 모두 similarity 0를 갖게 될 것이고, 그 각 단어에 대해 유일한 semantic attribute를 부여한 셈이다. 아무튼 새로운 semantic attribute vector는 dense하다 (0인 원소들이 거의 없다).

하지만 반대로 이렇게 새로 만들어지는 vector는 엄청난 고통 그 자체다. Similarity를 측정하기 위해 우리가 굉장히 노력해서 수 천개의 semantic attribute을 생각해냈다 한들, 그 attribute 값을 얼마나로 정할 수 있을까? 프로그래머가 직접 그것들을 설계하는 대신 neural network가 스스로 feature의 표현을 배운다는 것은 딥러닝 아이디어의 핵심이다. 그러니 word embedding이 그저 우리 model의 parameter가 돼서 학습 과정에서 업데이트되면 안 될까? 이것이 우리가 앞으로 할 일이다. 우리는 network가 원리대로라면 학습할 수 있는 latent semantic attribute 들을 얻게 될 것이다.

참고로 word embedding은 그 해석이 거의 불가능한 모델이다. 즉, 우리가 직접 정성껏 만든 vector들을 통해서 mathematician과 physicist가 둘 다 커피를 좋아하기 때문에 비슷하다고 해석할 수 있는 반면, neural network가 알아서 학습한 embedding을 봤을 때, 두 번째 차원에서 굉장히 큰 값을 둘 다 가지고 있음을 안다 해도 그 attribute가 어떤 의미를 지니는 지 알 길이 없는 것이다. 어떤 latent semantic dimension 상에서 비슷한 점이 있겠지만, 우리가 알 수 있는 것은 아닐 것이다.

정리하자면, word embedding은 단어의 "의미"를 표현하는 것이고, 주어진 문제와 관련된 의미적 정보를 효율적으로 계산해서 이루어 진다. 우리는 다른 것도 embed할 수 있다: 품사 정리, tree 쪼개기, 뭐든지! Feature embedding은 NLP에서 핵심적인 개념이다.

Word Embeddings in Pytorch

#Word-Embeddings-in-Pytorch

예제와 숙제로 들어아기 전에, Pytorch에서, 그리고 일반적은 딥러닝 프로그래밍 상황에서 embedding을 사용하는 것에 대해 몇 가지 참고 사항을 잠깐 얘기하고자 한다. One-hot vector를 만들기 위해서 고유 index를 만들어줘야 하는 것처럼, embedding을 사용할 때도 단어 하나마다 고유한 index가 필요하다. 이 index가 lookup table의 키가 될 것이다. 즉, embedding은 @@0@@ matrix에 저장이 될 것인데, 여기서 @@1@@는 embedding의 차원이고, index @@2@@에 해당하는 단어는 이 매트릭스의 @@3@@ 번째 행을 embedding으로 갈게 된다. 여기 제공되는 모든 코드에서 단어에서 index로 가는 mapping은 word_to_ix라는 Python dictionary다.

torch.nn.Embedding에서 제공하는 embedding은 두 가지 argument를 필요로 하는데, 단어장의 크기와 embedding의 차원 크기이다.

또한 lookup table에 대한 index로 사용하기 위해서는 반드시 torch.LongTensor를 사용해야 한다. Float 값은 index로 쓰일 수가 없다.

Loading output library...

An Example: N-Gram Language Modeling

#An-Example:-N-Gram-Language-Modeling

N-gram 모델에서 우리는 단어들의 나열 모음인 @@0@@가 주어졌을 때 다음을 계산해내길 원한다.

@@1@@

아래 예제에서 우리는 training 데이터를 바탕으로 loss 함수를 계산하고 backpropagation을 통해 parameter를 업데이트할 것이다.

Exercise: Computing Word Embeddings: Continuous Bag-of-Words

#Exercise:-Computing-Word-Embeddings:-Continuous-Bag-of-Words

Continuous bag-of-words (CBOW) 모델은 NLP deep learning에서 자주 사용되는 방법으로, target 단어 앞 뒤로 몇 단어들의 문맥이 주어졌을 때에 알맞을 단어를 예측한다. CBOW는 순차적이지 않고 굳이 확률적일 필요가 없기 때문에 language modeling과 구별된다. CBOW를 통해 word embedding을 빠르게 학습하고, 더욱 복잡한 모델의 embedding을 위한 초기값으로 학습된 embedding을 사용하는 것이 전형적인 사용 예이다. 따라서 이 방법은 pretrained embeddings 라고 불리며, 1~2 퍼센트 정도의 성능 향상을 대부분의 경우 보장한다.

CBOW 모델을 설명하겠다. Target 단어 @@0@@와 양 쪽 문맥 범위가 @@1@@이어서 @@2@@라고 하겠다), CBOW는 다음을 최소화하고자 한다.

@@3@@

여기서 @@4@@는 단어 @@5@@에 대한 embedding이다.

아래 Pytorch class를 채워서 CBOW 모델을 구성해보라. 팁을 주자면:

  • 당신이 필요한 parameter가 무엇무엇인지 생각해보자.
  • 각 연산이 필요로 하는 data의 모양이 무엇인지 확실하게 정리해라. 모양을 바꿔야 할 필요가 있다면 .view()를 사용하면 된다.
Loading output library...