무신사가 검색 품질을 관리하는 방법

MUSINSA tech
MUSINSA tech
Published in
16 min readJul 30, 2021

mean Average Precision(mAP) — 검색 모델 평가 지표의 개념과 활용

안녕하세요. 무신사 검색 프로덕트의 성장 방향을 항상 고민하는 검색 개발자 김남수, PM 이다희입니다.

지난 글(검색어 분석을 통한 상품 정렬 개선)에서 ‘무신사 추천순’이라는 상품 정렬 모델의 개선 과정을 소개해 드렸습니다. 모델 성능을 평가할 때 mean Average Precision(mAP) 지표를 활용해 A/B 테스트를 진행한다고 소개했는데요. 이번 글에서는 이 mAP 지표에 대해 상세히 설명하고, 지표를 활용하여 검색 서비스를 어떻게 개선하고 있는지 공유하려 합니다.

정렬 순서를 고려한(rank-aware) 검색 모델 평가 지표

‘무신사 추천순’은 검색어를 통해 파악한 검색 의도를 기준으로 상품들을 정렬하는 모델입니다. 정렬 결과에 대한 고객의 판단을 어떻게 정량적으로 평가할 것인가에 대해 여러번 고민을 거듭했죠. 평가의 핵심은, 검색 결과에서 상위의 상품이 클릭되었을 때 높은 평가를 받을 수 있도록 하는 것이었습니다. 상품의 정렬 순서를 고려한(rank-aware) 검색 모델 평가 지표로 검토했던 후보는 3개입니다.

Mean Reciprocal Rank(MRR)

  • 각 사용자마다 클릭한 상품 중 가장 상위의 위치를 역수로 계산하고, 사용자별로 계산된 점수를 모아 평균을 내는 방법입니다.
  • 가장 단순하고 계산이 쉬운 지표지만, 고객이 클릭한 모든 상품의 순서를 고려하는 것이 아니라 가장 높은 위치에서 클릭된 상품 1개만 고려하므로 해당 지표 사용 시 평가의 정교함이 비교적 떨어질 수 있습니다.
MRR 계산 방식

mean Average Precision(mAP)

  • 각 사용자마다 클릭한 상품 위치까지의 목록(sublist)에 대하여 정밀도(precision)를 계산하고, 사용자별로 계산된 점수를 모아 평균을 내는 방법입니다.
  • 클릭한 모든 상품의 순서를 고려하므로 MRR에 비해 좀 더 정교한 지표지만, 클릭한 상품에 대해 고객의 선호도(예: 1점 ~ 5점)가 존재하는 경우에는 선호도의 수준을 반영하기 어렵다는 단점이 있습니다.
mAP 계산 방식

normalized Discounted Cumulative Gain(nDCG)

  • mAP와 유사하나, 고객의 선호도가 더 높은 상품이 상위에 위치할수록 높게 평가하는 방법입니다.
  • MRR, mAP와 달리 고객의 선호도 수준까지 반영 가능하며, log 함수를 이용하여 하위 정렬된 상품의 영향도를 줄임으로써 좋은 평가 성능을 보입니다.
nDCG 계산 방식

위 3가지 지표 중 mAP가 일정 수준의 정교함을 가지면서, 가장 효율적으로 모델 성능을 측정할 수 있다고 판단하여 주요 지표로 선정했습니다. MRR과 비교해 보았을 때, mAP는 고객 행동 데이터를 좀 더 정밀하게 반영하는 특성이 있어 신뢰도가 더 높은 지표로 판단하였습니다. 고객이 1개의 검색어에 대해 5개 상품을 클릭했다고 가정했을 때, mAP는 5개 상품의 클릭 데이터를 모두 반영하는 반면, MRR은 그 중 가장 순서가 앞선 1개 상품만의 클릭 데이터를 반영하고 나머지 4개 상품의 데이터는 반영하지 않기 때문입니다.

nDCG는 평가 지표로서 mAP보다 정밀함의 수준이 높지만

1. mAP의 계산 절차가 훨씬 쉽고 간편하며

2. 이진법(binary)의 선호도 데이터를 사용할 경우(즉, 상품 클릭=선호, 상품 미클릭=비선호) mAP와 nDCG의 계산 결과는 서로 일정한 상관관계(correlation)를 보이므로

mAP로도 충분히 저희가 원하는 지표 사용 목적을 달성할 수 있었죠.

mean Average Precision(mAP)이란?

