본문 바로가기

DM ML AD

테스트 및 평가 자동화

지난 글 '데이터 문제 접근하기'에서 마지막 단계인 테스트가 중요하다고 적었습니다. 테스트와 관련해서 팀내에 공유했던 글이 있어서, 블로그/일반에 맞게 조금 수정해서 올립니다.

===

최근 구글의 데이터 사이언스에서 개설한 Unofficial Google Data Science 블로그에 가장 최근에 올라온 Experiment Design and Modeling for Long-term Studies in Ads의 주요 논문과 이 논문에 엮인 참조논문들을 보면서 (모든 논문을 제대로 읽은 것은 아님^^) (온라인) 테스트를 이해하는 도움글이 필요할 것같아서 간단히 글을 남깁니다.

테스트의 목적이야 새로 추가/개선된 기능이 실제 효과가 있는지를 미리 확인해보는 것입니다. 인터넷 업계에서는 새로운 기능을 모든 사용자들에게 한꺼번에 오픈하는 것이 아니라, 소수의 사용자들에게 먼저 적용해서 반응을 본 후에 전체에 공개하는 것이 일반적입니다. 당연히 반응이 나쁘면 기존 것을 유지하거나 새로운 개선안을 다시 테스트 합니다. 여러 대안이 있다면 그것들 중에서 가장 좋은 것을 선택하는 방법으로 테스트를 진행할 수도 있습니다. 여러 측면에서 테스트를 구분할 수가 있습니다.

오프라인 테스트와 온라인 테스트
오프라인 테스트는 새로운 기능이나 설정값을 실 사용자들에게 보여주고 반응을 추적하지 않고, 기존에 쌓아뒀던 로그 데이터를 이용해서 신규 기능이 적용됐을 때 어떻게 작동하고 어느 정도의 성능을 낼 것인가?를 미리 예측/시뮤레이션해보는 것입니다. 오프라인 테스트의 전제 조건이 충분한 (로그) 데이터입니다. 제대로 된 오프라인 테스트를 위해서 현재 로깅하는 것보다 훨씬 더 많은 데이터를 쌓아놓아야 하는데, 이게 현실적으로 불가능한 경우가 많습니다. 그래서 (정성적으로 확인이 됐다면) 오프라인 테스트를 스킵하는 경우도 종종 발생하고, 원래 봐야하는 평가 지표가 아닌 다른 2차, 3차 지표로 원래 지표를 확인해서 원래 지표를 가늠하는 수준에서 진행되는 경우도 있습니다.

오프라인 테스트가 기존의 데이터를 바탕으로 성능을 유추하는 것이라면, 온라인 테스트는 변경된 기능을 소수의 사용자들에게 실제 노출시켜서 반응을 보는 것입니다. 뒤에서 설명하겠지만 흔히 말하는 버킷테스트나 A/B 테스트가 온라인 테스트를 의미하는 경우가 많습니다. 제한된 사용자지만 실 사용자들의 반응을 확인함으로써 전체 적용 시의 효과를 미리 확인할 수 있습니다. 소수 (보통 5%나 10%)의 제한된 사용자들에게만 변경된 것을 노출시키기 때문에 성능이 더 나쁘더라도 전체의 성능 크게 떨어뜨리지 않는 방법입니다. 

버킷 테스트, A/B 테스트
온라인 테스트를 흔히 버킷 테스트라고 부르는데, 이는 특정 버킷 (선택된 제한된 사용자군)에게만 새로운 기능/설정이 적용되어서 (즉, 나머지 사용자들은 현재 설정대로 노출) 그들의 행동을 확인하기 때문에 버킷 테스트라고 부릅니다. 그리고 A/B 테스트라고도 부르는데, 이는 A그룹과 B그룹으로 나눠서 다른 것을 보여주기 때문입니다. A/B 테스트는 '현재 vs 신규'로 구분하는데, 경우에 따라서 'A, B, C, D...' 등으로 더 많은 그룹으로 세분화해서 동시에 테스트를 진행해서 가장 성능이 좋은 그룹/설정을 선택할 수도 있습니다. 실험에서 A그룹은 대조군 Control 또는 comparison으로 현재 상태를 그대로 적용한 그룹이고, B그룹은 실험군 Experiment로 새로 적용된 기능을 보여주는 그룹입니다.

