📝 상세 정리

  • 야호! 자연어처리의 세계로 들어왔다!
    • 문제의 본질은 컴퓨터가 우리의 말을 이해하게 만드는 것
  • 2.1 자연어 처리란
    • 우리가 평소에 쓰는 말을 자연어라고 한다.
    • 자연어 처리 (NLP)는 이 자연어를 처리하는 분야.
      • 컴퓨터가 우리말을 이해하게 만들자
    • 우리의 말은 문자로 구성되며, 말의 의미는 단어로 구성된다.
      • 단어는 의미의 최소단위이다.
      • 따라서 컴퓨터에게 단어의 의미를 이해시키는게 중요하다.
      • 그 방법으로는
        • 시소러스를 활용한 기법
        • 통계 기반 기법
        • 추론 기반 기법 (word2vec)
  • 2.2 시소러스
    • 단어의 의미를 나타내기 위해, 사람이 직접 단어의 의미를 정의해보자.
      • 표준국어 대사전처럼 각각의 단어에 그 의미를 설명해 넣을 수 있을까?
        • EX) 자동차
          • 원동기를 장치하여 그 동력으로 어쩌구
    • 시소러스는 유의어 사전으로, 뜻이 같은 단어나 비슷한 단어를 한 그룹으로 묶은 것
      • 동의어 / 유의어
      • 상위와 하위, 전체와 부분 등 더 세세한 관계까지 정의해둔 경우도 있다.
      • 이 그래프 구조를 단어 네트워크라고 생각하고, 컴퓨터한테 가르칠 수 있지 않을까?
    • WordNet
      • 자연어 처리에서 가장 유명한 시소러스
    • 그런데 이런 시소러스에도 문제가 있는데..
      • 시대 변화에 대응하기 어렵다
      • 사람을 쓰는 비용은 크다
      • 단어의 미묘한 차이를 표현할 수 있다
  • 2.3 통계 기반 기법
    • 이제부터는 말뭉치(corpus) 를 이용할 것
      • 대량의 텍스트 데이터
        • 맹목적으로 수집한거 말고, 연구나 어플리케이션을 위해 수집한 것
      • 말뭉치 안에는 자연어에 대한 사람의 지식이 충분히 담겨있다고 볼 수 있다!
    • 자연어 처리에는 다양한 말뭉치가 이용되는데
      • 위키백과나 구글뉴스등도 되고
      • 셰익스피어나 나츠메소세키씨 작품이라던지
      • 일단 한번 연습을 해보자.
    • 전처리
      • 텍스트 데이터를 단어로 분할하고 그 분할된 단어들을 단어 ID 목록으로 변환하는 일
    • 단어의 분산 표현
      • 색을 코발트블루/싱크레드처럼 이름붙일수도 있지만, RGB기호로 나타낼 수도 있을 것이다
        • 심지어 그쪽이 색을 더 정확하게 명시할수도 있고, 3개의 성분으로 간결한 표현도 된다
        • 관련성 여부도, 정량화하기도 쉽다!!
        • 그렇다면 단어도 이렇게 벡터로 표현할 수 있을까?
          • 이를 단어의 분산 표현 이라고 하자
    • 분포 가설
      • 많은 연구들과 기법들이 있었는데, 그 뿌리는 다음과 같다.
        • 단어의 의미는 주변 단어에 의해 형성된다
        • 이를 분포 가설이라고 한다.
      • 이는 단어 자체에는 의미가 없고, 그 단어가 사용된 맥락이 의미를 형성한다는 것을 내포한다.
        • 앞으로 맥락이란 주변에 놓인 단어들을 가리킬 것이다.
          • 윈도우 크기가 k라면 좌우 k단어씩, v[idx-k:idx+k+1] 을 의미한다.
      • 일단 먼저 주변 단어를 세어보는 방법이 자연스럽게 떠오른다!
        • 이를 통계 기반 기법이라고 하자.
        • id값의 종류를 크기로 하는 벡터를 id에 대해 연결해서, $N^2$ 행렬을 만들 수 있다.
          • 이를 동시발생 행렬이라고 하자.
      • 이제 벡터 사이 유사도를 측정하자.
        • 내적.. 유클리드거리.. 등등 모두 쓸 수 있겠지만
        • 우리는 코사인 유사도를 이용하자.
          • $\text{similarity}(\mathbf{x}, \mathbf{y}) = \frac{\mathbf{x} \cdot \mathbf{y}}{||\mathbf{x}|| , ||\mathbf{y}||} = \frac{x_1 y_1 + \cdots + x_n y_n}{\sqrt{x_1^2 + \cdots + x_n^2} \sqrt{y_1^2 + \cdots + y_n^2}}$
            • 이때 ${||\mathbf{x}||}$는 노름이다.
            • 값은 -1에서 1 사이가 나온다.
      • 이걸로 내림차순을 하든 뭘하든 해서 유사도를 계산할 수 는 있지만… 말뭉치가 작으면 문제가 많다.
  • 2.4 통계 기반 기법 개선하기
    • 두 단어를 그냥 이렇게 생으로 하면.. 문제가 깊다
      • the car의 the같이 괘씸한 놈이 존재함
    • 점별 상호정보량 (PMI)
      • $\text{PMI}(x, y) = \log_2 \frac{P(x, y)}{P(x)P(y)}$
        • $P(x), P(y), P(x, y)$ 는 각각 x가 일어날 확률, y가 일어날 확률, 동시에 일어날 확률
        • 이 PMI값이 높을수록 관련성이 높다
        • 이는 동시발생 행렬을 이용해서 다시 쓸 수 있는데
      • $= \log_2 \frac{\frac{C(x, y)}{N}}{\frac{C(x)}{N} \frac{C(y)}{N}} = \log_2 \frac{C(x, y) \cdot N}{C(x) C(y)}$
        • 하지만 이때 동시발생횟수가 0이면 $log_2 0$ 을 계산해야한다는 문제가 있다…
          • 따라서 양의 상호정보량을 사용하자.
            • $= \text{PPMI}(x, y) = \max(0, \text{PMI}(x, y))$
            • 0 이상의 실수로 표현하는게 가능해졌다!
    • 거대한 문제가 생겼다
      • 단어가 $N$개면 차원 또한 $N$개가 된다!!!
        • 심지어 대부분은 0이다
    • 차원 감소
      • 물론 중요한 정보는 최대한 유지하면서 차원을 줄여야한다.
      • sparse한 행렬/벡터를 중요한 축을 잘 찾아서 dense한 행렬/벡터로 만들어야 한다
    • 특잇값분해(SVD)
      • 임의의 행렬을 세 행렬의 곱으로 분해
      • $\mathbf{X} = \mathbf{U}\mathbf{S}\mathbf{V}^T$
        • $\mathbf{U}, \mathbf{V}$는 직교행렬
        • $\mathbf{S}$는 대각행렬
      • 근데 이게 시간복잡도가 $O(N^3)$이라서, Truncated SVD같은걸 이용하기도 한다.
        • 특잇값이 작은걸 버리는 방식
    • PTB 데이터셋
      • 본격적인 적당한 말뭉치를 이용해보자!
      • 여러가지 전처리는 좀 해두셨다
        • 희소한 단어를 <unknown>으로 바꾸기
        • 구체적인 숫자르 N으로 수정하기
        • 각 문장의 끝에 <eos> (end of sentence) 추가하기
      • 결과가 재밌다! 신기하네
  • 2.5 정리
    • 우리는 단어의 의미를 벡터로 인코딩하는데 성공했다! 와!
    • 심지어 SVD를 이용해서 차원을 감소시키고 더 좋은 벡터를 얻어냈다! 와!!

❔질문 사항

  • 윈도우를 이용해서 하면, 문법적인것 (굴절어, 교착어 등)에 대한 정보가 손실되지 않나?
    • I say hello와 hello say I가 같은 의미를 가지게 되니까.
  • 직교행렬을 공부하자
    • 선형대수를 공부해야한다 ㅁㄴㅇㄹㅁㄴㅇㄹ

🔗 참고 자료