+ 개발

단어 임베딩을 활용한 유사도 계산

AI.Logger 2024. 9. 9. 00:20
  • 수업 내용 리마인드 및 아카이빙 목적의 업로드


 

자연어 처리에서 텍스트의 유사도를 측정하는 것은 매우 중요한 작업이에요. 단어 임베딩을 통해 벡터로 변환된 단어들 사이의 거리를 측정하면, 단어들이 얼마나 비슷한지 계산할 수 있습니다. 이번 글에서는 유클리디안 거리, 자카드 유사도, 코사인 유사도를 계산하는 방법을 단계별로 알아봐요.

 

1. 유클리디안 거리 (Euclidean Distance)

유클리디안 거리는 두 벡터 사이의 직선 거리를 의미합니다. 즉, 두 점 사이의 최단 거리를 구하는 방법이죠. 벡터 간의 차이를 계산한 후, 그 차이의 제곱을 더하고 루트를 취하면 유클리디안 거리가 나옵니다.

 

* 유클리디안 거리 계산 코드 예시

import numpy as np

# 단어 임베딩 사전
word_embedding_dic = {
    '사과': [1.0, 0.5],
    '바나나': [0.9, 1.2],
    '원숭이': [0.5, 1.5]
}

# 유클리디안 거리 계산 함수
def euclidean_dist(x, y):
    x = np.array(x)
    y = np.array(y)
    return np.sqrt(np.sum((x - y) ** 2))

# 사과와 바나나의 유클리디안 거리 계산
print(f"사과와 바나나의 유클리디안 거리: {euclidean_dist(word_embedding_dic['사과'], word_embedding_dic['바나나']):.4f}")

위 코드에서는 사과와 바나나의 유클리디안 거리를 계산하고 그 결과는 0.7071입니다. 두 단어의 벡터 간의 거리가 가까울수록 두 단어가 유사하다는 것을 의미해요.

 

2. 자카드 유사도 (Jaccard Similarity)

자카드 유사도는 두 집합 사이의 유사도를 측정하는 방법입니다. 두 집합의 교집합합집합으로 나누어 계산해요. 텍스트에서 자카드 유사도를 계산할 때는, 각 문장을 단어로 나누어 두 집합 간의 유사도를 계산합니다.

 

* 자카드 유사도 계산 코드 예시

# 두 문장
s1 = '대부분 원숭이는 바나나를 좋아합니다.'
s2 = '코주부 원숭이는 바나나를 싫어합니다.'

# 토큰화
token_s1 = s1.split()
token_s2 = s2.split()

# 교집합과 합집합
union = set(token_s1).union(set(token_s2))
intersection = set(token_s1).intersection(set(token_s2))

# 자카드 유사도 계산
jaccard_similarity = len(intersection) / len(union)
print(f"자카드 유사도: {jaccard_similarity:.4f}")

이 코드에서는 두 문장의 자카드 유사도를 계산합니다. 교집합에는 ['바나나를', '원숭이는']이 포함되고, 합집합에는 총 6개의 단어가 있어, 자카드 유사도는 0.3333입니다.

 

3. 코사인 유사도 (Cosine Similarity)

코사인 유사도는 두 벡터가 이루는 각도를 바탕으로 유사도를 측정하는 방법입니다. 벡터가 이루는 각도가 작을수록 유사도가 높아지고, 두 벡터가 같은 방향에 있을 때 유사도는 1에 가까워집니다. 반면, 90도일 때는 0, 반대 방향일 때는 -1에 가까워집니다.

 

* 코사인 유사도 계산 코드 예시

# 단어 임베딩 사전
word_embedding_dic = {
    '사과': [1.0, 0.5],
    '바나나': [0.9, 1.2],
    '원숭이': [0.5, 1.5]
}

# 코사인 유사도 계산 함수
def cosine_similarity(x, y):
    nominator = np.dot(x, y)  # 두 벡터의 내적
    denominator = np.linalg.norm(x) * np.linalg.norm(y)  # 벡터 크기의 곱
    return nominator / denominator

# 코사인 유사도 계산 예시
print(f"사과와 바나나의 코사인 유사도: {cosine_similarity(word_embedding_dic['사과'], word_embedding_dic['바나나']):.4f}")
print(f"사과와 원숭이의 코사인 유사도: {cosine_similarity(word_embedding_dic['사과'], word_embedding_dic['원숭이']):.4f}")
print(f"바나나와 원숭이의 코사인 유사도: {cosine_similarity(word_embedding_dic['바나나'], word_embedding_dic['원숭이']):.4f}")

위 코드에서는 사과와 바나나의 코사인 유사도는 0.8944, 사과와 원숭이는 0.7071, 바나나와 원숭이는 0.9487로 계산됩니다. 값이 1에 가까울수록 두 벡터(단어)의 유사도가 높다는 것을 의미합니다.

 

 

* Scikit-learn을 사용한 코사인 유사도 계산

코사인 유사도를 계산할 때는 Scikit-learn의 cosine_similarity 함수를 사용할 수도 있어요. Scikit-learn을 활용하면 계산이 더 간편해집니다.

from sklearn.metrics.pairwise import cosine_similarity

# 사과와 바나나의 코사인 유사도
cos_sim_ab = cosine_similarity([word_embedding_dic['사과']], [word_embedding_dic['바나나']])[0][0]
print(f"사과와 바나나의 코사인 유사도: {cos_sim_ab:.4f}")

# 사과와 원숭이의 코사인 유사도
cos_sim_am = cosine_similarity([word_embedding_dic['사과']], [word_embedding_dic['원숭이']])[0][0]
print(f"사과와 원숭이의 코사인 유사도: {cos_sim_am:.4f}")

이 코드에서는 Scikit-learn의 cosine_similarity 함수를 사용하여 코사인 유사도를 계산하고, 그 결과는 앞선 결과와 동일하게 나타납니다.

 

 

이 글에서는 유클리디안 거리, 자카드 유사도, 코사인 유사도 세 가지 방법으로 단어 사이의 유사도를 계산하는 방법을 알아보았어요. 각각의 방법은 데이터의 특성과 분석 목적에 따라 적절히 선택하면 됩니다.

  • 유클리디안 거리는 직선 거리로 두 벡터 간의 차이를 계산하는 방법이에요.
  • 자카드 유사도는 두 집합의 유사도를 계산할 때 유용하며, 교집합과 합집합을 이용해 계산합니다.
  • 코사인 유사도는 벡터 간의 각도를 바탕으로 유사도를 측정해, 방향성을 고려한 유사도 분석에 적합합니다.