구글이나 페이스북같이 수천만, 수억명의 사용자가 사용하는 서비스라면 1%미만의 버킷을 설정해도 됩니다. 테스트 버킷이 너무 적으면 결과의 신뢰성이 떨어지고, 너무 크면 실 서비스 지표에 영향을 주기 때문에 늘 그렇듯 적당히 (과학적인 글에서 비과학적인 표현이지만) 정하면 됩니다. 사용자나 PV가 적은 서비스라면 50% 버킷을 정해도 좋고, 아니면 특정 기간 (몇 시간, 하루 ~ 일주일 등)을 정해서 100% 버킷을 정해도 됩니다. 단, 기간으로 버킷을 정할 때는 계절/요일 등의 외부 요소에 의해서 서비스 지표가 달라진다는 점을 염두에 둬야 합니다. 온라인 테스트는 상시 진행되는 것이므로 버킷의 사이즈를 정하는 테스트를 먼저 진행하는 것도 필요할 수도 있습니다.

버킷 구분: 트래픽 기준과 사용자 기준
이런 버킷 또는 B그룹을 선택할 때 트래픽 기준으로 구분할 수도 있고, 사용자 기준으로 구분할 수도 있습니다. 트래픽 기준이라면 현재 들어오는 트래픽 중에 임의로 10%의 트래픽에는 신규 기능을 노출시키는 것입니다. 예를들어, 랜덤함수를 사용해서 0.1보다 작으면 신규 기능을, 0.1보다 크면 기존의 것을 그대로 보여주는 형태입니다. 이렇게 하면 구현 자체는 쉬울 수 있지만, 로그에 A/B그룹을 명시해줘야하는 불편함이 발생하고, 또 모든 사용자들에게 임의로 10%가 노출된다는 점이 장점이면서 단점일 수도 있습니다.

이에 비해서 사용자 기준의 경우, 10%의 사용자를 실험군으로 설정해서 그들에게만 신규 기능을 노출시키는 방법입니다. 보통 사용자 ID나 쿠키 정보를 활용해서 사용자를 구분합니다. ID를 사용하면 좋은 점은 ID가 시간이 변해도 바뀌지 않는다는 점이지만, 모든 사용자가 매번 로그인해서 사용하지 않는다는 단점이 있고, 쿠키 기반의 경우 쿠키가 변경되면 데이터 추적이 불가능하다는 단점이 있습니다. (특별한 경우가 아니면 쿠키가 변경될 가능성은 매우 낮음) 그리고, 사용자 기반의 경우 테스트 기간 동안 실험군을 고정시킬 수도 있고, 특정 주기마다 다른 사용자를 실험군으로 설정할 수도 있습니다. 특히 테스트의 편향성 bias를 체크하기 위해서 (알고리즘이 미적용된 깡통 서비스가 제공되는) 임의 random 버킷을 설정하는 경우가 있는데, 특정 사용자가 항상 임의 그룹에 속하게 되면 그 사용자들에게 늘 나쁜 서비스만 제공되기 때문에, 임의 버킷의 경우 주기적으로 (매시간/매일) 변경해주는 것이 좋습니다.

