etc/구글 머신러닝 부트캠프

[DSL] Sequence Models Week2 : Natural Language Processing & Word Embeddings

uyt8989 2022. 7. 21. 23:40

이제 본격적으로 자연어 처리는 어떻게 하는 건지 배운다.

 

1. Word Embedding

자연어 처리를 위해서는 우선 단어를 표현해야 한다. 물론 문자 단위로 해도 되긴 하지만 단어 단위가 뜻을 더 잘 담고 있다. 저번 시간에 사용했던 원핫벡터의 경우 총 10,000개의 단어를 표현하기 위해서는 차원이 10,00개가 필요하다. 그리고 단어가 하나 늘어날 때마다 차원도 하나 증가시켜야 한다. 확장성이 아주 떨어진다. 그리고 단어 사이의 유사도도 전혀 알 방법이 없다. 더해도 안되고 뻬도 안되고 곱해도 안되고 내적, 외적도 안된다. 그래서 워드 임베딩이라는 녀석을 사용한다. 앞으로 원핫벡터는 o, 워드 임베딩 벡터는 e로 표현한다.

 

워드 임베딩은 단순히 0과 1로 단어를 나타내는게 아니라 어떤 특징에 대한 값을 여러 개 저장해서 단어를 나타낼 수 있다. 예를 들어서 king은 남자이면서 왕족이면서 나이도 어느 정도 먹은 단어로 표현한다. 이렇게 단어를 표현하기 때문에 단어 사이의 유사도를 측정할 수 있다.

단어 사이의 유사도는 보통 코사인 유사도를 사용한다.  이 식은 두 벡터 사이의 각도의 코사인 값을 계산한다. 

워드 임베딩은 엄청 많은 양의 단어를 사용해서 학습한다. 컴퓨터 비전에서 배웠던 tranfer learning처럼 우선 워드 임베딩 자체를 학습한 다음에 그 임베딩을 가지고 자연어 처리 응용 개발에 사용한다. 워드 임베딩을 처음 만들 때는 데이터가 엄청 많이 필요하지만 이후에 모델을 개발할 때는 그것보다 훨씬 적은 양의 데이터도 충분하다.

 

Bag of words 크기에 굉장히 예민한 원핫벡터와 다르게 워드 임베딩은 좀 더 유연하다. 강의에서는 워드 임베딩을 300차원 정도로 사용했지만 실제로는 50일 수도 있고 1000일 수도 있다. 애플리케이션의 규모에 따라 다르겠지.

 

마지막으로 embedding matrix에 원핫벡터를 곱하면 워드 임베딩 벡터를 구할 수 있다. 

 

2. Word2Vec

언어 모델을 구성하기 위해선 문맥 파악이 필요하다. 이 문맥을 학습시키는 방법은 다양하다. 앞의 단어 몇 개를 볼 수도 있고, 앞뒤로 몇 개의 단어를 볼 수도 있다. 원래 되게 복잡한 방법을 사용했었는데, 요새는 훨씬 간단한 방법을 사용하는 추세라고 한다. 그리고 언어 모델을 구하는 게 아니라 워드 임베딩을 구하고자 한다면 훨씬 간단한 방법을 사용할 수 있다. 워드 임베딩을 학습시키는 방법으로 Word2Vec이라는 게 있다. 그런데 유독 한글 자막이 난리 난 느낌이라 강의만으로는 개념 이해가 쉽지 않았다. 그래서 다른 강의들과 다르게 다른 레퍼런스를 많이 참고했야 했다.

 

Word2Vec에는 주변 단어를 사용해서 중간 단어를 예측하는 CBOW와 그 반대로 중간 단어를 사용해서 주변 단어를 예측하는 skip-gram이 있다. 강의에서는 주로 설명한 skip-gram은 소프트맥스를 사용한 다중 클래스 분류 문제라고 볼 수 있다. 이 알고리즘은 context와 target을 정하고 특정 context하에서 target일 확률을 구한다. 여기서 사용하는 theta t는 target이랑 관련 있는 매개변수다.

대신 이 방법은 p(t|c) 값을 구하기 위해서 분모에 있는 합을 매번 구해야 한다. 단어의 개수만큼 합을 구해야 하니 단어가 적을 때는 크게 지장 없지만 어휘의 수가 늘어나면 늘어날수록 점점 계산이 부담스러워진다. 이 문제를 해결하기 위해서 계층적 소프트맥스라는 방법을 사용할 수 있다. 시그마의 항이 너무 많은 게 문제이므로 항의 개수를 줄인다. 어휘를 한 번에 분류하는 게 아니라 카테고리를 분류해서 여러 번 소프트맥스를 적용한다. 트리라고 생각하면 될 것 같다. 대신 균형이나 대칭이 이루어지지는 않는다. 그래서 좀 자주 나오는 단어는 루트랑 가깝게 배치한다.

 

