[NLP] Reciprocal Rank Fusion(RRF)을 활용한 검색 시스템 성능 향상

jongmin-oh·2023년 10월 2일
0

하이브리드 검색

목록 보기
2/2

What is RRF?

단일 검색 시스템은 모든 상황에서 최적의 결과를 제공하지 못할 수 있습니다.
이러한 이유로 연구자들은 다양한 검색 시스템의 결과를 통합하여 더 나은 검색 결과를 제공하는 방법을 모색하고 있습니다. Reciprocal Rank Fusion(RRF)은 이러한 통합 방법 중 하나로, 다른 검색 시스템의 순위 정보를 결합하여 최종 순위를 생성하는 알고리즘입니다.

(이전 글 참고)

How to Use

저는 키워드 검색과, 밀집 벡터 검색을 query1 과 query2로 사용하였습니다.
검색결과를 ids 값으로 받습니다.

# 검색 결과 예시
query1_ids = [1, 30, 50, 128, 301]
query2_ids = [30, 128, 1, 120, 50]

def get_ranking(query1_ids, query2_ids):
    # 중복 없는 모든 값들을 구합니다.
    all_values = list(set(query1_ids + query2_ids))

    # 결과를 저장할 딕셔너리를 초기화합니다.
    ranking = {}

    # 모든 값을 순회하면서 해당 값의 순위를 구합니다.
    for value in all_values:
        rank1 = query1_ids.index(value) + 1 if value in query1_ids else None
        rank2 = query2_ids.index(value) + 1 if value in query2_ids else None
        ranking[value] = [rank1, rank2]

    return ranking

검색 결과:

{
   128: [4, 2],
   1: [1, 3],
   301: [5, None],
   50: [3, 5],
   120: [None, 4],
   30: [2, 1]
}

def reciprocal_rank(self, rank):
    """주어진 순위에 대한 Reciprocal Rank를 계산하는 함수"""
    try:
        return 1 / rank
    except TypeError:
        return 0.0

해당 랭킹들을 0~1값으로 치환합니다.

1등의 경우 1.0
2등의 경우 0.5

RRF 계산

EMBED_WEIGHT: float = 0.6
KEYWORD_WEIGHT: float = 0.4

def get_rrf_scores(query1_ids, query2_ids):
    ranking = get_ranking(query1_ids, query2_ids)

    ids = []
    scores = []

    for key in ranking.keys():
        # 각 검색 시스템의 순위
        embed_rank = ranking[key][0]
        keyword_rank = ranking[key][1]

        # 각 검색 시스템의 Reciprocal Rank 계산
        embed_rr = reciprocal_rank(embed_rank)
        keyword_rr = reciprocal_rank(keyword_rank)

        # 가중치가 적용된 Reciprocal Rank 계산
        rrf = (EMBED_WEIGHT * embed_rr) + (KEYWORD_WEIGHT * keyword_rr)

        scores.append(rrf)
        ids.append(key)

    sorted_scores = sorted(scores, reverse=True)
    sorted_ids = [
        key for _, key in sorted(zip(scores, ranking.keys()), reverse=True)
    ]
    return {"ids": sorted_ids, "scores": sorted_scores}

결과:

{'ids': [1, 30, 128, 50, 301, 120],
 'scores': [0.7333333333333333, 0.7, 0.35, 0.28, 0.12, 0.1]}

계산된 점수로 다시 정렬
1번 인덱스는 1위,3위를 했고,
30번 인덱스는 2위,1위를 했지만

가중치 때문에 1번 인덱스가 가장 높은 점수를 얻었다.

임베딩 벡터 검색이 좋냐, 키워드 검색이 좋냐
임베딩 검색이 잠재의미를 파악해서 좋다고는 하지만, 키워드 검색도 충분한 성능을 보여주고 있다.
RRF를 사용하여 하이브리드 검색을 구현하면 두 방법을 고민하지 않고 검색결과를 조합하여
다시 랭킹을 매길 수 있다.

profile
스타트업에서 자연어처리 챗봇을 연구하는 머신러닝 개발자입니다.

1개의 댓글

comment-user-thumbnail
2023년 11월 12일

좋은글 잘보고갑니다. ^^ 엘라 공부중에 너무 흥미가 생기네요

답글 달기