보통 ID체계를 숫자로 표시했을 때, 'ID mod 버킷수'로 해서 특정 나머지값을 가지는 그룹을 실험군으로 선택합니다. 예를들어, ID가 10153159337581569라면 10153159337581569 % 100하면 나머지가 69이므로, 이 사용자는 69번 버킷에 속하게 됩니다. 10153159337581569 % 10으로 해서 9번 버킷에 속할 수도 있습니다. 이런 식으로 버킷을 구분해서 원하는 비율만큼 실험군으로 정하면 됩니다. %100인 경우, 69번 버킷만 실험군으로 사용하겠다면 실험군은 1%가 되는 것이고, 68번 69번을 사용하겠다면 2%가 되고... 60(6#)번대를 모두 사용하겠다 또는 9로 끝나는 (#9)를 모두 사용하겠다고 하면 10% 버킷이 만들어 집니다. %1000으로 하면 더 세부적인 그룹이 만들어집니다. 그런데, 임의의 버킷을 만들기 위해서 ID체계도 임의적으로 적용돼야 한다는 점은 중요합니다. '1로 끝나는 모든 ID는 남성이고, 2로 끝나면 여성이다' 이런 식의 규칙이 있다면 임의 버킷을 만들 수가 없습니다. 물론, 필요에 따라서 성별, 연령 등을 구분해서 버킷을 만드는 경우도 있습니다.

A/B 테스트를 적용할 때, 트래픽 또는 사용자 기준 외에도 시간 기준으로도 적용할 수가 있습니다. 하루동안 모든 사용자에게 적용하고 롤백한다와 같이 모든 트래픽/사용자가 시간 기준으로' A그룹 - B그룹 (하루) - 다시 A그룹'이 되는 식입니다. 그런데 이건 참 위험한 방법입니다. 특히 B그룹이 적용됐을 때 예상치 못한 외부 효과 때문에 더 좋게/나쁘게 결과가 나올 가능성이 많기 때문입니다. 이런 외부효과에 영향을 받지 않기 위해서 같은 기간 동안 A/B그룹을 나눠서 함께 보고 비교하는 것이 일반적입니다. 보통 A/B 테스트를 진행한 후에 그냥 성능이 더 좋은 쪽 (예를들어, B)이 있으면 모든 사용자에게 그냥 B (신규 기능)을 적용하는 것이 일반적인데, 서두에 소개한 구글 블로그의 논문에서는 A/A - A/B - A/A 과정을 거치는 것을 추천합니다. 뒤쪽에 A/A를 진행하는 이유는 테스트 기간동안 B그룹에 속했던 사용자들이 신규 기능에 학습돼서 테스트 후에도 이상행동을 보이는지를 확인하기 위해서라고 합니다. 예를들어, 새로운 기능 B가 사용자들을 실망시켜서 테스트 기간 이후에 B그룹에 속했던 사용자들이 서비스에서 이탈해버리는 경우도 발생할 수 있습니다. 단기적으로 성능이 좋은 것도 중요하지만, 장기적으로 사용자의 학습에 의한 효과도 같이 보기 위해서라고 합니다. (자세한 것은 첫번째 논문 참고)

테스트에서 중요한 것 중에 하나가 편향성 bias이 없어야 한다는 점입니다. 앞서 말한 임의 ID 체계가 필요한 이유도 편향성을 막기 위한 것입니다. 그리고, 편향성을 막기 위해서 실험계획 Design of Experiment (DOE) 또는 Experimental Design이라는 게 필요한데, 이건 따로 공부하세요.

테스트에서 어쩌면 가장 중요한 것은 평가 지표입니다. IMPRESSION (광고에서 노출을 impression이라고 함)을 높일 것인가? 아니면 CTR을 높일 것인가? 등의 지표가 명확해야 합니다. 그리고, 1차 지표 외에도 다른 2차, 3차 지표도 함께 고려될 필요가 있습니다. 광고의 경우 CTR도 높아야 하지만, CTR이 높아졌다고 해서 전체 수익이 낮아지면 안되는 것과 같이, 실험 전에 1차지표 외에 2, 3차 지표도 함께 고민해야 합니다.

평가지표에서 (예를 들어, CTR) 테스트 기간을 거쳐서 단순히 B의 평균 CTR이 A의 평균 CTR보다 높아고 해서 그냥 B가 더 낫다라고 결론을 내리면 안 됩니다. 분산을 함께 봐야지 평균의 함정에서 벗어날 수 있습니다. A의 CTR이 10%이고, B의 CTR이 11%였는데, A와 B의 CTR분산이 모두 2~3%였다면 사실 A와 B가 다르지 않다라고 봐도 무관합니다. 이때 사용하는 방법이 ANOVA (Analysis of Variance)인데, 실험계획을 공부하면 실제 실험계획보다는 ANOVA를 더 중요하게 다룬다는 불편한 진실이...

ANOVA는 가설검증의 방법으로 주로 사용됩니다. 가설검증이란 귀무가설 (Null Hypothesis 또는 H0, A와 B는 같다)를 검증하는 것입니다. A와 B가 평균은 다르지만, 분산 때문에 신뢰구간 내에서 겹칠 수도 있다면 귀무가설을 기각합니다. 즉, 통계적 유의미성을 판단하는 방법입니다. 엑셀에서 ANOVA를 실행해보면 P-value, F-value 등이 나오는데, 이것들을 보고 통계적 유의미성을 판단합니다. 그런데, '과학적인 방법: 통계적 오류들'에서 설명하듯이 P밸류로 유의성을 판단하는 것이 항상 옳은 것은 아니라고 합니다. (참고 원문)

그리고, 온라인 테스트에서 가장 효과적인 검증을 위해서 수치를 그래프로 비쥬얼라이즈해주는 것이 가장 직관적으로 바로 판단할 수 있습니다. 테스트의 설계에서 비쥬얼라이제이션까지 모두 고려돼야... 숫자보다는 눈으로 보는 게 더 감이 오니까...


반응형