Sentence Embedding

이승준·2024년 10월 16일

Language Models

목록 보기
1/3

Sentence Embedding

  • 문장을 고정된 크기의 벡터로 변환
    • 문장 내의 단어 순서, 구조, 맥락 등을 고려해 문장의 의미를 보존
    • 머신러닝 모델이 문장을 수치 데이터로 처리할 수 있게 도와줌
  • query 와 특정 문장의 embedding vector 끼리의 내적을 통해 유사도를 측정할 수 있다

Huggingface: bge-m3

  • sentence embedding 을 진행하기 위해 huggingface 에서 bge-m3 model 을 import 해봤다.
  • 이 모델은 한국어 embedding 이 가장 잘 된다고 알려져 있다.

import bge-m3

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("BAAI/bge-m3")

embedded_vector = model.encode("야 저기 차 온다")
embedded_vector.shape
>>> 1024
  • bge-m3 의 embedding dimension 이 1024 인 것을 알 수 있다.

유사도 측정

  • 위에서 인코딩한 "야 저기 차 온다" 라는 문장과 가장 유사한 문장을 dataset 에서 찾아보자
# prepare dataset
import pandas as pd

data = [
    "내일 차타고 놀러가자",
    "지금 오는 버스는 어디서 오는 버스야?",
    "차 한잔 하면서 이야기 하시죠",
    "5차 공동구매! 오늘만 세일!",
    "홍차 녹차 중에 어떤 차가 좋으세요?",
]

df = pd.DataFrame(data, columns=["text"])
  • 각 문장의 embedding vector 를 생성하고, df 에 이를 나타내는 column 을 추가해보자
    • 이를 위해 list comprehension 을 사용했다
    • apply 를 사용해도 되나, list comprehension 이 더 가독성이 좋다고 생각했다.
    • 하지만, 각 row / column 에 적용해야 할 함수가 복잡하면 apply 가 유리할 수 있다.
def get_embedding(text):
	"""
    text: str
    	input text to be embedded
    
    returns: embedding vector of input text
    """
    return list(model.encode(text))

df["embedding"] = [get_embedding(text) for text in df["text"]]
  • query 와 각 문장들의 cosine similarity 를 구하고 정렬
import numpy as np

def cos_sim(A, B):
    """
    A, B: list
        embedding vectors

    returns: cosine similarity of A and B
    """
    return A @ B / (np.linalg.norm(A) * np.linalg.norm(B))
    
def get_candidate(df, query):
    """
    df: string
        list of embedding vectors of candidates
    query: string
        sentence to be compared with candidates

    returns: df of top 3 candidates
    """
    query_embedded = get_embedding(query)
    df["similarity"] = [cos_sim(np.array(emb), query_embedded) for emb in df["embedding"]]

    candidates_sorted = df.sort_values("similarity", ascending=False, ignore_index=True)
    return candidates_sorted.head(3)
    
top_3_candidates = get_candidate(df, "야 저기 차 온다!")
top_3_candidates

>>> 내일 차타고 놀러가자	
>>> 지금 오는 버스는 어디서 오는 버스야?	
>>> 차 한잔 하면서 이야기 하시죠	
  • query 를 바꿔보자
top_3_candidates = get_candidate(df, "예쁜 카페에 가고 싶어.")
top_3_candidates

>>> 차 한잔 하면서 이야기 하시죠	
>>> 내일 차타고 놀러가자	
>>> 지금 오는 버스는 어디서 오는 버스야?
  • "차"라는 단어가 polysemic 하기 때문에 다양한 우선순위가 생성된다
  • "예쁜 카페에 가고 싶다"는 말과 "내일 차 타고 놀러가자" 의 유사도가 예상보다 높았다.
    • query 가 어딘가에 놀러간다는 의미를 내포하기 때문인 것으로 생각된다.

OpenAI API

  • 이번에는 OpenAI 의 API 를 발급받아, text-embedding-ada-002 를 이용해보자

Client 구현

  • API server 에 요청을 보낼 client 를 구현하자
  • OpenAI 에서 발급받은 API key 를 전달해야 하는데, 아래 방법들을 통해 노출을 방지할 수 있다
  1. API key 를 환경변수로 전달하는 방법
os.environ["OPENAI_API_KEY"] = #your key here
  • 환경에 따른 유연성이 좋다는 장점이 있다.
  1. 다른 py 파일에 선언 후 import
import os
import sys
    
sys.path.append(os.path.abspath("../../data"))
from openai import OpenAI
import API_KEY

API_KEY = API_KEY.OpenAI_KEY
client = OpenAI(api_key=API_KEY)
  • key 를 담은 파일이 있는 module 을 계속 추가해줘야 하는 번거로움이 있다.
  • API Key 는 환경변수로 한 번 설정하면 다른 파일에서 추가적인 설정이 필요없기 때문에 1번을 채택
from dotenv import load_dotenv
from openai import OpenAI # for general usage of OpenAI API

load_dotenv()

client = OpenAI()

embedding = client.embeddings.create(
    model="text-embedding-ada-002",
    input=["야 저기 차 온다!", "저건 어디로 가는 버스야?"],
)

len(embedding.data[0].embedding)

>>> 1536 # embedding dimension of model
  • 이후 과정은 huggingface model 을 이용했을 때와 동일하다
profile
인하대학교 컴퓨터공학과

0개의 댓글