정보공간_1

[7기 신촌 박진상] 기계학습 #4 - TF-IDF를 이용한 유사도 측정 본문

IT 놀이터/Elite Member Tech & Talk

[7기 신촌 박진상] 기계학습 #4 - TF-IDF를 이용한 유사도 측정

알 수 없는 사용자 2015. 5. 23. 12:04

안녕하세요. 엘리트 7기 신촌 멤버십의 박진상입니다.

이번 시간에는 지난번에 이어서 TF-IDF 알고리즘의 구현과 구현된 TF-IDF를 이용해서 문서간 유사도를 측정하는 프로그램을 만들어보겠습니다.

먼저 TF-IDF 공식을 복습한 다음 코드로 옮기겠습니다.



TF 값은 해당 텍스트가 얼마나 해당 문서 내에서 많이 등장하는 지를 나타내고, IDF 값은 해당 텍스트가 얼마나 문서 내에서 다른 문서들에 비해 희귀한지, 즉 다른 문서가 아닌 이 문서의 특징적인 키워드인지를 나타내줍니다. 그럼 이번에도 역시 파이썬을 이용해서 코드로 옮겨보겠습니다.

가장 먼저 지난번에 만들었던 ngram 함수를 수정하겠습니다. Ngram 알고리즘이 N글자 단위로 Tokenize를 수행했다면, 이번엔 단어 단위로 문서를 쪼개는 Wordgram이라는 함수를 만들고, 단어에 대한 Dictionary 를 반환하도록 하겠습니다.



이제 문서에 대해서 단어를 기준으로 빈도수를 분석한 하나의 사전이 완성되었습니다. 그렇다면, 이제 TF-IDF 공식을 적용하는 건 어렵지 않습니다. 공식 그대로 구현하겠습니다.



쉽죠? tf_value 함수에서는 문서에 대한 해당 단어의 TF값을 구하고, 상위 함수인 tf_analyze 함수에서는 파일 내의 단어들에 대해 TF 값들을 모두 구한 정렬된 Dictionary를 반환합니다.

(* OrderedDict 는 파이썬의 내장 모듈이 제공하는 Dictionary 타입의 클래스로, 일정한 형태의 결과를 반환합니다. 코드에서는 Sort 함수와 람다식을 통해서 안의 값들을 정렬한 모습입니다.)

IDF 값을 정확히 구하기 위해서는 문서 Set이 좀 더 필요합니다. 따라서 구텐베르크 프로젝트(https://www.gutenberg.org/) 에서 역시 문서를 더 수집하고, 공식을 코드로 옮깁니다.





코드는 루트 디렉토리를 잡고, 그 안의 문서들에 대해 IDF를 적용하는데, 폴더 내 문서들의 값 대비 해당 문서의 IDF 값을 구하는 방식으로 구현되었습니다. 역시 idf_analyze 함수의 결과는 해당 문서 내의 단어들에 대한 IDF 값을 구한 정렬된 Dictionary를 반환합니다.

이제 TF-IDF를 구하기 위해서는 값들을 곱해주면 되겠죠? 다음은 샘플 TF-IDF값의 상위 20개의 결과입니다. 샘플로 이상한 나라의 앨리스와 아서왕 이야기, 빨간모자 그리고 Men of Iron 이라는 소설의 TF-IDF 값들을 확인해보겠습니다. 결과는 조금 다를 수 있고 노이즈를 제거해야 할 수도 있습니다. :-) (무엇보다 불용어를 제거하지 않았기 때문에 노이즈가 심합니다 ^_^ 예제를 따라 하시는 분이라면 꼭 불용어(Stop words)를 제거해주세요. 결과가 월등히 좋아집니다. :D)



해당 문서를 읽어보면, TF-IDF 상위 값들이 얼추 문서를 대변하고 있는 대표 키워드가 되고 있다는 사실을 알 수 있습니다. 물론 완벽하다고는 할 수 없겠지만 그래도 상당히 신빙성 있는 대표성을 지닙니다. 문서의 대표 텍스트들을 분석해냈으니 그냥 두기에는 조금 아깝습니다. 분석한 TF-IDF 값들을 가진 Dictionary를 벡터(Vector)로 간주하고, 좀 더 응용한 시스템을 만들어보겠습니다.

TF-IDF 가 높은 단어들은 문서의 아이덴티티(Identity)를 더 높게 반영한다고 할 수 있고, 따라서 이 값들이 유사하다면 유사한 문서라고 생각할 수 있습니다. 이를 이용해서 문서간 유사도를 측정해보겠습니다.

벡터간의 유사도를 측정하는 여러 방법이 있지만, 그 중 코사인 유사도(Cosine Similarity)라는 기법이 있습니다. 이 공식은 다음과 같이 두 벡터의 내적을 크기의 곱으로 나눈 값과 같습니다. 고등학교 수학에서 벡터 사이의 코사인 각도 구하는 공식과 같습니다.



그럼 이 유사도를 이용해서 문서간 유사도를 측정해보도록 하겠습니다. 시스템은 다음과 같이 구성됩니다. 비교할 문서들의 TF-IDF 값을 담은 Dictionary 자체를 벡터로 하면 문서간 코사인 유사도를 구할 수 있습니다.



즉 분자에는 공통된 부분의 Dot 곱이, 분모에는 각 Dictionary 벡터들의 크기가 들어가게 됩니다. 코드로 옮겨보겠습니다.





그러면 결과를 확인해보겠습니다. 저는 샘플 이외의 데이터 셋이 많기 때문에 샘플 4개간 비교 결과를 따로 엑셀로 정리해봤습니다. :-)




눈여겨 볼만한 점은 아더왕 이야기와 Men of Iron이라는 소설의 유사도가 상대적으로 월등히 높은것인데, Men of Iron 이라는 소설은 아더왕 이야기의 작가가 영국의 중세를 배경으로 쓴 소설이라고 하네요. 역시 기사들과 왕들의 이야기가 주를 이룬 다는 점을 감안하면, 예제로 간단히 만들어본 유사도 측정이 신뢰할 만하다고 할 수 있습니다.


물론, 각종 노이즈가 많고 단순한 모델이라 정확하다고는 할 수 없겠지만 간단하면서도 효과적으로 유사도를 측정하는 것을 볼 수 있습니다.

이렇게 문서의 대표값을 통해서 우리는 텍스트 마이닝의 다양한 활용을 할 수 있습니다