brunch

You can make anything
by writing

C.S.Lewis

by 이영민 Jul 01. 2016

R을 이용한 한글 띄어쓰기

with Hidden Markov Model

구글맵의 리뷰 데이터(한글)를 가져와서 형태소 분석을 통해 명사, 형용사, 동사, 부사만을 추출하는 작업을 하고 있다. 그런데 아무래도 자연어다 보니, 띄어쓰기가 전혀 되어 있지 않은 문장이 전체의 약 5.4% 정도를 차지했다(전체 222개 중 12개). '이 정도는 그냥 버려도 되겠지'라는 생각이 들기도 했으나, 지금이야 200여 개를 가지고 하지만 나중에 데이터 규모가 커지면 오류가 발생할 확률도 커질 것이고, 분석을 좀 더 정교하게 하고자 하는 욕심도 생기고, 해서 띄어쓰기 문제를 해결해 보기로 했다.


방법은, HMM(Hidden Markov Model)


유명한 확률 모델이다. 위키피디아를 찾아 보면 설명이 잘되어 있다. 내부 알고리즘에 대해서는 정확하게 이해하기 어려웠으나 영민한 사람들이 R을 이용하여 코딩을 해 놓은 것이 있어서 알고리즘에 대한 깊은 이해 없이도 사용해 볼 수 있었다(감사합니다). 코드에 대한 내용은 아래 두 개의 블로그를 참고하였다.


 http://freesearch.pe.kr/archives/2746

http://blog.naver.com/PostView.nhn?blogId=soccerball1&logNo=220000516152&parentCategoryNo=&categoryNo=&viewDate=&isShowPopularPosts=false&from=postView


위 블로그들에서도 나와 있듯이 HMM은 어떤 데이터(코퍼스)로 학습시키느냐에 따라서 결과가 많이 달라진다. 나도 최인훈의 '광장'과 '회색인'을 이용하여 학습시켜 보았다. 아래 결과를 보면, 완벽하진 않지만 되긴 된다. 혹시나 해서 해당 파일에 '아버지가 방에 들어가신다.'라는 문장을 넣어서 다시 학습시키고 난 후 돌려 보았는데, 그래도 결과는 똑같았다. 그런 식으로 작동하는 게 아닌가 보다.


HMM 실행 결과


기본 문장으로 테스트를 해 본 후에, 본격적으로 내가 수집한 구글맵 리뷰 데이터를 가지고 돌려 보니 두 가지 경우에 'subscript out of bounds'라는 에러가 발생한다는 것을 알 수 있었다.  


에러 발생 이유 1: 특정 음절 또는 단어가 코퍼스에 포함되어 있지 않은 경우


특히 '뷁', '젱', '읅' 같이 사전에 존재하지 않는 음절의 경우 100% 에러가 발생하며, '조깅', '소셜', 콘서트' 같은 외래어의 경우에도 에러가 발생한다. 또한 '^^', '~', '\n' 같은 특수문자가 음절에 포함되어 있을 때도 동일한 에러가 발생한다. 아래의 경우, '즹'이라는 음절을 빼고 돌리니까 에러가 발생하지 않았다.


HMM 알고리즘에서 에러가 발생하는 경우


에러 발생 이유 1에 대한 해결책: 'gsub'함수 이용


해결책은 비교적 간단하다. 'gsub' 함수를 이용해서 해당 음절, 단어, 또는 특수문자를 제거해 주면 된다. 다만, 다소 노가다 작업을 해야 할 뿐이다.


'gsub' 함수를 이용한 텍스트 전처리(일부)


에러 발생 이유 2: 문장 내에 한 군데라도 띄어쓰기가 되어 있는 경우


또한 기존 문장에 한 군데라도 띄어쓰기가 되어 있으면 'subscript out of bounds' 에러가 발생한다. 즉, 이 알고리즘에서는 input으로 사용할 문장에 띄어쓰기가 한 군데라도 되어 있으면 안 된다는 얘기다. 이 에러는 꽤 크리티컬하다. 내가 가지고 있는 데이터는 띄어쓰기가 되어 있는 문장과 띄어쓰기가 전혀 되어 있지 않은 문장들이 섞여 있기 때문이다. 따라서 이 알고리즘을 제대로 돌릴 수가 없었다.


띄어쓰기가 되어 있는 경우 에러 발생


에러 발생 이유 2에 대한 해결책: 코딩!


이 크리티컬한 문제를 해결하고자 코드를 짰다. 논리는 간단하다. 'str_detect' 함수를 이용해서 해당 문장에 띄어쓰기가 전혀 되어있지 않은 문장을 찾아 그 경우에만 HMM 알고리즘을 적용시키도록 한 것이다.

 

띄어쓰기가 안 되어 있는 문장에만 HMM을 적용하도록 함


위 코드로 돌리는데 계속 'subscript out of bounds' 에러가 나서, 해당 문장을 확인해 보면 역시나 이상한 음절이 있거나, 외래어가 있거나, 특수문자가 있거나 또는 자음만 나열된 문장들이 포함되어 있기 때문이었다. 이것들을 일일이 'gsub' 함수로 제거하고 나서야 최종적으로 성공할 수 있었다.


그러나 이것만으로는 부족하다.


왜냐하면 위 방법은 띄어쓰기가 전혀 되어 있지 않은 문장에만 적용 가능하기 때문이다. 띄어쓰기가 한 번이라도 되어 있는 문장은 위 코딩을 적용할 수가 없다. 그래서 비슷한 연구를 하는 연구실 후배와 함께 다시 코드를 짜 보았다. 역시나 논리는 간단하다. raw 데이터에 대해서 공백 단위로 어절을 분리해 내고, 각 어절(음절의 개수가 1개 이상인)에 대하여 HMM을 적용한 후, 이들을 다시 하나의 문장으로 합치는 것이다.


HMM 제대로 적용하기


HMM을 이용한 띄어쓰기가 절대적으로 훌륭한 방법은 아니다. 앞에서도 얘기했듯이 어떤 코퍼스로 훈련을 시키냐에 따라 분석 결과가 많이 달라지기 때문이다. 따라서 고퀄의 코퍼스를 이용하여 훈련을 시키는 방법과, 'subscript out of bounds' 에러를 좀 더 스마트하게 해결할 수 있는 방법에 대해 고민해 봐야 한다.



(제목 배경 이미지 출처)

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari