본문 바로가기
인공지능/ChatGPT

[openai-cookbook] 임베딩과 이웃 기반 검색을 사용한 추천 예제 (리뷰문서)

by judy@ 2023. 6. 4.

목차

    포스팅 개요

    • 자료 위치: https://github.com/openai/openai-cookbook/blob/main/examples/Recommendation_using_embeddings.ipynb
    • 주제: 추천을 위해 유사한 아이템을 찾는 데에 임베딩을 사용하는 방법에 대해 기술. AG의 뉴스 아티클 코퍼스를 사용함
    • 특이점
      • 다른 유사도 기반 검색의 경우, 질의-위키피디아, 리뷰 키워드-리뷰전문 등 있었음. 이번에는 기사-유사한 기사의 검색임. 즉, 아이템 간의 유사도 검색을 하여 A 기사를 보고 있는 사람이 관심 있을만한 유사한 다른 기사를 추천하는 데에 의미가 있음.
      • openai에 유사도를 계산하는 모듈이 있음. 이걸 사용함. 특별한 것은 아님. 공식 도큐먼트가 없음?

    핵심 내용

    “기사가 주어졌을 때, 가장 유사한 다른 기사들은?” 에 대답하는 모델이며, 따라서 추천으로 해석 가능

    1. imports

    openai의 임베딩 모듈을 사용한다

    from openai.embeddings_utils import (
        get_embedding,
        distances_from_embeddings,
        tsne_components_from_embeddings,
        chart_from_components,
        indices_of_nearest_neighbors_from_distances,
    )
    
    💡 이 때, ploty가 없다는 에러가 발생하는데, 아마도 차트를 그릴 때 사용해서 발생하는 오류로 보임. pip install plotly로 설치하면 정상 동작

    임베딩 모델 정보

    EMBEDDING_MODEL = "text-embedding-ada-002"
    

     

    2. Load data

    데이터 프레임의 컬럼 정보는 title, description, label_int, label이 있는데, 이 중 어떤 label이 몇 개 있는지 확인해보자.

    df.label.value_counts()
    
    label
    World       520
    Business    511
    Sports      491
    Sci/Tech    478
    Name: count, dtype: int64
    

     

    3. build cache to save embeddings

    임베딩은 매 호출마다 토큰에 의해 비용이 부과되므로, 호출 결과를 저장해두는 것이 좋음. 이 때문에 결과를 저장하기 위한 캐시를 생성함. 파일의 확장자는 pkl로 파이썬 딕셔너리 객체를 저장하기 위해 사용함.

    캐시 구조: Python Dictionary

    • keys: (string, model)
    • values: embeddings

    저장 원리

    • (string, model)이 없으면, 임베딩을 수행하고 결과를 캐시에 저장
    • 있으면 패스

    openai-cookbook repository에 모든 레코드(기사)에 대해 이미 데이터를 모두 캐싱해두어서 API 호출 없이도 임베딩 결과가 불러와짐

     

    4. Recommend similar articles based on embeddings

    임베딩에 기반한 유사 기사 추천은 다음의 3단계로 추천이 이루어짐

    1. 모든 기사 descriptions의 임베딩을 가져옴
    # get embeddings for all strings
    embeddings = [embedding_from_string(string, model=model) for string in strings]
    
    # get the embedding of the source string
    query_embedding = embeddings[index_of_source_string]
    
    1. 소스 제목과 다른 모든 기사 사이의 거리를 계산 (코사인 유사도에 기반하여 모든 기사와 유사도 계산)
    # get distances between the source embedding and other embeddings 
    # (function from embeddings_utils.py)
    distances = distances_from_embeddings(
        query_embedding, embeddings, distance_metric="cosine")
    
    1. 소스 제목과 가장 가까운 다른 기사를 출력
    # get indices of nearest neighbors 
    # (function from embeddings_utils.py)
    indices_of_nearest_neighbors = \\
    indices_of_nearest_neighbors_from_distances(distances)
    
    # print out its k nearest neighbors
    k_counter = 0
    for i in indices_of_nearest_neighbors:
        # skip any strings that are identical matches to the starting string
        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}"""
        )
    

     

    여기서 잠깐 ⁉️⁉️

    def indices_of_nearest_neighbors_from_distances(distances) -> np.ndarray:
        """Return a list of indices of nearest neighbors from a list of distances."""
        return np.argsort(distances)
    

    소스코드: https://github.com/openai/openai-python/blob/main/openai/embeddings_utils.py

    • indices_of_nearest_neighbors_from_distances 이 메서드는 과연 Top N과 다를까? 전혀 다르지 않음

     

    5. Example recommendations

    예제 1: Tony Blair(전 영국 총리) 관련 기사 추천

    • 기사 내용: 토니 블레어 기후 위협 경고
    • Top 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
    )
    
    👉 Source string: BRITAIN: BLAIR WARNS OF CLIMATE THREAT Prime Minister Tony Blair urged the international community to consider global warming a dire threat and agree on a plan of action to curb the quot;alarming quot; growth of greenhouse gases.

    --- Recommendation #1 (nearest neighbor 1 of 5) --- String: THE re-election of British Prime Minister 
    Tony Blair
     would be seen as an endorsement of the military action in Iraq, Prime Minister John Howard said today. Distance: 0.153 --- Recommendation #2 (nearest neighbor 2 of 5) --- String: LONDON, England -- A US scientist is reported to have observed a surprising jump in the amount of carbon dioxide, the main 
    greenhouse
     gas. Distance: 0.160 --- Recommendation #3 (nearest neighbor 3 of 5) --- String: The anguish of hostage Kenneth Bigley in Iraq hangs over Prime Minister 
    Tony Blair
     today as he faces the twin test of a local election and a debate by his Labour Party about the divisive war. Distance: 0.160 --- Recommendation #4 (nearest neighbor 4 of 5) --- String: Israel is prepared to back a Middle East conference convened by 
    Tony Blair
     early next year despite having expressed fears that the British plans were over-ambitious and designed Distance: 0.171 --- Recommendation #5 (nearest neighbor 5 of 5) --- String: AFP - A battle group of British troops rolled out of southern Iraq on a US-requested mission to deadlier areas near Baghdad, in a major political gamble for British Prime Minister 
    Tony Blair
    . Distance: 0.173

    위처럼 모두 토니 블레어 또는 기후와 관련된 기사가 나오는 것을 확인할 수 있음.

     

    Appendix: 정교한 추천을 위해 임베딩을 사용할 수 있다.

    아이템 인기도나 유저 클릭 데이터와 같은 많은 신호를 학습하는 머신 러닝 모델로 정교한 추천 시스템 구현 가능. 이런 모델에 임베딩을 적용하면, 새로운 유저의 데이터가 없어서 발생하는 “cold-started” item 에게 유용할 수 있음

    1. 유사한 아티클의 임베딩을 시각화해보자

    처음 있었던 label 컬럼으로 색을 구분하였더니, 같은 기사 카테고리끼리 비슷한 좌표에 위치하는 것을 알 수 있음.

    2. 토니 블레어 기사는 어디에 있을까?

    두 개 말고는 멀리있다. 왜?

    t-SNE는 시각화를 목적으로 고차원(1536 토큰)의 데이터를 2D 또는 3D로 축소하여 나타내는 방법. 1536개의 특징이 있을 때에는 Tony blair 기사에 대해 5개의 기사들이 가까이 위치하나, 이를 2D로 압축하면 이와 같은 특성이 잘 나타나지 않기 때문임.

    3. 엔비디아 칩셋 데이터는 가까이 있나?

    이들은 압축 벡터에서도 유사성이 대체로 잘 표현됨.


    마무리

    • 많은 use case가 임베딩 → 검색으로 이루어짐
    • DTx 콘텐츠의 동영상 자막이나 기록 내용 등을 임베딩하여 추천 모델의 정확성을 향상할 수 있음
    반응형