정규화 기법 중에서 코퍼스의 단어의 개수를 줄일수 있는 방법이 어간 추출(stemming)과 표제어 추출(lemmatization)이다.
두 작업의 목적은 의미가 같은 단어를 하나의 단어로 일반화 시켜서 문서 내의 단어의 수를 줄이는 것이다.
자연어 처리에서 전처리의 최종 목표는 원본 코퍼스의 복잡도를 감소시키는 것이다.
표제어 추출(Lemmatization)
표제어(lemma)란 '기본 사전형 단어'이다. 표제어 추출은 단어로부터 표제어를 찾는 과정으로 단어의 형태가 달라도 뿌리가 같은 단어를 찾아서 개수를 줄인다. 예를 들어 am, are, is는 서로 다른 단어이지만 뿌리 단어는 be이다. 이때 단어들의 표제어를 be라고 한다.
표제어 추출을 하는 가장 섬세한 방법은 단어의 형태학적 파싱을 진행하는 것이다. 형태소란 '의미를 가진 가장 작은 단위'로
형태학(morphology)이란 형태소로부터 단어를 만들어가는 학문이다.
형태소의 종류로 어간(stem)과 접사(affix)가 존재하는데 이 둘을 살펴보자
1) 어간(stem)
: 단어의 의미를 가지고 있는 핵심 부분
2) 접사(affix)
: 단어에 추가적인 의미를 주는 부분
형태학적 파싱이란 이 두가지 구성 요소를 분리하는 작업이다. cats란 단어에 형태학적 파싱을 하면 cat(어간)과 s(접사)로 분리된다.
물론 더 이상 분리할 수 없는 경우도 있다.
WordNetLemmatizer 실습
우선 wordnet을 설치한다
import nltk
nltk.download('wordnet')
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
words = ['policy', 'doing', 'organization', 'have', 'going', 'love', 'lives', 'fly', 'dies', 'watched', 'has', 'starting']
print("표제어 추출 전 : ", words)
print("표제어 추출 후 : ",[lemmatizer.lemmatize(word) for word in words])
위의 코드를 실행하면 아래와 같은 결과를 얻는다.
표제어 추출 전 : ['policy', 'doing', 'organization', 'have', 'going', 'love', 'lives', 'fly', 'dies', 'watched', 'has', 'starting']
표제어 추출 후 : ['policy', 'doing', 'organization', 'have', 'going', 'love', 'life', 'fly', 'dy', 'watched', 'ha', 'starting']
표제어 추출은 단어의 형태가 적절히 유지가 되지만 dy나 ha같이 의미없는 단어로 추출하는 경우도 있다.
이는 표제어 추출기(lemmatizer)가 단어의 품사를 알아야 제대로 추출을 하기 때문이다.
WordNetLemmatizer는 입력으로 단어가 동사 품사라는 사실을 알려줄 수 있다.
즉, dies와 watched, has가 문장에서 동사로 쓰였다는 것을 알려주면 표제어 추출기는 품사의 정보를 보존하면서 정확한 Lemma를 출력하게 된다.
lemmatizer.lemmatize('dies', 'v')
위 코드를 실행하면 제대로 파싱이 된다.
'die'
표제어 추출은 문맥을 고려하며 수행했을 때의 결과는 해당 단어의 품사 정보를 보존하지만 어간 추출을 수행한 결과는 품사 정보가 보존되지 않는다.
어간 추출(stemming)
어간을 추출하는 작업으로 기계적으로 정해진 규칙에 따라 어간을 추출하는 과정이다.
이 작업은 섬세한 작업이 아니기 때문에 어간 추출 후에 나오는 결과 단어는 사전에 존재하지 않는 단어일 수도 있다.
아래에서 어간추출 알고리즘 중에 하나인 포터 알고리즘으로 어간을 추출한다.
PorterStemmer
from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize
stemmer = PorterStemmer()
sentence = "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."
tokenized_sentence = word_tokenize(sentence)
print('어간 추출 전 :', tokenized_sentence)
print('어간 추출 후 :',[stemmer.stem(word) for word in tokenized_sentence])
우선 토크나이저로 문장을 토큰화하고 토큰화해서 얻은 단어들을 stemmer에 넣어준다.
어간 추출 전 : ['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', '.']
어간 추출 후 : ['thi', 'wa', 'not', 'the', 'map', 'we', 'found', 'in', 'billi', 'bone', "'s", 'chest', ',', 'but', 'an', 'accur', 'copi', ',', 'complet', 'in', 'all', 'thing', '--', 'name', 'and', 'height', 'and', 'sound', '--', 'with', 'the', 'singl', 'except', 'of', 'the', 'red', 'cross', 'and', 'the', 'written', 'note', '.']
위의 결과는 포터 알고리즘으로 문장의 어간을 추출한 결과이다.
포터 알고리즘의 일부를 살펴보면 ALIZE → AL / ANCE → 제거 / ICAL → IC 뭐 이런 식이다.
아래 코드로 실제 결과를 살펴보자
words = ['formalize', 'allowance', 'electricical']
print('어간 추출 전 :',words)
print('어간 추출 후 :',[stemmer.stem(word) for word in words])
어간 추출 전 : ['formalize', 'allowance', 'electricical']
어간 추출 후 : ['formal', 'allow', 'electric']
어간 추출은 기계화된 작업이기 때문에 표제어 추출보다 빠르게 진행된다. 포터 알고리즘은 나름 세밀하게 설계되어 영어 자연어 처리에서
어간 추출을 수행 시 1번 옵션이다. NLTK에서는 포터 알고리즘 외에도 랭커스터 스태머(Lancaster Stemmer) 알고리즘을 지원한다.
이번에는 포터 알고리즘과 랭커스터 스태머 알고리즘으로 각각 어간 추출을 진행했을 때, 이 둘의 결과를 비교해보자.
porter vs lancaster
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']
동일한 단어에 대해서 두 스태머는 서로 다른 결과를 출력한다. 따라서 목적에 맞게 적절한 어간 추출기를 사용하면 된다.
한국어의 어간 추출
한국어는 5언 9품사의 구조를 가지고 있다.
체언 | 명사, 대명사, 수사 |
---|---|
수식언 | 관형사, 부사 |
관계언 | 조사 |
독립언 | 감탄사 |
용언 | 동사, 형용사 |
이 중에서 용언에 해당하는 동사와 형용사는 어간(stem)과 어미(ending)의 결합으로 구성된다.
Reference
'인공지능 > 자연어 처리(NLP)' 카테고리의 다른 글
nlp 기초 실습 (1) 텍스트 전처리[2]-정제와 정규화 (0) | 2024.04.08 |
---|---|
nlp 기초 실습(1) 텍스트 전처리 [1] (0) | 2024.04.08 |