본문 바로가기

공부기록/Data Science

단어 표현 - 어떻게 자연어를 컴퓨터에게 인식시킬 수 있을까 ?

반응형

출처 : 텐서플로와 머신러닝으로 시작하는 자연어 처리, https://wikidocs.net/31767

단어표현이란

단어 표현은 모든 자연어 처리 문제의 기본 바탕이 되는 개념이다. 기존에 컴퓨터는 텍스트를 유니코드 혹은 아스키 코드 방식으로 인식했다. 이 방법을 사용하면 텍스트를 이진화 된 값으로 인식한다. 이 경우 언어적인 특성이 전혀 없이 컴퓨터가 문자를 인식하기 위해 만들어진 값이므로 자연어 처리를 위해 만드는 모델에 적용하기에 부적합하다.

어떤 방식으로 텍스트를 표현해야 자연어 처리 모델에 적용할 수 있을까?

단어의 표현 방법은 크게 두 가지가 있다.

 

1. 국소 표현 (Local Representation)방법

  • 이산 표현 (Discrete Representation)
  • 각 단어에 숫자를 맵핑하여 단어를 표현하는 방법

2.분산 표현(Distributed Representation)방법

  • 연속 표현 (Continuous Representation)
  • 주변 단어로 하나의 단어를 정의.
    ex.'깜찍한', '독립적인', '고양이' 라는 단어가 있을때 '고양이'라는 단어를 '깜찍한', '독립적인' 이라는 단어로 정의하는 것을 말한다. 

Local Representation

여기서는 국소표현방법으로 one-hot-encoding만 다루도록 하겠다.

원-핫 인코딩

단어를 표현하는 가장 기본적인 방법은 원-핫 인코딩(one-hot encoding) 방식이다. 각 단어의 인덱스를 정한 후 각 단어의 벡터를 그 단어에 해당하는 인덱스의 값을 1로 표현하는 방식이다.

 

예시
(포도,딸기,수박,레몬,망고) 라는 단어를 알려야 한다고 했을 때 원-핫 인코딩 방식으로 표현하면 각 단어를 표현하는 벡터의 크기는 5가 된다.각 단어는 이 중에서 하나만 1이 된다.
포도는 [1,0,0,0,0], 딸기는 [0,1,0,0,0],수박은 [0,0,1,0,0], 레몬은 [0,0,0,1,0], 망고는 [0,0,0,0,1]으로 표현한다.

 

코드
토큰화된 단어들에 대해서 고유의 인덱스를 부여한다.

token = ['포도', '딸기', '수박', '레몬', '망고']
word2index={}
for voca in token:
     if voca not in word2index.keys():
       word2index[voca]=len(word2index)
print(word2index)

결과
{'포도': 0, '딸기': 1, '수박': 2, '레몬': 3, '망고': 4}

 

토큰을 입력하면 해당 토큰에 대한 원-핫 벡터를 만들어내는 함수를 만든다.

def one_hot_encoding(word, word2index):
       one_hot_vector = [0]*(len(word2index))
       index=word2index[word]
       one_hot_vector[index]=1
       return one_hot_vector
one_hot_encoding("포도",word2index)

결과
[1, 0, 0, 0, 0]

