텍스트 데이터 전처리
오늘은 저번 시간에 소개한 것처럼 텍스트 데이터 전처리에 대해서 소개하려고 한다. 말 그대로 소개이니 가벼운 마음으로 "이런 개념이 있구나" 정도로 읽으면 좋을 것 같다. 왜냐하면 뒤에서 다시 중요한 기법에 대해서는 자세하게 다룰 예정이다. 즉, 오늘은 몸풀기로 예습을 한다고 생각하면 될 것이다.
전처리를 해야 하는 이유는 자연어에는 컴퓨터가 이해할 수 없는 많은 노이즈들이 존재하기 때문이다. 쉽게 말해 컴퓨터가 저장 공간이 크고 빠르다는 장점이 있지만 인지능력에 있어서는 인간에 비해서 아직 많이 부족하기 때문에 컴퓨터가 이해할 수 있도록 사전 작업을 해줘야 한다고 생각하면 될 것이다.
자연어를 전처리 한다는 것은 마냥 쉬운 일이 아니다. 한국어, 영어, 일본어, 중국어 등 모두 전처리를 하는 방식이 조금씩 다르다. 그리고 컴퓨터가 인식하기 힘든 노이즈들이 있다. 그리고 우리는 한국어를 사용하지만 안타깝게도 대부분의 AI 논문과 문서들은 영어로 되어있다. 그렇기에 지금은 영어를 기준으로 살펴보고자 한다.
더 많은 노이즈들이 있지만 지금은 단순히 개념을 이해하기 위한 목적으로 대표적인 노이즈 3가지만 소개하고 넘어가겠다.
문장부호 단어에 ,?!. 등이 결합되어 있는데 사람이야 이것을 보고 인식을 하지만 컴퓨터는 이런 부호들까지 합쳐서 단어로 인식해 버린다. 그렇기 때문에 문장부호 양쪽에는 공백을 추가해 줘야 한다.
대소문자 컴퓨터는 영어의 대문자와 소문자를 완전히 다른 문자로 구분 지어버릴 수 있다. 그렇기 때문에 보통 전처리 과정에서 모든 단어를 소문자로 바꾸는 방법을 사용한다.
특수문자 문자의 중간중간에 수많은 특수 문자들이 있다. 컴퓨터가 이를 단어로 인식해 버리면 문제가 정확한 모델을 만들 수 없게 된다. 그렇기 때문에 우리가 사용한 알파벳과 기호 혹은 한글을 사용하고는 모두 제거해 주는 전처리 작업을 거쳐야 한다.
토큰이란 문장을 특정한 기준으로 쪼개었을 때 만들어진 단어들을 의미하며 이러한 특정한 기준을 정하는 것이 Tokenization 기법이라고 한다. 토큰화를 하는 이유는 문장을 단어 단위로 정확하게 끊어서 의미를 파악하여 단어 단위로 쪼개는 분산 표현의 단점을 보완할 수 있다는 장점이 있다.
참고 : 분산 표현이란 Enbedding 레이어를 통해서 구현할 수 있으며 단어를 정확하게 파악할 수 있는 벡터 표현이다. 조금 더 설명을 덧붙이자면 두 단어 벡터 사이의 거리를 가깝게 하고, 그렇지 않은 단어들끼리는 멀어지도록 조금씩 조정해 주어 얻어지는 단어 벡터를 의미한다.
지금부터는 토큰화의 다양한 기법들을 살펴보도록 하겠다. 1) 공백 기반 토큰화 2) 형태소 기반 3) BPE 4) WPM 5) synlp 등이 있다.
말 그대로 문장을 공백(띄어쓰기) 기반으로 토큰화를 진행해 준다. 파이썬에서는 split() 함수를 사용하여 간단하게 구현할 수 있다. 하지만 한국어 문장은 복잡하기 때문에 공백을 기준으로 토큰화를 하면 성능이 좋지 못할 것이다.
형태소란 뜻을 가진 가장 작은 말의 단위이다. 즉 "내일도 운동만 한다" -> 내일, 도, 운동, 만, 한다로 쪼개는 것이다. 이를 통해서 공백 기반 토큰화의 단점을 보완할 수 있을 것이다. 한국어 형태소 분석기의 대표적인 라이브러리는 5가지의 분석 기법을 가진 KoNLPy가 있다.
KoNLPy공식 사이트 : https://konlpy-ko.readthedocs.io/ko/v0.4.3/
KoNLPy 성능비교 : https://iostream.tistory.com/144
위 두 개의 토큰화에는 치명적인 단점을 내포하고 있는데 바로 OVV 문제이다. OVV란 Out-Of-Vocabulary 즉, 새로 등장한 단어에는 약한 모습을 보인다. (3)부터는 OVV 문제를 극복한 기법들을 소개하고자 한다.
BPE는 가장 많이 등장하는 바이트 쌍을 새로운 단어로 치환하여 압축하는 작업을 반복한다. 모든 단어를 바이트들의 집합으로 취급하여 자주 등장하는 문자 쌍을 합치면 접두어나 접미어의 의미를 캐치할 수 있고 처음 등장하는 단어는 문장들의 조합을 나타내어 OVV 문제를 해결할 수 있다.
참고자료(논문) : https://arxiv.org/pdf/1508.07909.pdf
BPE 기반으로 변형해 구글에서 만든 알고리즘으로 BPE와 달리 공백 복원을 위해 단어의 시작 부분에 언더바를 추가하고 빈도수 기반이 아닌 가능도를 증가시키는 방향으로 문자 쌍을 합친다. 그리고 이 기법은 한국어 텍스트 처리도 고려하여 만들어졌다.
하지만 이 기법을 공개되지 않았기 때문에 대신 구글에서 만든 SentencePiece 라이브러리를 통해서 성능 높은 BPE를 사용할 수 있다.
참고자료(논문) : https://static.googleusercontent.com/media/research.google.com/ko//pubs/archive/37842.pdf
참고자료2(SentencePiece) : https://github.com/google/sentencepiece
한국어를 위해서 만들어진 토크나이저로 형태소 기반인 koNLPy의 단점을 해결하기 위해서 만들어졌다. 그리고 학습 데이터를 이용하지 않으면서 데이터에 존재하는 단어를 찾거나, 문장을 단어열로 분해, 혹은 판별을 할 수 있는 비지도 학습 접근법을 지향한다.
참고자료 : https://github.com/lovit/soynlp
위에서 배운 기법들은 모두 통계 기반 기법들을 소개한 것이다. 신경망을 활용하여 단어들끼리 유사도 연산을 할 수 있게 의미를 부여하는 알고리즘도 존재하는 데 이를 추론 기반 기법이라고 한다. 지금부터 대표적인 추론 기반 기법 3가지를 소개하겠다.
Word2Vec는 직역하면 "단어를 벡터로 만들다"이다. 조금 더 설명을 덧붙이자면 동시에 등장하는 단어끼리는 연관성이 있다는 아이디어에서 시작된 알고리즘이다.
그리고 Word2vec에는 크게 두 가지 모델이 있다. 첫 번째로는 주변에 있는 단어들을 입력으로 중간에 있는 단어들을 예측하는 CBOW(Continuous bag-of-words)이다. 두 번째는 중간에 있는 단어들을 입력으로 주변 단어들을 예측하는 Skip-gram이다.
그러면 이 둘 중 어떤 모델을 사용해야 할까? 통상적으로 skip-gram 모델을 사용해야 한다. 단어 분산 표현의 정밀도 면에서 skip-gram 모델의 결과가 더 좋은 경우가 많다. 특히 말뭉치가 커질수록 저빈도 단어나 유추의 성능 면에서 skip-gram 모델이 더 뛰어난 경향이 있다. 반면 학습 속도는 CBOW가 더 빠르다.
FastText는 Word2Vec의 연산의 빈부격차가 크다는 단점을 보완하기 위해 BPE와 비슷한 아이디어를 적용하여 고안된 방법이다. FastText의 특징은 한 단어를 n-gram의 집합이라고 보고 단어를 쪼개어 각 n-gram에 할당된 Embedding의 평균값을 구하여 기존 단어마다 Embedding을 할당하던 방식과 차이를 보인다는 것이다.
참고자료 : https://brunch.co.kr/@learning/7
ELMo는 단어의 의미 벡터를 구하기 위해 그 단어만 필요한 것이 아니라 그 단어가 놓인 주변 단어 배치의 맥락을 함께 고려한다는 개념인 Contextualized Word Embedding를 적용하였다. 그래서 위에 소개했던 Word Embedding 알고리즘의 동음이의어를 처리할 수 없다는 단점을 보완할 수 있다.