어간 추출이란?
특정한 단어의 핵심이 되는 부분을 어간(Stem)이라고 합니다. 그리고 단어에서 어간을 찾아내는 것을 어간 추출(Stemming)이라고 합니다. 서로 다른 형태의 단어들도 어간 추출을 하면 같은 단어로 통합되기 때문에 이를 정규화 방법 중 하나로 사용합니다.
아래는 어간 추출 알고리즘 중 하나인 포터 스테머 알고리즘(Porter Stemming Algorithm)의 규칙 일부입니다. 단순히 어미만 잘라내는 방식으로 어간을 찾고 있는데요. 그렇기 때문에 사전에 없는 단어가 결과로 나오기도 합니다.
● alize → al (Formalize → Formal)
● ational → ate (Relational -> Relate)
● ate → 제거 (Activate -> Activ)
● ment → 제거 (Encouragement -> Encourage)
예를 들면 Activate에서 ate를 제거해 찾은 어간 activ는 사전에 없는 단어입니다. ate를 제거하고 뒤에 e를 붙여줘야 완전한 단어가 되지만, 그렇게까지 섬세하게 처리해 주지는 못하고 있네요.
따라서 코퍼스의 특성이나 분석하는 상황에 따라 어간 추출을 하는게 적합한지를 잘 판단해야 합니다. 그렇지 않으면 분석에 활용돼야 하는 중요한 단어가 손실될 수 있습니다.
NLTK로 어간 추출 하기
NLTK는 어간 추출을 위한 알고리즘으로 포터 스테머(Porter Stemmer)와 랭커스터 스테머(Lancaster Stemmer)를 제공합니다. 두 알고리즘은 어간 추출을 하는 기준이 미세하게 다르기 때문에 무엇을 사용하느냐에 따라 결과가 조금씩 달라집니다. 하지만 사용 방식은 거의 동일하기 때문에, 이번 레슨에서는 포터 스테머 알고리즘을 사용하는 방법만 자세히 알아 볼게요. 아래는 어간 추출을 위한 코드입니다.
from nltk.stem import PorterStemmer
porter_stemmer = PorterStemmer()
text = "You are so lovely. I am loving you now."
porter_stemmed_words = []
# 단어 토큰화
tokenized_words = nltk.word_tokenize(text)
# 포터 스테머의 어간 추출
for word in tokenized_words:
stem = porter_stemmer.stem(word)
porter_stemmed_words.append(stem)
한 부분씩 살펴볼게요. 먼저, 어간 추출을 하기 전에 단어 토큰화가 돼야합니다.
# 단어 토큰화
tokenized_words = nltk.word_tokenize(text)
다음으로, 토큰화 된 단어를 순회하며 어간을 추출하여 결과를 porter_stemmed_words에 추가합니다. 참고로, NLTK의 porter_stemmer.stem() 함수는 단어가 포터 스테머 알고리즘의 기준에 포함되면 추출된 어간을 반환하고, 그렇지 않은 경우에는 원래의 단어를 반환해 줍니다.
# 포터 스테머의 어간 추출
for word in tokenized_words:
stem = porter_stemmer.stem(word)
porter_stemmed_words.append(stem)
어간 추출 결과를 한번 확인해 볼게요.
print('어간 추출 전 :', tokenized_words)
print('포터 스테머의 어간 추출 후:', porter_stemmed_words)
lovely와 loving이 love로 어간 추출 되었습니다. 서로 다른 두 개의 단어가 하나의 어간으로 정규화 되었네요.
지금까지 포터 스테머 알고리즘을 이용한 어간 추출 방법을 배웠는데요. 랭커스터 스테머 알고리즘은 동일한 코드에 적용하는 함수만 바꾸면 됩니다.
from nltk.stem import LancasterStemmer
lancaster_stemmer = LancasterStemmer()
text = "You are so lovely. I am loving you now."
lancaster_stemmed_words = []
# 랭커스터 스테머의 어간 추출
for word in tokenized_words:
stem = lancaster_stemmer.stem(word)
lancaster_stemmed_words.append(stem)
랭커스터 스테머 알고리즘을 사용하면 결과가 조금 다르게 나오는데요. 꼭 각각의 알고리즘을 적용해 보고 차이를 비교해 보시기 바랍니다.
그러면 어간 추출을 하는 코드도 하나의 함수로 만들어볼게요.
preprocess.py
from nltk.stem import PorterStemmer
# 포터 스테머 어간 추출 함수
def stemming_by_porter(tokenized_words):
porter_stemmer = PorterStemmer()
porter_stemmed_words = []
for word in tokenized_words:
stem = porter_stemmer.stem(word)
porter_stemmed_words.append(stem)
return porter_stemmed_words
만든 함수는 preprocess.py 파일에 등록하고, 이후 포스팅에서 필요할 때마다 불러와 사용하겠습니다.
'Data Analysis > Natural Language Processing(NLP)' 카테고리의 다른 글
문장 토큰화(Sentence Tokenization) (0) | 2023.06.09 |
---|---|
어간 추출 실습 (0) | 2023.06.09 |
정규화(Normalization) (0) | 2023.06.08 |
자연어 전처리 적용 I (0) | 2023.06.08 |
불용어 제거 실습 (0) | 2023.06.08 |