Deep Learning/Natural Language Processing

[W13D2] NLP 텍스트 전처리

makeitworth 2021. 7. 29. 00:06

자연어 처리: 텍스트 전처리

자연어 처리란

  • 자연어의 의미를 컴퓨터로 분석해서 특정 작업을 위해 사용할 수 있도록 하는 것
  • 응용분야
    • 기계번역, 감성 분석, 문서 분류, 질의응답 시스템, 챗봇, 언어 생성(ex> GPT), 음성인식, 추천 시스템 등...
    • 최근의 딥러닝 분야의 인기 성장은 컴퓨터 비전 분야의 발전과 성공의 영향이 컸다. 자연어 처리에서는 비전만큼의 성공을 거두지 못해왔다. 그러다가 비전에 사용하던 알고리즘을 자연어 문제에 적용시켜서 성능 향상이 이뤄지기 시작했고, 요즘에는 성공적인NLP의 기술(ex> transformer model, BERT model)을 컴퓨터 비전에 적용시켜 발전시키고 있다.

참고 자료

단어(Word)

  • He stepped out into the hall, was delighted to encounter a water brother. -> 단어의 수를 셀 때, 문장부호를 단어에 포함시켜야 할까?
    • 문장부호(,)가 여러 단어, 구 사이의 관계를 지을 경우 문장부호를 단어에 포함시키는 것이 사물들 사이의 경계를 잘 구분할 수 있는 이점이 있다.
    • 문장부호가 문장의 의미에 영향을 주는 경우(? 또는 !) 문장부호를 단어에 포함시키는 것이 좋다.
  • I do uh main- mainly business data processing. -> 구어체 문장의 경우, fragments(깨어진 단어, 단어를 더듬으면서 말한다던지), filled pauses(hu, um…)를 단어에 포함시켜야 할까?
    • 빼는 게 좋다고 생각할지 모르나, 포함하는 게 좋을 때도 있다. 음성인식의 경우 fragments나 filled pauses가 나타나는 경우 문장의 일부분을 다시 반복할 가능성이 높다. 따라서 뒷내용을 예측하는 데 도움이 될 수 있다.
    • 사람마다 um, ah등 중간에 말이 비는 부분들을 채우는 방식이 다르다. 따라서 화자가 누구인지 디텍트 하는데 도움이 된다.
    • 음성을 텍스트로 만들어줄 때 또한 단어로 포함시켜 제거해주는게 좋다.
  • "Suess's cat in the hat is different from other cats!"
    • 표제어(lemma): 여러 단어들이 공유하는 뿌리 단어
    • 단어형태(wordform): 같은 표제어를 공유하지만 다양한 형태를 가질 수 있음
    •  cat/cats: 두 가지의 형태를 가지고 있지만 동일한 표제어 cat을 공유함
  • Vocabulary: 단어의 집합
  • Type: Vocabulary의 한 원소(Token에서 중복제거)
  • Token: 문장 내에 나타나는 한 단어
  • They picnicked by the pool, then lay back on the grass and looked at the stars.
    • 16 tokens
    • 14 types(the가 반복됨)
  • 대표적인 자연어 데이터셋

말뭉치(Corpus)

  • 하나의 말뭉치는 일반적으로 대용량 문서들의 집합이다.
  • 말뭉치의 특성은 아래의 요소들에 따라 달라진다
    • 언어 (7097개의 언어가 존재)
    • 방언
    • 장르(뉴스, 소설, 과학기술문서 등)
    • 글쓴이의 인구통계적 속성(나이, 성별, 인종 등)
  • 다양한 말뭉치에 적용할수 있는 NLP알고리즘이 바람직하다.

텍스트 정규화

  • 모든 자연어 처리는 텍스트 정규화를 필요로 한다 -> 이 시간에는 토큰화를 집중적으로 볼 것
    • 토큰화(tokenizing words) : 토큰을 구분하는 알고리즘
    • 단어 정규화(normalizing word formats) : wordform을 정규화
    • 문장 분절화(segmenting sentences): 하나의 문서를 여러 개의 문장으로 구분해주는 것