이 밖에도 케라스의 to_categorical()을 이용해 원-핫 인코딩을 할 수 있다. (참고 https://wikidocs.net/22647)

 

장점

  • 방법 자체가 매우 간단하고 이해하기 쉽다.

단점

  • 단어의 벡터의 크기가 매우 크고, 값이 희소(sparse)하다는 문제.
    실제 자연어 처리 문제를 해결할 땐 위의 예시처럼 5개의 단어가 아니라 수십만, 수백만 개의 단어를 표현해야 한다.또한 큰 공간에 비해 실제 사용하는 값은 1이 되는 값 하나 뿐이므로 매우 비효율적이다.
  • 단어 벡터가 단어의 의미나 특성을 전혀 표현할 수 없다는 문제.
    단순히 단어가 무엇인지만을 표현하고, 벡터값 자체에는 단어의 의미나 특성 같은 것들이 전혀 표현되지 않는다.
  • 각 단어간 유사성을 표현할 수 없다.

이 문제를 해결하기 위해 벡터의 크기가 작으면서도 벡터의 단어의 의미를 표현할 수 있는 방법들이 제안되었다. 이러한 방법들은 분포가설(Distributed hypothesis)을 기반으로 한다.

 

Continuous Representation

분포가설이란 "같은 문맥의 단어, 즉 비슷한 위치에 나오는 단어는 비슷한 의미를 가진다."라는 개념이다.
분포가설을 기반으로 하는 벡터의 크기가 작으면서도 단어의 의미를 표현할 수 있는 방법은 크게 두 가지 방법으로 나뉜다.

  • 카운트 기반 (count-base) 방법 : 특정 문맥 안에서 단어들이 동시에 등장하는 횟수를 직접 세는 방법
  • 예측(predictive) 방법 : 신경망 등을 통해 문맥 안의 단어들을 예측하는 방법

카운트 기반 방법

카원트 기반 방법은 기본적으로 동시 출현 행렬(Co-occurence Matrix)을 만들고 그 행렬들을 변형하는 방식을 사용한다.

여기서는 동시 출현 행렬까지만 다루도록 하겠다.

동시출현(공기, Co-occurrence) : 단어들이 동시에 등장하는 횟수
동시 출현 횟수를 하나의 행렬로 나타낸 뒤 그 행렬을 수치화해서 단어 벡터로 만드는 방법

동시 출현 행렬 (Co-occurrence Matrix)
아래의 예시문장으로 동시 출현 행렬을 만들어보자.
나의 취미는 영화 보기 입니다.
내 취미는 넷플릭스 보기이다.
나의 취미는 유튜브 보기 입니다.

 

  나의 취미는 영화 넷플릭스 유튜브 보기 입니다. 이다.
나의 0 0 2 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
취미는 2 0 0 1 1 1 0 0 0
영화 0 0 1 0 0 0 1 0 0
넷플릭스 0 0 1 0 0 0 1 0 0
유튜브 0 0 1 0 0 0 1 0 0
보기 0 0 0 1 1 1 0 2 1
입니다. 0 0 0 0 0 0 1 0 0
이다. 0 0 0 0 0 0 1 0 0

 

이렇게 만들어진 동시 출현 행렬을 토대로 특이값 분해를 하거나 단어 벡터를 만든다.

 

장점

  • 빠르다. 적은 시간으로 단어 벡터를 만들 수 있다.

예측 방법

예측 기반 방법은 신경망 구조 혹은 어떠한 모델을 사용해 특정 문맥에서 어떤 단어가 나올지를 예측하면서 단어를 벡터로 만드는 방식이다.

  • Word2vec
  • NNLM (Nenural Netwrok Language Model)
  • RNNLM (Recurrent Neural Netwrok Language Model)

참고 : <한국어 임베딩> 이기창

임베딩이란

벡터 공간Vector으로 + 끼워넣는다embed = Embedding
단어난 문장 각각을 벡터로 변환하는 일련의 과정 전체를 가리키는 용어이다.

임베딩이 중요한 이유는 전이학습 transfer learning 때문이다. 대규모 말뭉치 corpus를 미리 학습 pretrain한 임베딩을 모델의 입력값으로 사용하고, 모델이 task를 잘 수행할 수 있도록 업데이트 fine-tuning하는 방식을 썼을때 성능이 좋다.

임베딩의 역할

  • 단어/문장 유사도 계산
  • 의미적/문법적 정보 함축
  • 전이학습
    여기서는 Word2vec만 다루도록 하겠다.

Word2vec

Word2vec는 워드 임베딩 방법중 하나이다. 임베딩은 단어를 밀집 표현(희소 표현과 반대되는 표현)으로 변환하여 벡터화 한다. Word2vec은 CBOW(Continuous Bag of Words) 와 Skip-Gram 두가지 모델로 나뉜다.
원-핫 벡터는 단어 간 유사도를 계산할 수 없지만 Word2vec을 사용하면 단어 간 유사도를 반영할 수 있도록 단어의 의미를 벡터화 할 수 있다.

 

희소 표현(Sparse Representation)
벡터 또는 행렬(matrix)의 값이 대부분이 0으로 표현되는 방법. (각 단어간 유사성을 표현할 수 없음.)

ex. 원-핫 벡터 = 희소 벡터(sparse vector)

 

분산 표현(Distributed Representation)
단어의 '의미'를 다차원 공간에 벡터화하는 방법

  • 분산 표현을 이용하여 단어의 유사도를 벡터화하는 작업은 워드 임베딩(embedding) 작업에 속함.
  • 분포 가설을 이용하여 단어들의 셋을 학습하고, 벡터에 단어의 의미를 여러 차원에 분산하여 표현
  • 저차원에 단어의 의미를 여러 차원에다가 분산하여 표현
  • 단어 간 유사도를 계산 가능

 

CBOW vs Skip-Gram

  • CBOW
    : 어떤 단어를 문맥 안의 주변 단어들을 통해 예측하는 방법학습 방법
    • <고양이가 생선을 먹는다.> 라는 문장에서 주변 단어를 통해 <생선>이라는 하나의 단어를 예측하는 모델이다. 
      1. 입력층 : 각 주변의 단어들을 원-핫 벡터로 만들어 입력층 벡터로 사용
      2. N-차원 은닉층 : 가중치 행렬을 각 원-핫 벡터에 곱해 n-차원 벡터를 만든다.
      3. 출력층 : 만들어진 n-차원 벡터를 모두 더한 후 개수로 나누어 평균 n-차원 벡터로 만든다. n-차원 벡터에 다시 가중치 행렬을 곱해서 원-핫 벡터와 같은 차원의 벡터로 만든다.
      4. 만들어진 벡터를 실제 예측하려고 하는 단어의 원-핫 벡터와 비교해서 학습한다.

  • Skip-Gram
    : 어떤 단어를 가지고 특정 문맥 안의 주변 단어들을 예측하는 방법
    • <고양이가 생선 을 먹는다.>
      <생선>이라는 단어를 가지고 주변에 올 단어를 예측하는 모델이다.

학습 방법

  1. 입력층 : 하나의 단어를 원-핫 벡터로 만들어서 입력값으로 사용
  2. N-차원 은닉층 : 가중치 행렬을 원-핫 벡터에 곱해서 n-차원 벡터를 만든다.
  3. 출력층 : n-차원 벡터에 다시 가중치 행렬을 곱해서 원-핫 벡터와 같은 차원의 벡터로 만든다.
  4. 만들어진 벡터를 실제 예측하려는 주변 단어들 각각의 원-핫 벡터와 비교해서 학습한다.
반응형