이번 장에서는 정규화 기법 중 코퍼스에 있는 단어의 개수를 줄일 수 있는 기법인 표제어 추출(lemmatization)과
어간 추출(stemming)의 개념에 대해서 알아보자. 또한 이 둘의 결과가 어떻게 다른지도 확인해보자!.
1. 표제어 추출(Lemmatization)
표제어: Lemma라고 부르며, "기본 단어"라는 뜻을 갖고 있다. 따라서 표제어 추출이란, 단어들로부터 표제어를 찾아가는 것이라고 할 수 있다.
핵심은 단어들이 다른 형태를 갖더라도, 뿌리 단어와 비교했을 때 단어의 개수를 줄일 수 있을지 판단한다.
예를 들어 am, are, is는 서로 다른 스펠링 이지만, be V라는 점에서는 모두 동일하다.
따라서 am, are, is에 대한 표제어 추출결과는 be인 것이다.
표제어 추출을 위한 방법으로는 단어를 형태학적으로 파싱(parsing)하는 것이다.
따라서 모든 단어들을 형태소로 만들어야 한다.
그리고 형태소는 크게 두 가지로 이루어져 있다.
1. 어간 (stem) : 단어의 의미를 담고있는 단어의 핵심 부분
2. 접사 (affix) : 단어에 추가적인 의미를 주는 부분
결론적으로, 표제어 추출은 위 두 가지를 분리하는 작업이라고 할 수 있다.
"cats"에 대한 추출값은 cat(어간) + s(접사)
코드를 통해서 실습을 진행해보자.
결과를 보면 알겠지만, 표제어 추출은 어간 추출과는 달리 단어의 형태가 적절히 보존되는 양상을 보이는 특징을 가진다.
하지만 그럼에도 위의 결과에서는 dy나 ha와 같이 의미를 알 수 없는 적절하지 못한 단어를 출력하고 있다.
이는 표제어 추출기(lemmatizer)가 본래 단어의 품사 정보를 알아야만 정확한 결과를 얻을 수 있기 때문이다.
WordNetLemmatizer는 입력으로 단어가 동사 품사라는 사실을 알려줄 수 있습니다.
즉, dies와 watched, has가 문장에서 동사로 쓰였다는 것을 알려준다면 표제어 추출기는 품사의 정보를 보존하면서 정확한 Lemma를 출력할 수 있다.
2. 어간 추출 (Stemming)
어간 추출은 형태학적 분석을 단순화한 버전이라고 볼 수도 있고, 정해진 규칙만 보고 단어의 어미를 자르는 어림짐작의 작업이라고 볼 수도 있다. 따라서 추출 값이 사전에 존재하지 않는 단어일 수도 있다!
" 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, copi 등 사전에 없는 단어가 추출된 것을 확인할 수 있다.
stemmer = PorterStemmer()를 사용한것을 확인할 수 가 있는데,
포터 알고리즘의 규칙 중 대표적으로 아래의 규칙들을 가진다.
ALIZE → AL (realize -> real) ANCE → 제거 (allowance -> allow) ICAL → IC (electricical -> electic)
보통 어간 추출은 표제어 추출보다 더 빠르게 작동한다.
또한 어간 추출기 중 포터 어간 추출기 (PorterStemmer())이 가장 준수한 성능을 자랑한다고 한다.
2. 한국어 어간 추출 (Stemming)
한국어의 어간을 먼저 살펴보면, 5언 9품사의 구조를 갖고 있다.
이 중에서, 용언(동사 및 형용사)은 어간+어미로 구성되어 있다.
1) 활용(conjugation)
활용이란 용언의 어간(stem)이 어미(ending)를 가지는 일을 말한다.
활용(conjugation)은 한국을 포함한 인도유럽어(indo-european language)에서도 주로 볼 수 있는 언어적 특징 중 하나를 말하는 통칭적인 개념이다.
어간(stem): 용언(동사, 형용사)을 활용할 때, 원칙적으로 모양이 변하지 않는 부분.
활용에서 어미에 선행하는 부분. 때론 어간의 모양도 바뀔 수 있음(예: 긋다, 긋고, 그어서, 그어라).
어미(ending): 용언의 어간 뒤에 붙어서 활용하면서 변하는 부분이며, 여러 문법적 기능을 수행
어간이 어미를 취할 때, 어간의 모습이 일정하다면 규칙 활용, 어간이나 어미의 모습이 변하는 불규칙 활용으로 나뉨.
(2) 규칙 활용
규칙 활용은 어간이 어미를 취할 때,어간의 모습이 일정합니다. 아래의 예제는 어간과 어미가 합쳐질 때, 어간의 형태가 바뀌지 않음을 보여줍니다.
잡/어간 + 다/어미
이 경우에는 어간이 어미가 붙기전의 모습과 어미가 붙은 후의 모습이 같으므로, 규칙 기반으로 어미를 단순히 분리해주면 어간 추출이 됩니다.
(3) 불규칙 활용
불규칙 활용은 어간이 어미를 취할 때 어간의 모습이 바뀌거나취하는 어미가 특수한 어미일 경우를 말한다.
예를 들어 ‘듣-, 돕-, 곱-, 잇-, 오르-, 노랗-’ 등이 ‘듣/들-, 돕/도우-, 곱/고우-, 잇/이-, 올/올-, 노랗/노라-’와 같이 어간의 형식이 달라지는 일이 있거나 ‘오르+ 아/어→올라, 하+아/어→하여, 이르+아/어→이르러, 푸르+아/어→푸르러’와 같이 일반적인 어미가 아닌 특수한 어미를 취하는 경우 불규칙활용을 하는 예에 속한다.
이 경우에는 어간이 어미가 붙는 과정에서 어간의 모습이 바뀌었으므로 단순한 분리만으로 어간 추출이 되지 않고 좀 더 복잡한 규칙을 필요로 합니다. 아래의 링크는 다양한 불규칙 활용의 예를 보여준다.
앞서 배운 단어 데이터(코퍼스)에서 용도에 맞게 토큰으로 분류하는 토큰화(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])
동일한 단어들의 나열에 대해서 두 스태머는 전혀 다른 결과를 보여준다. 두 스태머 알고리즘은 서로 다른 알고리즘을 사용하기 때문이다. 그렇기 때문에 이미 알려진 알고리즘을 사용할 때는, 사용하고자 하는 코퍼스에 스태머를 적용해보고 어떤 스태머가 해당 코퍼스에 적합한지를 판단한 후에 사용하여야 한다.
이런 규칙에 기반한 알고리즘은 종종 제대로 된 일반화를 수행하지 못 할 수 있다. 어간 추출을 하고나서 일반화가 지나치게 되거나, 또는 덜 되거나 하는 경우다. 예를 들어 포터 알고리즘에서 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