앞서 배운 단어 데이터(코퍼스)에서 용도에 맞게 토큰으로 분류하는 토큰화(tokenization)에 대해서 배웠다.

이번에는 토큰화의 작업 전,후에서 사용하는 정제(cleaning) & 정규화(normalization)에 대해서 배워보자.

 

먼저 정제와 정규화의 목적은 아래와 같다.

정제(cleaning) : 갖고 있는 코퍼스로부터 노이즈를 제거

정규화(normalization) : 표현 방법이 다른 단어를 통합시켜서 같은 단어로 만들어줆

1. 규칙에 기반한 표기가 다른 단어들의 통합

필요에 따라 같은 의미를 갖고 있음에도, 표기가 다를 수 있다. 이를 하나의 단어로 정규화 할 수 있다.

ex) USA와 US

위 두개는 같은 의미를 가지므로 같게 정규화 해보자.

 

먼저, 대/소문자 통합이다.

통상 영어의 첫 글자는 대문자로 표기한다. He is ~~~ 에서 He 는 he와 같다.

따라서 He/he의 정규화는 대/소문자 통합으로 해결할 수 있다.

 

주의할 점은 대문자와 소문자가 다른의미를 가지는 경우이다.

위 예시에서 미국인 US와 우리를 뜻하는 us가 다른 것처럼!

 

또한 고유명사로써 회사 이름, 사람 이름의 경우 또한 마찬가지이다.

 

그 밖에도, 아래와 같은 방식 등으로 텍스트 전처리를 수행할 수 있다.

2. 불용어 제거 

3. 등장 빈도가 적은 단어

4. 길이가 짧은 단어

 

위 방법들에 대해서는 다음 포스트에서 자세히 다뤄 보도록 하자.

 

어간 추출(Stemming)과 표제어 추출(Lemmatization)

어간추출과 표제어추출 모두 단어의 개수를 줄이는 방식이다.

먼저 어간 추출이란  형태학적 분석을 단순화한 버전이라고 볼 수도 있고, 정해진 규칙만 보고 단어의 어미를 자르는 어림짐작의 작업이라고 볼 수도 있다고 한다.

This was not the map we found in Billy Bones's chest, but an accurate copy, complete in all things--names and heights and soundings--with the single exception of the red crosses and the written notes.

위의 예시 문장에 대해서 어간추출을 진행해보도록 하자.

 

규칙 기반의 접근을 하고 있으므로 어간 추출 후의 결과에는 사전에 없는 단어들도 포함되어 있다.

가령, 포터 알고리즘의 어간 추출은 이러한 규칙들을 가진다.

ALIZE → AL
ANCE → 제거
ICAL → IC

 

위의 규칙에 따르면 좌측의 단어는 우측의 단어와 같은 결과를 얻게된다.

 

formalize → formal
allowance → allow
electricical → electric

 

실제 코드를 통해 확인해보자.

words = ['formalize', 'allowance', 'electricical']

print('어간 추출 전 :',words)
print('어간 추출 후 :',[stemmer.stem(word) for word in words])
어간 추출 전 : ['formalize', 'allowance', 'electricical']
어간 추출 후 : ['formal', 'allow', 'electric']

어간 추출 속도는 표제어 추출보다 일반적으로 빠른데, 포터 어간 추출기는 정밀하게 설계되어 정확도가 높으므로 영어 자연어 처리에서 어간 추출을 하고자 한다면 가장 준수한 선택이다. NLTK에서는 포터 알고리즘 외에도 랭커스터 스태머(Lancaster Stemmer) 알고리즘을 지원한다. 이번에는 포터 알고리즘과 랭커스터 스태머 알고리즘으로 각각 어간 추출을 진행했을 때, 이 둘의 결과를 비교해보자.

from nltk.stem import PorterStemmer
from nltk.stem import LancasterStemmer

porter_stemmer = PorterStemmer()
lancaster_stemmer = LancasterStemmer()

words = ['policy', 'doing', 'organization', 'have', 'going', 'love', 'lives', 'fly', 'dies', 'watched', 'has', 'starting']
print('어간 추출 전 :', words)
print('포터 스테머의 어간 추출 후:',[porter_stemmer.stem(w) for w in words])
print('랭커스터 스테머의 어간 추출 후:',[lancaster_stemmer.stem(w) for w in words])
어간 추출 전 : ['policy', 'doing', 'organization', 'have', 'going', 'love', 'lives', 'fly', 'dies', 'watched', 'has', 'starting']
포터 스테머의 어간 추출 후: ['polici', 'do', 'organ', 'have', 'go', 'love', 'live', 'fli', 'die', 'watch', 'ha', 'start']
랭커스터 스테머의 어간 추출 후: ['policy', 'doing', 'org', 'hav', 'going', 'lov', 'liv', 'fly', 'die', 'watch', 'has', 'start']

동일한 단어들의 나열에 대해서 두 스태머는 전혀 다른 결과를 보여준다. 두 스태머 알고리즘은 서로 다른 알고리즘을 사용하기 때문이다. 그렇기 때문에 이미 알려진 알고리즘을 사용할 때는, 사용하고자 하는 코퍼스에 스태머를 적용해보고 어떤 스태머가 해당 코퍼스에 적합한지를 판단한 후에 사용하여야 한다.

이런 규칙에 기반한 알고리즘은 종종 제대로 된 일반화를 수행하지 못 할 수 있다. 어간 추출을 하고나서 일반화가 지나치게 되거나, 또는 덜 되거나 하는 경우다. 예를 들어 포터 알고리즘에서 organization을 어간 추출했을 때의 결과를 보자.

organization → organ

organization과 organ은 완전히 다른 단어 임에도 organization에 대해서 어간 추출을 했더니 organ이라는 단어가 나왔다. organ에 대해서 어간 추출을 한다고 하더라도 결과는 역시 organ이 되기 때문에, 두 단어에 대해서 어간 추출을 한다면 동일한 어간을 갖게 될 수 있다. 이는 의미가 동일한 경우에만 같은 단어를 얻기를 원하는 정규화의 목적에는 맞지 않다.

마지막으로 동일한 단어에 대해서 표제어 추출과 어간 추출을 각각 수행했을 때, 결과에서 어떤 차이가 있는지 간단한 예를 통해서 알아 보도록 하자.

 

Stemming

am → am
the going → the go
having → hav

 

Lemmatization
am → be
the going → the going
having → have

 

 

출처: 위키독스

         (https://wikidocs.net/21707)

+ Recent posts