이제 mAP에 대해 좀 더 깊게 다뤄보겠습니다. 앞서 말씀드렸듯이, mAP란 사용자가 검색 결과 페이지에서 클릭한 모든 상품에 대해 점수를 반영하되, 해당 상품의 정렬 순서에 따라 점수에 차등을 주는 지표입니다. 지표를 활용하는 관점에서 보자면, 고객이 얼마나 상위에서 상품을 클릭했는가, 혹은 원하는 상품을 상단에서 빠르게 찾을 수 있는가를 양적으로 표현한 수치라고 할 수 있을 것 같습니다. mAP의 수식은 다음과 같습니다.

mAP 수식

수식에서 Q는 1명의 사용자가 1개의 세션에서 입력한 특정 검색어를 뜻합니다. 검색어별로 평균 정밀도(average precision, AP) 값을 계산한 후, 전체 검색어에 대해 각 평균 정밀도 값을 다시 한번 평균(mean)을 내는 절차를 통해 검색어별 1개 세션에서의 일반적인 모델 성능을 측정할 수 있습니다.

정밀도(precision)는 검색된 상품 중 관련 있는 상품의 비율을 의미하며, 이와 연관된 지표인 재현율(recall)은 검색어와 관련이 있다고 판단된(=클릭된) 상품들 중 실제로 검색된 상품의 비율을 뜻합니다. 평균 정밀도는 상품을 정렬한 순서대로 보았을 때, 재현율이 변화하는 정렬 위치별 정밀도 값의 평균이라고 할 수 있습니다.

mAP, 정밀도(precision)와 재현율(recall) 간 관계

mAP가 100%일 경우, 검색된 상품 중 무조건 1번째 상품을 클릭했다고 해석할 수 있으므로 mAP가 높을수록 모델 성능이 좋다고 판단합니다.

실제 검색이나 추천 시스템 연구에서는 고객들이 모든 검색/추천 결과 페이지가 아닌, 처음 일부 페이지만 보고 결과에 대해 판단하기 때문에 초기에 등장하는 k개의 문서에 대해서만 mAP를 측정하기도 합니다. 이러한 지표를 mAP@k라고 표현하며, 모델간 성능 비교 연구에서 다수 사용되고 있습니다. (사용 예시 : mAP@5, mAP@50 등)

파이썬으로 mAP를 계산하고자 하는 경우, 아래와 같이 ‘ml_metrics’ 패키지에서 AP@k를 구하는 함수가 제공되므로 mAP@k 또한 쉽게 계산할 수 있습니다.

파이썬을 통한 mAP 계산

지표를 활용한 서비스 개선

대시보드 구축 및 활용

위와 같은 검색 품질 지표에 대한 이해를 바탕으로, 무신사 스토어 통합검색 서비스의 상품이나 콘텐츠의 정렬이 고객의 검색 의도에 적합한지 지속해서 모니터링하고자 대시보드를 구축하였습니다.

mAP 측정 시, 기존에는 Google Analytics(GA) 기반의 로그 데이터를 추출하여 로컬 환경에서 지표 측정 프로그램을 실행하는 방식을 취하고 있었는데, 이러한 방식은 실시간 고객 반응 측정이 어렵고, 지표 데이터 수집부터 분석까지 소요되는 시간이 다소 길다는 한계점이 있었죠. 프로덕트 분석 담당자 입장에서 GA 기반 로그는 수집된 지 기본적으로 하루가 지나야 분석이 가능하다는 점이 상당히 답답했습니다.

이에 신규 구축한 대시보드는 Elastic(Elasticsearch-Logstash-Kibana) Stack 구조를 채택하여 PC와 모바일 웹/앱 환경에서 발생하는 모든 고객의 클릭 로그를 실시간으로 수집하고, mAP 측정 결과를 단시간 내에 시각화할 수 있는 환경을 구현하였습니다. 이미 사내에 블랙홀(Blackhole)이라는 로그 수집/관리 시스템이 잘 구축되어 있고, Elasticsearch, Kibana 환경이 구축되어있어 Elastic Stack 구조를 선택하는 데는 그리 오랜 시간이 걸리지 않았습니다 :)

고객 반응 데이터 수집부터 대시보드 구축까지의 전체 작업 흐름도는 아래와 같습니다.

대시보드 구축 절차

1단계. 사용자 이벤트 로그 전송

검색결과 페이지 내 고객들의 행동 데이터(상품 또는 콘텐츠 클릭 이벤트 로그)를 실시간으로 전송하는 단계입니다. 무신사의 로그 시스템인 블랙홀은 SDK 통해 로그를 남길 수 있는 기능을 제공하고 있습니다.

아래는 SDK 적용 예시입니다.

