본문으로 건너뛰기

가이드

온라인 실험(A/B 테스트)

오프라인 비교는 새 버전이 더 낫다고 말했습니다. 프로덕션의 A/B 테스트는 같은 질문을 실제 사용자에게 던집니다. 여러분의 라우터가 단위(사용자 또는 세션)를 두 암에 무작위로 배정하고, oloproof experiment는 그 로그를 읽어 다른 모든 규칙과 같은 네 가지 상태로 답합니다. 이 방법은 명시된 조건 아래 독립 감사에서 승인되었습니다. observed_until은 결과 로그를 추출한 시점에 대한 여러분의 진술이고, 단위는 독립적으로 무작위 배정되었으며, 어떤 단위의 결과도 다른 단위의 암에 좌우되지 않고, 배정 비율이 바뀌는 동안 결과가 변하지 않았으며, 각 확인은 로그 전체를 읽습니다. 이 조건을 벗어나면 답은 보장되지 않습니다.

로그와 선언

CSV 또는 JSONL 파일 두 개: 단위당 한 행인 배정 로그(여러분이 선언한 단위 열과 arm)와, 단위와 그 value가 있는 결과 로그입니다.

experiment:
  name: checkout-v2
  unit: user
  allocation: {control: 0.5, treatment: 0.5}
  control: control
  treatment: treatment
  assignments: logs/assignments.csv
  outcomes: logs/outcomes.csv
  kind: rate
  rules:
    - {id: lift, kind: superiority}
    - {id: no-harm, kind: non_inferiority, margin: 0.01}
oloproof experiment experiment.yaml --policy release.yaml --json

kind: mean은 선언된 range: [low, high]를 받습니다. direction: max는 낮은 값을 더 좋게 읽습니다. 결과 행이 없는 배정된 단위는 결측이며 각 쪽에서 최악의 값으로 제한됩니다. 단, missing_outcome: zero가 행이 없으면 0이라고 지정하면 예외입니다. 0을 포함해 모든 단위에 대해 행을 기록하십시오. 전환한 단위만 담은 전환 로그는 다른 모든 단위를 결측으로 읽으며, 답은 INSUFFICIENT_EVIDENCE로 남습니다. 0으로 채우기는 집계되는 모든 단위의 결과 창이 닫혔다고 가정합니다. 한 시간 전에 배정된 단위는 아직 전환하지 않았으며, 이를 0으로 세면 더 빨리 전환하는 암이 유리해집니다. 배정 로그에 assigned_at 열을 두고 outcome_window_hours, as_of, observed_until(결과 로그를 추출한 시점)을 선언하면 as_of까지 창이 닫힌 단위만 집계됩니다. 이것들 없이 missing_outcome: zero는 모니터링 방식과 상관없이 거부됩니다. 모든 시각은 오프셋이나 Z를 붙여 쓰십시오(2026-10-11T00:00:00Z). 둘 다 없는 시각은 거부됩니다. as_of는 observed_until보다 늦을 수 없으며, 둘 다 미래일 수 없습니다. 추출 이후의 결과는 로그에 없기 때문입니다. 창이 질문을 정합니다. 48시간 창은 "48시간 안에 전환했는가"에 답하므로, 의도한 결과의 지연을 덮어야 합니다. 단위 ID는 공백을 제거한 뒤 텍스트로 비교되며, 42.0은 42로 읽힙니다. 종료 코드는 가장 나쁜 규칙의 것입니다: 0 PASS, 1 FAIL, 3 INSUFFICIENT_EVIDENCE, 4 MANUAL_REVIEW.

먼저 확인하는 것

  • 표본 비율. 각 암의 단위 수를 선언된 배분에 대해 검정합니다(두 암이면 정확 이항 검정, 그보다 많으면 카이제곱, 임계값 0.001). 불일치가 있으면 모든 규칙이 MANUAL_REVIEW가 됩니다. 분할이 깨졌다는 것은 암들이 더 이상 비교 가능하지 않다는 뜻이며, 같은 종류의 데이터를 더 모아도 고쳐지지 않습니다. 어떤 차이든 읽기 전에 원인(사용자를 잃는 리디렉션, 한 암에만 적용된 봇 필터)을 찾으십시오.
  • 두 암에 있는 단위. 배정이 새어 나갔습니다. 모든 규칙이 MANUAL_REVIEW로 읽힙니다.
  • 한 단위에 여러 결과 행. 거부됩니다. 한 사용자의 이벤트는 독립이 아니기 때문입니다. aggregate: unit_mean을 선언하면 각 단위 자신의 평균이 그 결과가 됩니다. 이때 답은 평균적인 이벤트가 아니라 평균적인 사용자에 관한 것입니다.
  • 빈 암. 결과가 생길 때까지 INSUFFICIENT_EVIDENCE입니다.
  • missing_outcome: zero에서 어떤 배정된 단위와도 맞지 않는 결과 행. 0은 조인에 기대므로, 깨진 조인은 실제 단위를 0으로 읽게 됩니다. ID가 일치할 때까지 모든 규칙은 MANUAL_REVIEW입니다. 기본값에서는 집계된 뒤 제외됩니다.

