두 텍스트 간의 유사도를 산출하는 고전적인 방법에는 텍스트 내의 단어 빈도를 가지고 벡터를 구축하여, 벡터 간 코사인 유사도를 구하는 것이 있습니다. 이 방법의 장점은 다른 어떤 언어학적 기법을 도입하지 않아도 (기껏해야 Stemming 정도만 하면 충분하죠) 단어 빈도만 세어서 꽤나 훌륭한 결과를 얻을 수 있다는 것입니다. 그런데 이런 통계적인 방법이 통하려면 해당 텍스트가 충분히 길어야한다는 조건이 필요하죠. 그렇지 않을 경우 텍스트로부터 만들어진 벡터가 희소(sparsity)하게 되어, 좋은 결과를 얻을 수 없게 됩니다. 그렇기 때문에 짧은 텍스트에 대해서는 조금 다른 방법이 필요하게 됩니다.
이 글에서는 W Song, 2007, Question Similarity Calculation for FAQ Answering 의 논문을 바탕으로 (원시적이긴 하지만) 통계적 방법과 의미론적 방법을 모두 사용하여 짧은 텍스트에 대한 유사도를 계산하는 방법에 대해 소개합니다. 사실 정말 어려울거 없는 간단한 방법이에요.
이는 고전적인 벡터 유사도 방법과 정확하게 일치합니다. 두 단문 내에서 불용어를 제거하고 스테밍을 진행한 후, 남은 단어를 벡터의 성분으로 사용합니다.
논문에서 예로 든 두 문장을 그대로 가져와서 사용해보겠습니다.
Q1: What is the color of rose?
Q2: What color is the Yangzte River?
논문에서는 문장의 구조를 살필수 있도록 of, is 같은 단어는 남겼다고 합니다.
what | is | color | of | rose | yangzte | river | |
---|---|---|---|---|---|---|---|
Q1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 |
Q2 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
그러면 위와 같이 문장을 벡터로 만들수 있고, 코사인 유사도를 쉽게 계산할 수 있겠죠.
계산해보면 Sim(Q1, Q2) = 0.6 이 됩니다.
의미적 유사도를 산출하기 위해서 이 논문에서는 WordNet 거리를 이용했습니다. WordNet에는 단어를 유의어 목록을 가지고 네트워크로 연결한 시스템입니다. A-B가 유의어고, B-C도 유의어라고 할때, A-B의 WordNet Distance는 1, B-C의 WordNet Distance도 1, A-C의 WordNet Distance는 2가 되겠죠. (예전 싸이월드 미니홈피의 촌수 따지는 것과 정확하게 같은 개념입니다.) 한 단어가 다른 단어로 연결되는 길이 여러가지가 있을때에는 가장 짧은 길을 두 단어의 WordNet 거리로 정의하구요. 이 WordNet거리는 두 단어가 얼마나 의미론적으로 유사한지 확인하는데 쓸 수 있습니다. WordNet 거리의 역수를 취하면 WordNet 유사도가 됩니다. (이 때 유사도는 두 단어가 가장 가장 가까울때 1, 무한히 멀 경우 0이 되죠)
논문에서 제시한 방법은 다음과 같습니다.
먼저 Q1의 단어를 가지고 Q2와 워드넷 유사도를 계산해보겠습니다.
color | yangzte | river | MAX | |
---|---|---|---|---|
color | 1 | 0.1 | 0.111 | 1 |
rose | 0.333 | 0 | 0.083 | 0.333 |
AVG(MAX) | 0.667 |
Q1의 각 단어들과 Q2의 유사도 평균은 0.667 입니다.
이번에는 방향을 바꿔서 Q2의 각 단어들과 Q1의 유사도 평균을 구해보지요.
color | yangzte | river | AVG(MAX) | |
---|---|---|---|---|
color | 1 | 0.1 | 0.111 | |
rose | 0.333 | 0 | 0.083 | |
MAX | 1 | 0.1 | 0.111 | 0.403 |
0.403이네요. 두 유사도의 평균을 구하면 0.535가 됩니다. 최종적으로 이 값이 짧은 텍스트 Q1, Q2의 의미적 유사도가 됩니다.
통계적 유사도와 의미적 유사도를 섞어서 최종 유사도를 산출해내야하는데, 단순히 반반 섞는것보다는 실험을 통해 어떤 비중이 좋을지 살펴봐야겠지요. 논문의 결과에 따르자면, 500개의 질문쌍을 대상으로 실험을 진행해본 결과, 의미적 유사도에 0.7의 가중치, 통계적 유사도에 0.3의 가중치를 주어서 합쳤을때, S@1 = 64.3%로 가장 높은 성능을 보였다고 합니다. 통계적 유사도나 의미적 유사도 단일을 사용했을때보다는 7~14% 정도의 성능향상이 있었구요.
논문에서는 이 방법을 짧은 질문 문장의 유사도를 계산하는데에 사용했지만, 이는 꼭 질문이 아니라도 다른 짧은 텍스트에도 적용할 수 있겠죠. 단순한 방법이라 적용하는 것도 그렇게 어렵지 않겠구요.
하지만 너무 단순한 모델이라는 생각도 들었습니다. 단순히 의미적 유사도와 통계적 유사도를 따로 구해서 합치는 것이 아니라, 두 개념을 통합하여 함께 적용해 유사도를 산출하면 더 나은 결과를 얻을수 있지 않을까요. 구체적으로 적자면, 단어 등장 빈도는 통계적 유사도 계산에서만 쓰이고, 워드넷 거리는 의미적 유사도 계산에서만 쓰이는데, 코사인 유사도 방식을 확장하여, 빈도 수에 워드넷 거리를 반영하거나, 혹은 거꾸로 의미적 유사도 평균을 구할 때 단어의 빈도나 TF-IDF같은 가중치를 주어서 평균을 구한다면 훨씬 진보된 모델이 나오지 않을까 생각해봅니다.
그래서 통합된 모델이 있나 살펴봤는데, Y Li, 2006, Sentence Similarity Based on Semantic Nets and Corpus Statistics 논문에서 힌트를 얻을 수 있었습니다. 이 논문에서는 의미 벡터끼리의 유사도와 어순 벡터끼리의 유사도를 이용해 전체 유사도를 만드는 방법을 제시했는데, 바로 윗 문단에서 얘기했던 통합한 모델이 바로 딱 이 것이 아닐까 싶네요. (매우 흡족). 세부적인 부부에서는 빈도수 대신 정보량을 이용하고, 의미 유사도 계산에도 지수 및 다른 시그모이드 함수를 사용한다는 차이점이 있지만, 이런것은 생략하고 큰 맥락만 소개합니다.
핵심은 의미 벡터(Semantic Vector)를 생성하는데에 있습니다. 일반적인 벡터 모형에서 각 단어의 빈도수를 벡터의 성분으로 입력했다면 여기에서는 빈도수에 의미적 유사도를 반영하여 입력합니다. 해당 텍스트 내에 일치하는 단어가 있다면 그 성분의 값은 1이 되고, 일치하는 단어가 없다면 텍스트 내 존재하는 단어 중 가장 의미적으로 유사한 단어의 유사도 값이 되도록하는 겁니다. 여기서 유사도 값이 특정 수치보다 큰 경우만 입력되게 하고 나머지 경우에는 0으로 설정하도록 threshold를 잡을 수도 있습니다. 이렇게 threshold를 도입하면 threshold가 1이 되면 전통적인 벡터 모델과 일치하게 되고, 0이 되면 완전하게 의미 벡터 모델이 되는것이죠.
위에서 든 것과 같은 예제 문장을 들어보겠습니다. 먼저 Q1의 의미벡터는 다음과 같이 생성됩니다.
what | is | color | of | rose | yangzte | river | |
---|---|---|---|---|---|---|---|
what | 1 | ||||||
is | 1 | ||||||
color | 1 | 0.1 | 0.111 | ||||
of | 1 | ||||||
rose | 1 | 0.083 | |||||
MAX(X) | 1 | 1 | 1 | 1 | 1 | 0.1 | 0.111 |
what, is, color, of, rose 같은 경우는 Q1에 일치하는 단어가 있으므로 그대로 1의 값이 될것이고, yangzte와 river는 일치하는 단어가 없으므로 다른 단어들과의 유사도를 계산해 유사도가 가장 큰 값을 벡터 성분으로 취합니다. 따라서 Q1의 의미 벡터는 SQ1은 다음과 같게 됩니다. (설명을 위해 Threshold = 0으로 잡았습니다.)
SQ1 = [1, 1, 1, 1, 1, 0.1, 0.111]
마찬가지로 Q2에 대해서도 같은 것을 반복합니다.
what | is | color | of | rose | yangzte | river | |
---|---|---|---|---|---|---|---|
what | 1 | ||||||
color | 1 | 0.333 | |||||
is | 1 | ||||||
yangzte | 1 | ||||||
river | 0.083 | 1 | |||||
MAX(X) | 1 | 1 | 1 | 0 | 0.333 | 1 | 1 |
SQ2 = [1, 1, 1, 0, 0.333, 1, 1] 이 됩니다. 여기에서는 각 단어의 등장횟수가 모두 1이라서 숫자가 저렇게 나왔지만, 빈도가 1 이상인 경우 각 성분에 빈도를 곱해주면 되겠죠. TF-IDF로 가중치를 주는 것도 좋은 방법일듯합니다. (다만 이 논문에서는 해당 단어와 가장 유사한 단어의 정보량의 곱을 가중치로 주었습니다.)
이제 예전에 하던것처럼 SQ1 과 SQ2의 코사인 유사도를 구하면 됩니다. 그 값은 약 0.699이네요. 기존 벡터 모델에서의 유사도 0.6보다 약 0.1 정도 높은 수치네요. 그 이유는 기존 모델에서는 전혀 다른 단어로 처리되던(즉, 의미적 유사도 = 0으로 가정하던) rose, yangzte, river간의 의미 유사도 정보가 반영되었기 때문입니다. 유의 단어가 많거나, 전반적으로 단어 빈도가 낮아 sparsity가 높은 텍스트 간의 비교에 사용하면 적합하겠죠.
[네트워크 이론] 결집계수(Clustering Coefficient) (1) | 2017.03.17 |
---|---|
[네트워크 이론] 다양한 중심성(Centrality) 척도들 (2) | 2017.03.15 |
TextRank 기법을 이용한 핵심 어구 추출 및 텍스트 요약 (14) | 2017.02.20 |
코퍼스를 이용하여 단어 세부 의미 분별하기 (0) | 2017.02.07 |
상호정보량(Mutual Information) (7) | 2017.01.18 |
Word2Vec을 이용한 한국어 관련어 추출과 평가 (3) | 2017.01.15 |
댓글 영역