본문 바로가기

NLP/전처리

[전처리] 문자열 유사도 측정 (difflib)

이런 분들께

 

  • semantic similarity 가 아닌 apparent similarity 를 측정해야 할 때
  • 즉, '안녕하세요' 와 '단념하세요' 와 같은 문장의 유사도도 측정해보고 싶을 때

(위 예시를 보면 아실 수 있듯이, 의미 유사도를 측정이 아닌 점을 미리 밝힙니다.)

 

 

 

 

한국어도 보다 정밀하게 써보고 싶다면?

 

https://github.com/goonbamm/korean_apparent_similarity

 

GitHub - goonbamm/korean_apparent_similarity: To score apparent similarity between korean texts

To score apparent similarity between korean texts. Contribute to goonbamm/korean_apparent_similarity development by creating an account on GitHub.

github.com

 

 


 

영어 유사도

 

영어로 측정한다면, 아래 예시만 봐도 다양하게 활용할 수 있다. 영어는 글자 단위 자체가 알파벳이 전부라서 쉽다.

  • str1: Preserve (보존하다)
  • str2: Persevere (인내하다)
from difflib import SequenceMatcher

str1 = 'Preserve'
str2 = 'Persevere'

ratio = SequenceMatcher(None, str1, str2).ratio()
print(ratio)

 

한글에선 부가적인 작업이 필요하다

 

하지만, 한글로 한다면 이로서는 부족하다. 한글로 하면, 다음과 같은 문제가 생긴다.

  • 문제: '알' 와 '악' 의 유사도는 '알' 과 '초'의 유사도보다 높아야 한다. 실제론 그렇지 않다.
  • 원인: 하지만 유니코드상에선, '알'이나 '악'이나 '초'나 다 다르게 표현되기 때문이다.
  • 해결 방안: 완벽한 해결 방안은 아니다. 하지만 훨씬 낫다. 바로 초성/중성/종성을 분리하는 것이다. 한글을 마치 알파벳 단위처럼 분리하는 것이다.

 

하지만 직접 분리하는 것은 부담스럽다. 그래서 우리는 오픈 소스, github 을 사용해야 한다. 아래 굉장히 편리하면서도 간결하게 잘 정리해주셨다. 코드를 직접 보는 데, 5분도 안 걸릴 것이다.

 

https://github.com/neotune/python-korean-handler

 

GitHub - neotune/python-korean-handler: python3.x 에서 작동하는 한글 초성, 중성, 종성 분해

python3.x 에서 작동하는 한글 초성, 중성, 종성 분해. Contribute to neotune/python-korean-handler development by creating an account on GitHub.

github.com

 

 

 

2개 이상의 자음과 모음이 결합된 경우

 

그런데 해당 코드를 보면 알 수 있지만, 우리의 목적을 위해선 마지막으로 부가적인 작업을 추가해야 할 수 있다.

 

  • 1. 된소리: '짜장면' 과 '자장면'의 유사도는 '짜장면'과 '간장면'의 유사도보다 높아야 한다. 하지만, 유니코드 상으로는 'ㅉ' 과 'ㅈ'이 유사한지 알 수 없다.
  • 2. 이중 종성: '닭고기' 와 '닥고기'의 유사도가 '닭고기'와 '닾고기' 보다 높길 기대한다. 하지만, 유니코드 상으로는 'ㄺ' 이나 'ㄱ' 이나 'ㅍ' 은 그냥 서로 다를 뿐이다.
  • 3. 이중 모음: '쇠고기' 와 '소고기'의 유사도가 '쇠고기'와 '수고기'의 유사도보다 높길 바란다. 하지만, 유니코드 상으로는 'ㅚ' 와 'ㅗ' 나 'ㅜ' 는 다 다를 뿐이다.

 

실제 아래 코드에서도 2개 이상의 자음과 모음이 결합된 형태에 대해선 분리하지 않는다.

 초성 리스트. 00 ~ 18
CHOSUNG_LIST = ['ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ']

# 중성 리스트. 00 ~ 20
JUNGSUNG_LIST = ['ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ', 'ㅔ', 'ㅕ', 'ㅖ', 'ㅗ', 'ㅘ', 'ㅙ', 'ㅚ', 'ㅛ', 'ㅜ', 'ㅝ', 'ㅞ', 'ㅟ', 'ㅠ', 'ㅡ', 'ㅢ', 'ㅣ']

# 종성 리스트. 00 ~ 27 + 1(1개 없음)
JONGSUNG_LIST = [' ', 'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄹ', 'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅁ', 'ㅂ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ']

 

그러므로 직접 용도에 맞게 분리해보면 좋다. 하지만, 늘 분리 후에 우리가 원하는 대로 유사도 값이 나오는지 잘 봐야 한다. 애초에 점수 측정 알고리즘엔 순서, 공백 등 도 영향을 주고 있다. 그러므로, 다양한 형태로 유사도를 측정해보고 그에 맞게 개량하는 것이 가장 중요하다고 말할 수 있겠다.

 

그래서 직접 만들어봤으니, 사용해보실 분들은 사용해봐도 좋을 듯 하다.

 

https://github.com/goonbamm/korean_apparent_similarity

 

GitHub - goonbamm/korean_apparent_similarity: To score apparent similarity between korean texts

To score apparent similarity between korean texts. Contribute to goonbamm/korean_apparent_similarity development by creating an account on GitHub.

github.com