판정 방법

각 암의 평균에는 Oloproof가 한 번의 실행에 이미 쓰는 구간(비율에는 정확한 Clopper-Pearson, 그 밖에는 베팅 기반 유계 평균)이 주어지며, 각각 오류 예산의 절반을 씁니다. 차이는 두 구간의 반대쪽 끝으로 제한됩니다. 이는 모든 표본 크기에서 성립하며 교과서의 정규 구간보다 넓습니다. 우월성 규칙은 구간 전체가 0보다 위에 있을 때 통과하고, 비열등성 규칙은 하한이 마이너스 마진 이상일 때 통과합니다.

monitoring: anytime은 두 암 모두에 베팅 구간을 쓰며, 얼마나 자주 보든 언제 멈추든 성립합니다. 단, 매번 볼 때 그 시점까지의 로그 전체를 넘겨야 합니다. 읽은 뒤에 기간별로 행을 버리거나 거르지 마십시오. 기본값인 fixed는 계획한 표본 크기에서 한 번 읽습니다.

여러 처리

treatment: 대신 treatments: [b, c]를 선언하고 각 규칙에 비교할 처리를 지정하십시오(treatment: b). 각 암의 구간은 m개의 암에 대해 1 - alpha/m에서 구해지므로, 합집합 경계에 의해 모든 처리 빼기 대조군이 한꺼번에 포괄됩니다. 처리마다 규칙 하나, 각각 주장 하나이며, 그 묶음이 함께 성립합니다. 각 암이 다른 암들의 몫을 치르므로 각 구간은 암이 둘일 때보다 넓습니다. 처리가 여럿이면, 보고서는 그 처리를 지목하는 모든 규칙을 통과한 처리 중 가장 좋은 것을 지목하고, 그것이 통과한 다른 모든 처리와 분리되는지 말합니다. 각 차이는 같은 동시 구간으로 경계가 정해지며 0을 배제합니다. 동률은 선언된 순서를 유지하며 결코 분리되지 않습니다. 표본 비율 검사는 이미 모든 암을 읽습니다. 공동 보장은 하나의 실험 파일에 있는 암들을 포괄합니다. 처리를 여러 파일로 나누면 그 보장을 잃습니다.

비율 지표

클릭률은 클릭을 세션으로 나눈 것이며, 세션이 많은 한 사용자는 독립된 여러 사용자가 아닙니다. 단위마다 한 행으로, 모든 단위의 값이 들어가는 범위와 함께 비율을 선언하십시오.

  ratio: {numerator: clicks, denominator: sessions, numerator_range: [0, 50], denominator_range: [1, 50]}
  aggregate: unit_sum   # only if a unit has several rows: they are added

추정 대상은 각 암의 평균 분자를 평균 분모로 나눈 것입니다. 두 평균은 각각 오류 예산의 자기 몫으로 승인된 구간에 의해 경계가 정해지고, 비율은 그 끝을 나누어 정해지므로, 정규 근사 없이 모든 표본 크기에서 성립합니다. 분모의 구간이 0에 닿으면 구간이 나오지 않습니다. 범위 밖의 값은 단위를 지목하는 구성 오류이며, 잘라내지 않습니다. 델타 방법의 구간은 보통 더 좁으며, 옆에 표시되며 판정하지 않습니다.

테스트 이전의 공변량

테스트 전에 측정한 무언가(지난달 지출, 지난주 세션)를 따라가는 결과는 그것을 빼내면 덜 변동합니다. 각 단위의 테스트 이전 값과, 이 테스트의 결과를 읽기 전에 고정한 계수를 가져오십시오.

  covariate: {values: logs/pre_period.csv, range: [0, 500], theta_from: logs/history.csv}