이를 negative sampling으로 최적화하는 방법도 있다. 이전의 방법은 주어진 context 상에서 주변 단어를 예측했다면 이제는 context와 target이 주어지고 둘이 주변 관계가 있는지 확인한다. 이렇게 하면 다중 클래스 분류에서 이진 클래스로 바꿀 수 있다. 우선 문장에서 주변 단어를 하나 고르고 라벨을 1로 붙인다. 그리고 context랑 상관없이 사전에서 아무 단어나 k개 골라서 라벨을 0으로 붙인다. 이 k는 데이터가 작은 경우에 큰 값으로, 데이터가 큰 경우엔 작은 값으로 사용한다.

이를 로지스틱 회귀로 풀어낸다고 보면 된다. 여기서는 단어를 3개밖에 사용하지 않았지만 만약 단어 10,000개라면 마지막 레이어에서 출력이 10,000개다.

3. GloVe

또 다른 워드 임베딩 학습 방법으로 GloVe라는 게 있다. 식만 써놓고 보면 이전보다 훨씬 간단하다. 하지만 이 식을 도출하는 과정 자체는 그리 간단하지 않은 것 같지만 강의에서는 그냥 뚝딱 이 식을 완성해버린다. 왜 theta와 e가 대칭적인지에 대한 설명도 많이 부족하다고 느꼈다. 아무튼 이렇게 학습하면 잘 작동한다고 한다.

 

4. Sentiment Classification

위에서 학습한 워드 임베딩을 사용하면 자연어 문장이 주어졌을 때 문장의 감성을 분석할 수 있다. 예를 들어서 "영화가 정말 재미있어요"라는 영화 리뷰를 보고 나서 이 리뷰가 긍정적인지 부정적인지 등을 알아낸다. 워드 임베딩을 사용하는 방법으로는 크게 두 가지가 있다. 하나는 그냥 병렬적으로 단순 합이나 평균 등을 구하는 거고 나머지 하나는 RNN을 사용하는 방법이다. 전자는 간단하기는 하지만 문장의 순서를 전혀 고려하지 않는다. 따라서 RNN을 사용하는 방법이 훨씬 성능이 좋을 수밖에 없다.

워드 임베딩을 사용하는 경우의 장점은 이전에도 말했듯이 학습에 사용되는 라벨 된 데이터가 좀 적더라도 성능이 꽤나 잘 나올 수 있다는 점이다. 

 

5. Word Embedding Bias

여기서의 편향은 이전의 편향과는 조금은 다르다. "남자"와 "개발자" 두 단어 사이의 거리와 방향을 측정하고 "여자"에서 비슷한 단어를 찾을 때 편향 없이 학습했다면 "여자"에서도 "개발자"가 나와야 할 것이다. 하지만 "주부"라고 나온다면 워드 임베딩에 편향이 존재하는 것이다. 요새는 머신 러닝이 쓰이는 곳이 많다 보니 이런 편향을 줄이는 것이 상당히 중요한 문제가 됐다. 만약 편향이 존재하는 워드 임베딩을 사용해서 자연어 처리 응용을 만들게 되면 그 응용에도 문제가 생긴다. 쓰레기가 들어가면 쓰레기가 나온다는 말이 괜히 있는 게 아니다. 그만큼 데이터가 중요하다. 그래도 이미 학습된 워드 임베딩을 어떻게든 써먹어보고 싶다면 이 편향을 감소시켜야 한다. 

 

우선 편향이 존재하는 방향을 알아내야 한다. 강의에서 사용한 워드 임베딩은 300차원쯤 된다. 이 중에서 편향이 존재하는 방향을 찾기 위해서 알아내고자 워드 임베딩 두 개를 빼야 한다. "남자" - "여자"를 하게 된다면 성별 차이로 발생하는 편향이 어떤 방향인지 알아낼 수 있다. 그리고 편향이 없는 방향으로 성별 요소가 들어가 있지 않은 단어를 사영(?) 시킨다. "개발자" 같은 단어들의 편향을 줄여준다고 생각하면 된다. 그리고 성별 요소가 들어가 있는 단어들을 성별 요소가 없는 단어 들와 거리를 맞춰준다.

 

워드 임베딩을 학습시켜서 편향이 있는지 없는지를 검사해서 실제로 사회에서도 편향이 있는지 없는지를 분석할 수도 있을 것 같다.

 

* Courera의 Deep Learning Sepcialization 강의를 수강하는데 도움이 되고자 작성한 요약문입니다. 틀린 내용 있다면 정정해주시면 감사하겠습니다.