Normalization and Pre-Tokenization
- 본 글은 자연어에 대한 Preprocessing Pipeline을 알아보고, Preprocessing하는 방법에 대해 소개합니다.
1. 소개
텍스트 데이터를 모델에 입력할 때는 다음과 같은 파이프라인을 거치게 됩니다. Normalization에서는 raw string이 조금 일관성을 갖게 하고 깨끗하게 하는 과정을 말합니다. 예를 들어, 불필요한 여백, 불용어를 제거하고 대소문자를 조정하는 것입니다. Normalization에서 정제된 데이터는 Pre-Tokenization과정을 통해 더 작은 단위로 쪼게지게 됩니다. Pre-Tokenization을 통해 문장을 단어단위로 나누면 나누어진 토큰이 하나의 word로 취급이 되고, 이후 Tokenziation 과정을 통해 sub word 등으로 존재하게 됩니다. 오늘 다룰 내용은 파이프라인 중 Normalization과 Pre-Tokenization입니다.
2. Cleaning and Normalization
텍스트 데이터는 정제하고, 정규화하는 과정을 거쳐야 더 좋은 성능을 낼 수 있습니다. Cleaning은 코퍼스의 노이즈를 제거하는 과정이고, Normalization은 같은 단어이지만 표현 방법만 다른 경우 같은 표현으로 통합시키는 과정입니다. 예를 들어, 영어 'The'와 'the'는 같은 의미를 가지지만 다른 표현 방법입니다. 이를 같이 'THE' 혹은 'the'로 바꾸는 과정이 Normalization입니다.
Cleaning과 Normalization기법으로 다음과 같이 여러가지 기법이 있습니다. 먼저 규칙에 의해 표현이 다른 단어를 같은 의미임을 명시함으로써 통합하는 방법입니다. 예를 들어, '간다', '가는', '감', '갔다', '갔는데' 등 어근은 동일하지만 어휘가 바뀌면서 여러 단어로 표현될 수 있습니다. 이 단어들의 어근을 추출하는 방법으로 Steming, Lemmatization이 있습니다. 다음으로 영어 데이터의 경우에는 대, 소문자를 통합함으로써 정규화할 수 있습니다. 예를 들어, 'He goes to the U.S.A'와 'he goes to the united states of America'는 동일한 표현입니다. 우리는 'He'와 'he'가 같음을 알고 있습니다. 따라서 'He'를 소문자로 바꿔 같은 표현으로 만듭니다. 세 번째로 불필요한 단어를 제거할 수 있습니다. 불필요한 단어라는 것은 특수문자도 있지만, 분석 및 학습에 도움이 되지 않는 단어도 의미합니다. 영어에서는 길이가 굉장히 짧은 단어도 포함될 수 있습니다. 네 번째로 정규표현식을 사용하여 노이즈 데이터를 제거할 수 있습니다.
정규 표현식은 데이터의 패턴을 파악하여 제거하는 방법 중 하나입니다. 텍스트 데이터에서 특정 패턴을 인식하는데 유용한 도구로 사용됩니다. 파이썬에서는 RE 패키지와 NLTK을 이용하여 정규표현식을 사용할 수 있습니다. 위의 예시는 알파벳이 아닌 문자를 여백으로 대체한 경우입니다.
다음으로 Pre-tokenization을 알아보겠습니다. Pre-tokenization은 tokenization이전에 가장 큰 토큰의 형태로 나누는 것을 의미합니다. 가장 일반적인 방법은 특수문자를 제거하고 공백단위로 나누는 것입니다. 하지만 특수문자 중 \('\)와 같이 not의 축약을 위해 사용된 경우 의미를 잃어버리는 경우가 생길 것입니다. 특히 한국어의 경우 실질적인 의미를 갖는 단어와 문법적인 의미를 갖는 단어가 붙어 교착어의 특징을 갖습니다. 단순히 공백 단위로 나누면 여러 조사, 어미변환에 의해 같은 단어임에도 불구하고 다른 토큰으로 분류가 될 것입니다. 따라서 형태소를 더 신경써야 한다는 특징이 있으며, 한국어는 띄어쓰기가 잘 지켜지지 않는 점도 신경써야 할 것입니다. 한국어 텍스트 전처리 툴은 지도학습 기반의 'KoNLPy', 'KHaiii'가 있고, 비지도학습 기반의 'soynlp'가 있습니다.
KoNLPy는 한국어 자연어처리 파이썬 패키지입니다. 오픈소스 형태소 분석기를 파이썬에서 활용할 수 있는 형태로 제공하고 있습니다. 총 5개의 클래스를 제공하는데 Hannanum, Kkma, Komoran, Mecab, Okt가 있습니다. 5개의 클래스는 공통적으로 한국어 텍스트를 형태소 단위로 나누어주는 morphs를 지원하고, nouns를 활용하여 명사만 추출할 수 있고, pos를 활용하여 직접 품사를 태깅하는 작업도 가능합니다. 일반적으로 Mecab을 주로 사용하며 클래스에 따라 POS tagging방식이 조금씩 달라진다는 점이 특징입니다.
앞서 살펴본 KoNLPy가 규칙기반이라면, Khaiii는 데이터 기반으로 학습하여 만들어졌습니다. 특정 단어에서 Window size만큼 단어를 찾아 (1+2*window size, embedding size)가 입력으로 주어집니다. n-gram filter를 사용하여 벡터를 만들고, Max Pooling하여 가장 큰 스칼라를 찾습니다. 2, 3, 4, 5-gram으로 만든 벡터를 Fully connected하여 형태소를 분석 했습니다. Khaiii의 Base Window크기는 2, Embedding크기는 30으로 사용되었습니다.
한글의 경우 띄어쓰기가 지켜지지 않아도 의미 해석에 문제가 없는 경우가 많습니다. 이런 이유로 띄어쓰기가 정확하게 지켜지지 않는 경우가 많아 텍스트 데이터로 사용하기가 어렵습니다. PyKoSpacing은 띄어쓰시가 되어 있지 않은 문장을 띄어쓰기가 되어 있는 문장으로 바꿉니다.
띄어쓰기 뿐 아니라 맞춤법도 교정해주는 패키지도 존재합니다. 네이버 한글 검사기를 바탕으로 만들어진 패키지로 위의 예시와 같이 사용할 수 있습니다.
soynlp는 주어진 데이터의 패턴속에서 띄어쓰기, 토크나이즈 등을 학습합니다. 단어를 형태소로 예측할지 말지를 근거가 되는 것에 통계적인 수치를 사용합니다. Cohesion probability와 Branching entropy가 가장 중요한 통계 방법입니다. 먼저 Cohesion probability의 예시를 보겠습니다. '연합뉴스'라는 단어가 있을 떄 연 = \(c_1\), 합 = \(c_2\), 뉴 = \(c_3\), 스 = \(c_4\)라고 하겠습니다. cohesion(2)는\(P(C_{1:2}|C_{1:1})\)으로 P(연합|연)입니다. cohesion(3)는\(\sqrt{P(C_{1:3}|C_{1:2}}\)으로 \(\sqrt{P(연합뉴|연합)*P(연합|연)}\)입니다. 연 -> 연합의 확률이 0.19, 연합뉴 -> 연합뉴스의 확률이 0.57, 연합뉴스 -> 연합뉴스는의 확률이 0.15라고 하면, 모델은 연합뉴스를 하나의 형태소로 구분할 수 있게 됩니다. Branching entropy에 대해 알아보겠습니다. 확률분포 A와 B가 있다고 가정하겠습니다. A는 일정한 확률변수를 가진 확률분포이고 B는 확률변수의 폭이 큰 경우라면 Entropy(A) > Entropy(B)입니다. 예를 들어 "연합뉴" 다음에 "스"가 나올 확률이 높고 다른 문자가 나올 확률은 낮을 것입니다. 이 경우는 엔드로피가 낮을 것입니다. 반면 "연합뉴스" 다음에 나올 문자에 대한 확률은 "도", "는", "가" 등 여러 단어가 가진 확률이 비슷하여 엔드로피가 높을 것입니다. 따라서 엔드로피가 높을수록 이전 단어는 하나의 형태소라고 예측할 것입니다.