판정되는 결과는 Y - theta (X - c)입니다. theta는 선언되거나(theta:, 선택적 center:, 기본값은 범위의 중간), 테스트 이전 기간의 이력 파일(covariate와 outcome 열)에서 적합되며, 이 테스트 자신의 결과로는 결코 적합되지 않습니다. X는 배정 전에 측정되었고, 어느 단위에 X가 있는지도 배정 전에 정해졌으므로, 조정된 차이는 같은 추정 대상을 가집니다. 파일에 값이 없는 단위는 조정되지 않습니다. 조정된 결과의 범위가 더 넓기 때문에 유효한 조정도 조정하지 않은 것보다 넓을 수 있으므로, 보고서는 두 구간을 모두 보여 주고 어느 쪽이 더 좁은지 말합니다. 절감을 주장하지 않습니다.

새로움과 간섭, 표시만

novelty: {exposure_column: exposed_at, time_column: at, days: 7}는 배정 로그에서 각 단위의 첫 노출을, 각 결과 행의 시간을 읽고, 노출 후 처음 days 동안과 그 이후의 차이를 보여 줍니다. 초기 차이는 판정되었는데 이후 차이가 판정되지 않았거나 반대이면 "possibly a novelty effect"라고 이름 붙입니다. 이 분할은 결코 규칙을 판정하지 않습니다. 한 구간에 행이 없는 단위는 최악으로 경계 짓지 않고 그 구간에서 제외합니다. 행마다 결과 하나를 받으며, 비율이나 공변량은 받지 않습니다.

cluster_column: team은 여러 암의 단위를 가진 팀을 세고, 한 단위의 결과가 다른 단위의 암에 의존할 수 있는지 묻습니다. 그럴 수 있다면 팀으로 무작위화하고 그것을 단위로 선언하십시오.

여러 처리, 비율, 공변량은 2026년 11월 3일 독립 감사와 그 확인으로, 두 암과 같은 조건으로 승인되었습니다.

오프라인과 온라인

오프라인 비교와 그 지표를 지정하면(offline_comparison: <id>, offline_metric: pass_rate) 답은 판정된 두 방향이 일치하는지를 보고합니다. 이는 보고만 되고 아무것도 판정하지 않습니다. 불일치는 스위트를 살펴볼 이유이지 릴리스에 대한 판결이 아닙니다.

함정

  • 중간에 엿보기. 고정 기간 테스트를 매일 읽다가 좋은 날 멈추면 거짓 승리가 부풀려집니다. 표본 크기를 계획하거나 monitoring: anytime을 선언하십시오.
  • 새로움과 학습. 사용자는 새로운 것에 반응한 뒤 안정됩니다. 첫 주의 향상은 사라질 수 있으니 사용자의 주기를 포괄할 만큼 충분히 길게 실행하고, 분할을 보려면 novelty:를 선언하십시오.
  • 간섭. 구간은 한 단위의 결과가 다른 단위의 암에 의존하지 않는다고 가정합니다. 공유 재고, 마켓플레이스, 소셜 기능, 또는 한 암이 데운 캐시는 이를 깨뜨립니다. 그럴 때는 더 큰 단위(지역, 팀)로 무작위화하고, 클러스터가 얼마나 섞였는지 보려면 cluster_column:을 선언하십시오.
  • 바뀌는 분할에서의 드리프트. 구간은 테스트 동안 배분이 일정했거나, 배분이 바뀌는 동안 결과가 드리프트하지 않았다고 가정합니다. 10%에서 50%로의 단계적 확대나, 평일과 주말에 걸친 90/10 후 10/90은 각 암에서 기간의 가중치를 다르게 하여 차이에 시간 효과를 섞습니다. 표본 비율 검사는 합산된 수를 읽으므로 이를 보지 못합니다. 분할을 고정하거나, 확대 이후 기간만으로 결정하십시오.
  • 단위 바꾸기. 같은 단위로 무작위화하고 분석하십시오. 사용자를 무작위화하고 세션을 독립으로 세면 구간이 잘못 좁아집니다.

이것이 알려 줄 수 없는 것

  • 테스트의 기간, 지역 또는 트래픽 밖의 사용자에게도 결과가 성립하는지.
  • 테스트 전에 선언하지 않은 지표에 관한 어떤 것. 사후에 고른 지표는 기술입니다.
  • 라우터가 정말 무작위화했는지. 표본 비율 검사는 큰 결함은 잡지만 미묘한 결함은 잡지 못합니다.
  • 통과하지 못한 처리 중 어느 것이 가장 좋은지. 통과한 처리만 순위가 매겨집니다. 층화 배분과 스위치백 설계는 구현되지 않았습니다.