Unix 명령으로 간단하게 토큰화하기

  • 토큰화: 문서가 주어졌을 때 단어들의 시퀀스로 표현하는 것
  • 셰익스피어의 햄릿을 토큰화 해보자
    • tr -sc ‘A-Za-z’ ‘\in’ < hamlet.txt
      • tr은 한 패턴을 다른 패턴으로 교체해주는 명령어 (replace)
      • c 옵션은 ‘A-Za-z’ 패턴을 제외한 모든 나머지 패턴을 뒤세 나타나는 또 다른 패턴 ‘\n’으로 교체한다.
      • ‘A-Za-z’는 모든 알파벳 대문자와 소문자를 말한다
      • s 옵션은 중복되는 단어들을 하나로 합쳐준다.
      • 즉 주어진 텍스트에 나타나는 모든 단어들에 대해서 알파벳 대문자/소문자 외의 모든 다른 글자들을 new line으로 replace함. 즉 한줄에 단어 하나 씩 표시함
      • 이 문서 안에 나타나는 단어들을 모아서 vocabulary를 만들어보자.
  • 빈도수로 정렬
    • tr -sc 'A-Za-z' '\n' <  hamlet.txt | sort | uniq -c | sort -n -r
    • uniq는 단어들의 빈도수
    • sort는 가장 많이 나타난 단어 순으로 정렬 대문자를 소문자로 통일해서 정렬해보자.
  • 소문자로 변환해서 정렬
    • tr -sc ‘A-Z’‘a-z’ < hamlet.txt tr -sc ‘a-z’‘\in’ sort uniq -c sort -n -r
      • tr -sc ‘A-Z’‘a-z’: 모든 대문자를 소문자로 바꾼다
  • 이런 과정을 거친 후에 가장 빈번하게 나타나는 top K 단어들을 vocabulary에 포함시킴
    • vocabulary가 너무 커지면, parameter도 너무 커지는 문제 발생

