유사도 측정(코사인 유사도**(Cosine Similarity))**

<aside> 💡 두 벡터 간의 코사인 각도를 이용하여 구할 수 있는 두 벡터의 유사도를 의미함.

두 벡터의 방향이 완전히 동일한 경우에는 1의 값을 가지며, 90°의 각을 이루면 0, 180°로 반대의 방향을 가지면 -1의 값을 갖게됨. 즉, 결국 코사인 유사도는 -1 이상 1 이하의 값을 가지며 값이 1에 가까울수록 유사도가 높다고 판단할 수 있음. 이를 직관적으로 이해하면 두 벡터가 가리키는 방향이 얼마나 유사한가를 의미한다.

</aside>

Untitled

$$ \text{Cosine Similarity}(\vec{A}, \vec{B}) = \frac{\vec{A} \cdot \vec{B}}{|\vec{A}| |\vec{B}|} $$

1. sentence-transformers/xlm-r-100langs-bert-base-nli-stsb-mean-tokens

# SentenceTransformer를 사용하여 워드 임베딩을 수행합니다.
model = SentenceTransformer('sentence-transformers/xlm-r-100langs-bert-base-nli-stsb-mean-tokens').to('cuda')
embeddings = model.encode(df_cleaned['전체_정제'].tolist())
# 사용자 입력을 받습니다.
user_input = input("어떤 판례를 원하십니까? 구체적으로 말씀해주세요:")
## Q: 선거 자금 횡령
# 사용자 입력도 동일한 전처리와 워드 임베딩을 수행합니다.
user_input_cleaned = clean_text_with_mecab(user_input)
user_keyword_embedding = sentence_model.encode([user_input], convert_to_tensor=True)
from sklearn.metrics.pairwise import cosine_similarity

# 사용자 키워드 임베딩과 모든 판례 임베딩 간의 코사인 유사도 계산
similarity_scores = cosine_similarity(
    user_keyword_embedding.cpu().numpy(), # 사용자 키워드 임베딩을 CPU로 옮기고 NumPy 배열로 변환
    embeddings # 모든 판례 임베딩을 CPU로 옮기고 NumPy 배열로 변환
)

# 유사도 점수를 기반으로 상위 N개 판례 추천
N = 5 # 추천할 판례의 수
top_indices = similarity_scores.argsort()[0][-N:][::-1] # 가장 유사도가 높은 상위 N개 인덱스

# 상위 N개의 유사한 판례 출력 (여기서는 인덱스만 출력, 실제 환경에서는 해당 인덱스로 데이터를 조회하여 전문 제공)
for index in top_indices:
    print(f"판례 {index}와의 유사도: {similarity_scores[0][index]}")
    # 올바른 방법으로 데이터를 조회하여 전문 출력
    print("가장 유사한 문서 전문:", df.iloc[index]['전문'])

<aside> 💡 판례 44488와의 유사도: 0.5475528240203857

판례 73044와의 유사도: 0.4675711393356323

판례 11697와의 유사도: 0.44645342230796814

판례 47069와의 유사도: 0.438584566116333

판례 37488와의 유사도: 0.4262749254703522

</aside>

$$ \text{유사도 평균} = \frac{1}{N} \sum_{i=1}^{N} \text{유사도}_i $$

$$

\text{유사도 평균} = \frac{1}{5} (0.5475528240203857+ 0.4675711393356323 + 0.44645342230796814+ 0.438584566116333+ 0.4262749254703522)

$$

$$ 결과: 0.4653 $$

2. snunlp/KR-Medium

from transformers import AutoTokenizer, AutoModel
from sentence_transformers import SentenceTransformer, models
import torch

# CUDA 사용 설정 (GPU 사용을 위해)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# KR-BERT 모델과 토크나이저 로드
tokenizer = AutoTokenizer.from_pretrained("snunlp/KR-Medium")
bert_model = AutoModel.from_pretrained("snunlp/KR-Medium").to(device)

# SentenceTransformer에 사용하기 위한 모델 구성
word_embedding_model = models.Transformer("snunlp/KR-Medium")
pooling_model = models.Pooling(word_embedding_model.get_word_embedding_dimension(),
                                pooling_mode_mean_tokens=True,
                                pooling_mode_cls_token=False,
                                pooling_mode_max_tokens=False)

# SentenceTransformer 모델 생성 및 GPU로 이동
sentence_model = SentenceTransformer(modules=[word_embedding_model, pooling_model]).to(device)

# DataFrame에서 문장 리스트 추출
sentences = df_cleaned['전체_정제'].tolist()

# 문장 벡터 생성
sentence_embeddings = sentence_model.encode(sentences, convert_to_tensor=True)
# 사용자 입력을 받습니다.
user_input = input("어떤 판례를 원하십니까? 구체적으로 말씀해주세요:"))
# 사용자 입력도 동일한 전처리와 워드 임베딩을 수행합니다.
user_input_cleaned = clean_text_with_mecab(user_input)
user_keyword_embedding = sentence_model.encode([user_input], convert_to_tensor=True)
from sklearn.metrics.pairwise import cosine_similarity

# 사용자 키워드 임베딩과 모든 판례 임베딩 간의 코사인 유사도 계산
similarity_scores = cosine_similarity(
    user_keyword_embedding.cpu().numpy(), # 사용자 키워드 임베딩을 CPU로 옮기고 NumPy 배열로 변환
    sentence_embeddings.cpu().numpy() # 모든 판례 임베딩을 CPU로 옮기고 NumPy 배열로 변환
)

# 유사도 점수를 기반으로 상위 N개 판례 추천
N = 5 # 추천할 판례의 수
top_indices = similarity_scores.argsort()[0][-N:][::-1] # 가장 유사도가 높은 상위 N개 인덱스

# 상위 N개의 유사한 판례 출력 (여기서는 인덱스만 출력, 실제 환경에서는 해당 인덱스로 데이터를 조회하여 전문 제공)
for index in top_indices:
    print(f"판례 {index}와의 유사도: {similarity_scores[0][index]}")
    # 올바른 방법으로 데이터를 조회하여 전문 출력
    print("가장 유사한 문서 전문:", df.iloc[index]['전문'])

<aside> 💡 판례 49423와의 유사도: 0.7064461708068848

판례 69210와의 유사도: 0.7009966969490051

판례 70263와의 유사도: 0.6990678310394287

판례 70263와의 유사도: 0.6990678310394287

판례 56445와의 유사도: 0.6966639757156372

</aside>