<script src="https://static.msscdn.net/static/lib/blackhole/1.1.0/mssBlackholeSdk.js"></script>

<script>
mssBlackholeSdk.page({
page_id: '/search/results/goods'
});
<script>

아래는 적재 대상 로그 데이터 필드 정의 예시입니다. 로그를 발송할 html Element에 속성을 추가합니다.

<a name="goods_link"
class="img-block"
href="https://store.musinsa.com/app/goods/1848166"
title="쿨 코튼 2-PACK 티셔츠" -- 상품명 : 쿨 코튼 2-PACK 티셔츠
data-bh-system-tags="searchResult"
data-bh="click,impression"
data-bh-action-type="clk" -- 고객 행동 유형 : 클릭
data-bh-position1="6" -- 상품 정렬 순서 : 6번째
... (생략) ...
data-bh-custom-inflow-type="popular" -- 상품 정렬 기준 : ‘무신사 추천순'
data-bh-impression="sent">
<img src="https://image.msscdn.net/images/goods_img/20210316/1848166/1848166_4_220.jpg" alt="쿨 코튼 2-PACK 티셔츠">
</a>

2단계. 로그 수집 및 전처리

블랙홀을 통해 실시간으로 전송된 로그는 Kafka에 적재됩니다. Kafka Tool을 통해 로그 데이터 적재 현황을 확인할 수 있습니다.

Kafka를 통한 로그 적재 현황 확인

다음으로 Logstash를 통해 Kafka 데이터를 읽고 이를 Elasticsearch로 전달합니다. 이 때 나중에 로그 분석 단계에서 편하게 사용할 수 있도록 블랙홀 환경에 맞춰 명명된 필드명, 데이터 포맷, 필드값 등을 추가/삭제/변환하는 과정을 거칩니다.

아래는 로그 수집 및 전처리 예시입니다.

input {
kafka {
topics => ["토픽명"]
bootstrap_servers => "kafka bootstrap정보"
security_protocol => "SSL"
ssl_truststore_location => "인증서 파일 경로"
enable_metric => false
codec => "json"
group_id => "그룹 아이디"
}
}

##Filter section
filter {

... (생략) ...
mutate {
rename => {
"custom_keyword" => "keyword"
"custom_exp_id" => "exp_id"
"custom_exp_variant" => "exp_variant"
"custom_sort_code" => "sort_code"
"custom_page_no" => "page_no"
"custom_rows" => "rows"
"custom_score" => "score"
"custom_total_count" => "total_count"
"custom_selected_filter" => "selected_filter"
... (생략) ...
"agent" => "user_agent"
"gender" => "member_gender"
"position2" => "sequence"
"group_level" => "member_group_level"
}
}
... (생략) ...
}

3단계. 로그 저장

수집된 로그 데이터를 저장소(storage)에 저장하는 단계입니다. Logstash Output 설정를 통해 Elasticsearch로 데이터를 전달합니다.

Elasticsearch는 저장소를 관리하기 위해 인덱스의 수명 주기를 설정/관리하는 기능을 지원합니다. 저희는 아래와 같이 수명 주기를 설정하였습니다.

  • 로그 데이터는 최대 하루 데이터만 저장한다.
  • 하루가 지나면, 새로운 인덱스를 만들고 쓰기 위한 Alias를 변경한다.
  • 기존의 인덱스는 삭제된다.

아래는 로그 저장 예시입니다.

##Output section
output {
elasticsearch {
hosts => ["Elasticsearch Endpoint정보"]
ilm_rollover_alias => "인덱스명"
ilm_enabled => true
ilm_policy => "rotate-daily"
}
}

4단계. 로그 분석

mAP 등 사용자가 설정한 지표를 측정하는 단계입니다. 파이썬 기반 mAP 측정 코드를, AWS Lambda를 이용하여 서버리스(serverless) 환경에서 실행하였습니다.

일별 로그 데이터를 Elasticsearch search-action-log 인덱스(고객 행동 로그 저장소)로부터 불러와 mAP 측정 데이터를 생성하고, 생성한 데이터를 다시 Elasticsearch search-goods-relevance-feedback 인덱스(고객 행동 분석 로그 저장소)에 색인할 수 있도록 하였습니다.

AWS Lambda를 통한 로그 분석

5단계. 시각화

요구사항에 맞게 데이터를 조회 및 시각화할 수 있는 대시보드를 생성하는 단계입니다. Kibana는 Elasticsearch 데이터를 시각화하고, Elastic Stack을 탐색하게 해주는 무료 오픈 소스 인터페이스입니다.