UNIX 명령어로 tokenization할 때 문제점들

  • 문장부호(punctuation)들을 항상 무시할 수는 없다
    • 단어 안에 나타나는 문장부호들: m.p.h, AT&T, Ph.D
    • 화폐단위($10.00), 날짜(2021/02/15), URLs, hashtags(#), 이메일 주소
    • 문장부호가 단어의 의미를 명확하게 하는 경우는 제외시키지 않는 것이 좋다.
  • 접어(clitics): 다른 단어에 붙어서 존재하는 형태
    • we’re -> we are
  • 여러 개의 단어가 붙어야 의미가 있는 경우
    • New York, rock’n’roll

중국어의 tokenization 경우

ex>

姚明进入总决赛。 Yao Ming reaches the Finals

 

3단어?

姚明   进入  总决赛。

Yaoming  reaches  finals

 

5단어?

姚  明  进入  总  决赛。

Yao  Ming  reaches  overall  finals

 

7글자? (Don't use words at all)

姚  明  进  入  总  决  赛。

Yao Ming enter enter overall decision game

  • 중국어는 띄어쓰기가 없음
  • 중국어의 경우는 글자 단위로 vocabulary를 만들면 사이즈를 좀 줄일 수 있다.

한국어의 tokenization 경우

  • 한국어의 경우 토큰화가 복잡함
  • 띄어쓰기가 잘 지켜지지 않고 띄어쓰기가 제대로 되었더라도 한 어절에 하나 이상의 의미 단위들이 있을 수 있다.
  • 형태소(morpheme): 뜻을 가진 가장 작은 말의 단위
    • 자립 형태소: 명사, 대명사, 부사 등
    • 의존 형태소: 다른 형태소와 결합하여 사용되는 형태소. 접사, 어미, 조사 등

ex> 열심히 코딩한 당신, 연후에는 여행을 가봐요 

-> ['열심히', '코딩', '한', '당신', ',', '연휴', '에는', '여행', '을', '가봐요']

  • 단어보다 작은 단위(subword)로 토큰화가 필요하다. (한국어뿐만 아니라 영어, 다른 언어도 필요할 때 있음)

Subword Tokenization이 왜 필요한가?

  • 만약 학습 데이터에서 보지 못했던 새로운 단어가 나타난다면?
    • 학습 데이터: low, new, newer
    • 테스트 데이터: lower
    • -er, -est 등과 같은 형태소를 분리할 수 있으면 좋을 것이다
  • Subword toeknization algorithms
    • Byte-Pair Encoding(BPE) (수업 시간에 주로 다룰 것)
    • WordPiece: BPE와 유사한데 확률적인 개념을 이용해 발전시킨 것
    • Unigram language modeling: 완전히 확률 모델에 기반한 알고리즘
  • 모든 토크나이제이션 알고리즘은 두 가지 구성요소를 갖는다.
    • Token learner: 말뭉치에서 vocabulary(token 들의 집합)을 만들어 냄. 학습하는 부분
    • Token segmenter: 새로운 문장을 토큰화함. 학습한 것을 새로운 문장에 적용하는 부분.

Subword Tokenization - Byte-Pair Encoding(BPE)

  • Vocabulary를 단일 문자들의 집합으로 초기화한다
  • 다음을 반복한다.
    • 말뭉치에서 연속적으로 가장 많이 발생하는 두 개의 기호들(vocabulary 내의 원소들)을 찾는다
    • 두 기호들을 병합하고 새로운 기호로 vocabulary에 추가한다
    • 말뭉치에서 그 두 기호들을 병합된 기호로 모두 교체한다
  • 위 과정을 k번의 병합이 일어날 때까지 반복한다
  • 기호 병합은 단어 안에서만 이루어진다. 이것을 위해서 단어 끝을 나타내는 특수기호 ‘_‘을 단어 뒤에 추가한다. 그리고 각 단어를 문자 단위로 쪼갠다.
    • ex> low low low low low lowerst lowest newer newer newer newer newer newer wider wider wider new new
    • 단어 끝을 나타내는 특수기호 ‘_‘을 단어 뒤에 추가
    •  말뭉치(corpus)
      • l o w_ 5번, l o w e s t_ 2번, n e w er_ 6번, w i d er_ 3번, n e w_ 2번
      • -> 말뭉치에서 연속적으로 가장 많이 발생하는 두 개의 기호는 e r이므로, er로 병합하여 vocabulary에 넣는다. 그리고 말뭉치에 병합된 기호를 대체한다.
    • vocabulary(특수기호 _까지 포함)
      • _, d, e, i, l, n, o, r, s, t, w, er(처음에는 character와 특수기호 _만 있다가 er 추가됨)
    • 위의 과정을 반복하다 보면 er_, ne, new, lo, low, newer, low_의 토큰들이 추가로 병합이 일어나 vocabulary에 추가된다.
    • vocabulary 사이즈를 너무 크게 늘리면 안 되기 때문에 적절한 때에 멈춘다.
  • Token segmenter
    • 새로운 단어가 주어졌을 때 어떻게 토큰화할 것인지?
    • Greedy한 적용: 병합을 학습한 순서대로 적용(“e r” -> “er”)
    • 자주 나타나는 단어는 하나의 토큰으로 병합됨
    • 드문 단어는 subword 토큰들로 분할됨
  • 하나의 단어 “n e w e r _“은 하나의 토큰 “newer_“로 토큰화 됨 
  • 하나의 단어 “l o w e r _“은 하나의 토큰 “low er _“로 토큰화 됨 (학습 데이터에 없었던 단어라서)

Subword Tokenization - Wordpiece

  • BERT모델 사용시 input processing 할 때 사용됨
  • 기호들의 쌍을 찾을 때 빈도수 대신에 likelihood를 최대화시키는 쌍을 찾는다.(나타날 확률 계산)
  • 예를 들어, 말뭉치에서 lo이 일어날 확률보다 er이 일어날 확률이 크면 “er” 병합 토큰을 vocabulary에 추가한다.
  • BPE에 비해 확률적인 부분이 추가되었지만 완전히 확률적인 모델은 아님
  • 병합의 candidate들 중에서 고르는 방식이 greedy하다.
  • 확률은 어떻게 계산할 것이냐? -> 다음 날 언어모델 배울 때...

Subword Tokenization - Unigram

  • 병합을 하나씩 순차적으로 고르는 것이 아니라,
  • 확률 모델(언어 모델)을 사용한다.
  • 학습 데이터 내의 문장을 관측(observed) 확률변수로 정의한다
  • Tokenization을 잠재(latent) 확률변수로 정의한다. 
    • 연속적인(sequential) 변수
  • 데이터의 주변 우도(marginal likelihood)를 최대화시키는 tokenization을 구한다.
    • EM(expectation maximization)을 사용. 잠재적인 변수가 문제에 개입이 될 때 데이터의 우도를 최대화하는 문제를 풀 때 EM방식을 사용한다.
      • marginal likelihood 계산은 P(관측된 변수 x, 잠재 변수 z)을 z에 대해서 sumation을 하는 것이다. 이것이 P(x), marginal likelihood가 된다.
    • Maximization step에서 Viterbi 알고리즘을 사용(wordpiece는 greedy하게 likelihood를 향상)
      • 비터비를 사용해 가장 최선의 토크나이제이션을 한다.
      • 워드피스도 우도를 최대화시키기 때문에 unigram과 비슷하지만, 워드피스는 greedy하게 구하는 게 차이점이다. 다양한 토크나이제이션의 병합 가능성을 배제하고 하나씩 한다.

단어 정규화

  • 단어들을 정규화된 형식으로 표현 (아래의 항목들은 같은 의미를 가지고 있지만, 형태가 다른 토큰들)
    • U.S.A. or USA or US
    • uhhuh or uh-huh
    • Fed or fed
    • am, is, be, are
  • 검색엔진에서 문서들을 추출할 때 유용할 수 있다
    • 검색어: “USA”, 문서: 단어 “US”만을 포함하더라도 검색될 수 있도록

Case folding

  • 모든 문자들을 소문자화함
    • 일반화를 위해서 유용: 학습 데이터와 테스트 데이터 사이의 불일치 문제에 도움
    • 정보검색, 음성인식 등에서 유용
    • 그러나 감성 분석 등의 문서 분류 문제에서는 오히려 대소문자 구분이 유용할 수 있음(국가 이름 “US” vs 대명사 “us”)

Lemmatization

  • 어근을 사용해서 표현
    • am, are, is -> be라는 의미
    • car, cars, car’s, cars’ -> car라는 의미
    • 이처럼 하나로 통합해주면
  • He is reaading detective stories -> He be read detective story

최근 경향

  • 최근에는 단어 정규화를 aggressive하게 하지 않는다. 토크나이제이션은 많이 사용하지만, 그 이후 더 정규화하는 부분은 프로세싱을 잘 하지 않는다.
  • 단어 정규화가 필요한 근본적인 이유
    • 단어들 사이의 유사성을 이해해야하기 때문
    • 단어 정규화 작업을 같은 의미를 가진 여러 형태의 단어들을 하나의 단어를 대응시키는 것으로 이해할 수 있다(위의 Lemmatization처럼)
  • 단어를 vocabulary로 정의된 공간(고차원 희소 벡터)이 아닌 저차원 밀집(dense) 벡터로 대응시킬 수 있다면?
    • car => [0.13, 0.52, 0.01] 원소가 3개인 벡터
    • cars => [0.15, 0.49, 0.02]
    • 각각의 원소가 서로 비슷하면 벡터가 전체적으로 서로 비슷함을 알 수 있다. (굳이 정규화 필요없이)
    • 단어 임베딩을 사용해서 단어를 표현하게 되면 단어 정규화의 필요성이 줄어듦