본문 바로가기
카테고리 없음

[open ai] Recommendation using embeddings and nearest neighbor search 정리

by U ZZICK 2023. 9. 4.
반응형

https://github.com/openai/openai-cookbook/blob/main/examples/Recommendation_using_embeddings.ipynb


openai-cookbook 에 나오는 Recommendation_using_embeddings 에 대해 하나씩 살펴보며 정리한 내용입니다. 

노트북 바로가기 : Recommendation_using_embeddings.ipynb

 

* 최근접 이웃 탐색 (Nearest neighbor search)

 

이 노트북은 웹에서 흔히 볼 수 있는 추천 시스템에 관한 내용입니다. 제품, 책, 도움말 페이지 등 다양한 항목을 '비슷한 항목 추천'이라는 개념으로 연결시키는 방식을 다루고 있습니다.

이를 통해 주어진 항목과 유사한 다른 항목을 찾아내는 방법을 소개합니다. AG의 뉴스 기사 데이터셋을 사용하여 구체적인 예시를 제시하며, 모델을 활용하여 '주어진 기사와 유사한 어떤 기사들인지'를 찾는 방법을 설명합니다.

 

크게 아래와 같은 흐름을 가지고 있습니다. 

함수 import → 데이터 로드(뉴스 기사) → 임베딩 저장할 캐시 만들기 → 임베딩 기반으로 비슷한 기사 추천 → 추천 예시

 

1. import

embeddings_utils 라이브러리의 함수

이 노트북에서는 아래와 같은 함수들을 import 하고 있습니다. open ai 에서 제공해주는 함수입니다. 

  • get_embedding: 주어진 입력에 대한 임베딩을 얻는 함수입니다.
  • distances_from_embeddings: 임베딩 간 거리를 계산하는 함수입니다. 임베딩 간의 유사성을 측정할 수 있게 해줍니다.
  • tsne_components_from_embeddings: t-SNE (t-Distributed Stochastic Neighbor Embedding) 알고리즘을 사용하여 임베딩을 저차원 공간으로 변환하는 함수입니다. t-SNE는 데이터의 구조를 유지하면서 시각화하기에 적합한 차원 축소 기법입니다.
  • chart_from_components: 주어진 저차원 구성 요소(components)로부터 시각화 차트를 생성하는 함수입니다. 주로 t-SNE 변환된 데이터를 시각적으로 나타낼 때 사용됩니다.
  • indices_of_nearest_neighbors_from_distances: 주어진 거리 정보를 기반으로 최근접 이웃들의 인덱스를 반환하는 함수입니다. 이를 통해 임베딩 간 유사한 항목을 찾을 수 있습니다.

 

2. 데이터 로드

데이터를 로드해보면 제목, 설명, 레이블 등의 필드가 있고 아래는 0번째에 해당하는 기사를 가져와 번역해봤습니다.

기사 1

제목: 세계 소식

설명: 영국: 블레어, 기후 위협 경고 수상 토니 블레어(Prime Minister Tony Blair)는 국제 사회에게 지구 온난화를 심각한 위협으로 간주하고 온실가스의 "놀라운" 증가를 억제하기 위한 계획에 합의할 것을 촉구했습니다.

레이블: 세계

 

아래 사이트에서 AG 뉴스 기사에 대한 정보를 이용할 수 있습니다. 

http://groups.di.unipi.it/~gulli/AG_corpus_of_news_articles.html

 

3. 임베딩 저장할 캐시 만들기

생성한 임베딩을 저장하기 위한 캐시 설정합니다. 일반적으로 임베딩을 저장하여 재사용하는 것이 좋습니다. 저장하지 않으면 다시 계산할때마다 비용이 들기 때문입니다.

캐시는 (text, model) 튜플을 임베딩에 매핑하는 딕셔너리 형태로 저장되며, pickle 확장자로 저장됩니다.

 

get_embedding 함수를 호출하면 open ai 에서 캐시 파일에서 1차적으로 embedding 된 데이터를 key값을 찾고 없으면 embedding 하여 데이터를 리턴합니다. embedding 할때마다 비용이 발생하고, 횟수가 아니라 길이에 따라 비용이 측정됩니다. 

 

4. 임베딩 기반으로 비슷한 기사 추천

  1. 모든 기사의 Decription의 유사성 임베딩을 얻는다.
  2. 원본 Title 과 다른 모든 기사들간의 거리 계산한다.
  3. 원본 Title 과 가장 가까운 다른 기사들을 출력한다.
def print_recommendations_from_strings(
    strings: list[str],
    index_of_source_string: int,
    k_nearest_neighbors: int = 1,
    model=EMBEDDING_MODEL,
) -> list[int]:
    """Print out the k nearest neighbors of a given string."""
    # embeddings: 모든 기사 임베딩한 것
		# query_embedding: 원본 기사의 임베딩 값
    embeddings = [embedding_from_string(string, model=model) for string in strings]
    query_embedding = embeddings[index_of_source_string]

		# 거리 계산
		# 주어진 거리 정보를 기반으로 최근접 이웃들의 인덱스
    distances = distances_from_embeddings(query_embedding, embeddings, distance_metric="cosine")
    indices_of_nearest_neighbors = indices_of_nearest_neighbors_from_distances(distances)

    # 원본 기사 출력
    query_string = strings[index_of_source_string]
    print(f"Source string: {query_string}")

    # print out its k nearest neighbors
    k_counter = 0
    for i in indices_of_nearest_neighbors:
				# 시작 문자열과 정확히 일치하는 문자열 건너뛰기, 원본 소스를 제외하라는 거 같음.
        if query_string == strings[i]:
            continue
        # stop after printing out k articles
        if k_counter >= k_nearest_neighbors:
            break
        k_counter += 1

        # print out the similar strings and their distances
        print(
            f"""
        --- Recommendation #{k_counter} (nearest neighbor {k_counter} of {k_nearest_neighbors}) ---
        String: {strings[i]}
        Distance: {distances[i]:0.3f}"""
        )

    return indices_of_nearest_neighbors

 

5. 추천 예시

article_descriptions = df["description"].tolist()

tony_blair_articles = print_recommendations_from_strings(
    strings=article_descriptions,  # let's base similarity off of the article description
    index_of_source_string=0,  # let's look at articles similar to the first one about Tony Blair
    k_nearest_neighbors=5,  # let's look at the 5 most similar articles
)

article_descriptions : 모든 기사들

index_of_source_string : 0번째 기사를 선택

k_nearest_neighbors : 유사한거 5개 추천

 

반응형

댓글