Kibana에서 Elasticsearch 인덱스명을 조회하기 위해서는 먼저 인덱스 패턴을 등록해야 합니다. 이후 조회/분석 대상 데이터가 저장된 인덱스를 고르고, 시각화하고 싶은 그래프 유형을 선택하여 맞춤 대시보드를 생성할 수 있었습니다.

추가 개발사항

대시보드를 1차 생성하여 사내에 리뷰한 결과, 고객 디바이스별과 주요 검색어 사례별로 mAP 지표를 보고 싶다는 피드백이 있었습니다. 이에 Elasticsearch의 search-goods-relevance-feedback 인덱스에 디바이스와 키워드 필드를 추가하였으며 파이썬 코드도 일부 수정하는 작업을 진행했습니다. 이때 수정된 코드가 AWS Lambda function 실행 제한시간(15분)을 초과해버리는 현상이 나타났고, 아래와 같이 데이터 조회 쿼리를 병렬 호출할 수 있도록 코드를 개선하여 해당 현상을 해결했습니다.

쿼리 호출 구조 개선

결과적으로 저희가 생성한 대시보드 화면의 일부는 아래와 같습니다. 본 대시보드를 통해 고객의 검색 행동이나 패턴, 예를 들어 어떤 검색어 사례에서 고객이 상품을 상단에서 잘 클릭하지 않는지 등을 비교적 손쉽게 실시간 모니터링하고, 이를 참고하여 검색 모델이나 서비스 화면의 구조 개선 방향을 도출하고 있습니다.

검색어별 mAP 모니터링 예시

A/B 테스트 설계 및 분석

지난 글(검색어 분석을 통한 상품 정렬 개선)에서도 사례를 소개해 드렸듯이, 상품이나 콘텐츠를 정렬하는 알고리즘을 개선하는 프로젝트를 진행할 때에도 A/B 테스트의 주요 지표로 mAP를 사용하고 있습니다.

구체적으로 무신사 스토어는 모바일 웹/앱 환경에서 검색 결과 1페이지 당 상품이 60개씩 노출되고 있기 때문에, mAP@k에서 지표를 의미하는 k를 60으로 설정하여 모바일 환경에서의 검색 이용자 반응을 테스트 해보기도 합니다. 모델 성능이 좋지 않게 나오는 사례가 있을 경우, 해당 사례의 검색어나 검색 이용자의 인구통계학적(demographic) 특성 혹은 이용자 행동의 문맥(context) 정보로서 시간, 디바이스 등을 분석하고 최적의 성능을 구현하기 위한 상품/콘텐츠 정렬 개선 과제들을 도출하고 있습니다.

mAP 지표를 활용한 A/B 테스트 리포트

마치며

무신사가 검색 프로덕트의 품질을 어떻게 정량적으로 진단, 개선하고 있는지 mAP 지표를 중심으로 설명드렸습니다. 이를 통해 보다 객관적이고 신뢰도 있는 근거를 바탕으로 의사결정을 내리고, 고객이 원하는 상품이나 콘텐츠를 단시간 내 더 효율적으로 찾을 수 있게 되었습니다.

무신사는 고객의 반응을 빠르게 살펴보기 위해 항상 노력하고 있습니다. 이번 글에서 소개해드린 여러가지 검색 모델 평가 지표와 해당 지표를 활용한 대시보드, 실험에는 고객의 마음을 생각하고 프로덕트에 반영하려는 실무자들의 고민과 노력이 담겨 있습니다. 앞으로도 고객에게 집중하며 발전하는 무신사 검색 프로덕트의 모습 기대해주세요!

참고

- https://en.wikipedia.org/wiki/Evaluation_measures_(information_retrieval)
- https://en.wikipedia.org/wiki/Mean_reciprocal_rank
- https://en.wikipedia.org/wiki/Precision_and_recall
- https://esbook.kimjmin.net/01-overview/1.1-elastic-stack/1.1.3-kibana
- https://medium.com/@jee0645/asynchronous-execution-with-aws-lambda-2fbccbe83f78
- https://medium.com/swlh/rank-aware-recsys-evaluation-metrics-5191bba16832
- https://www.elastic.co/kr/logstash/
- https://www.elastic.co/kr/blog/implementing-hot-warm-cold-in-elasticsearch-with-index-lifecycle-management
- https://www.kaggle.com/wendykan/map-k-demo
- https://www.slideshare.net/MinsubYim/evaluation-in-ir-system
- https://www.uni-mannheim.de/media/Einrichtungen/dws/Files_People/Profs/goran/10-Evaluation-FSS20.pdf
- https://www.youtube.com/watch?v=pM6DJ0ZZee0

--

--