Estatística

Teste A/A: validar a montagem antes de confiar no resultado

O que é um teste A/A, o que um A/A aprovado realmente prova, como dimensionar um e por que a checagem de divisão pega mais bug real que o valor-p.

Ilustração plana de uma balança de braço perfeitamente nivelada com uma esfera idêntica em cada prato, em tons de verde profundo

Um teste A/A roda o seu pipeline de experimentação inteiro mostrando a mesma experiência aos dois grupos, então toda diferença que ele reporta é ruído ou defeito. É o jeito mais barato de descobrir se os seus resultados significam alguma coisa, e o mais mal lido, porque um A/A aprovado é um detector de falha que voltou vazio, não um certificado de que o sistema está são. Este guia cobre o que um A/A de fato valida, por que um A/A significativo é esperado e não alarmante, como dimensionar um para que o resultado limpo carregue informação, e a checagem de divisão que pega mais bug real que a leitura de conversão. Faz parte do nosso guia completo de teste A/B e forma par com SRM: divisão desigual de tráfego, que é a falha que um A/A mais costuma revelar.

O que é um teste A/A, e os dois trabalhos que ele faz

Kohavi, Longbotham, Sommerfield e Henne, no levantamento de 2009 sobre experimentos controlados na web, definem o teste A/A, que notam ser às vezes chamado de teste nulo, assim: em vez de um teste A/B, você exercita o sistema de experimentação, atribuindo usuários a um de dois grupos, mas expondo-os exatamente à mesma experiência. Eles nomeiam dois usos, e os dois são trabalhos genuinamente diferentes.

O primeiro é medição: coletar dados para avaliar a variabilidade deles nos cálculos de poder. A variância da sua própria métrica é insumo de todo tamanho de amostra que você vai calcular na vida, e um A/A te entrega ela na população, na instrumentação e na janela exatas em que você vai testar, em vez de vir de uma suposição de manual.

O segundo é validação: testar o sistema de experimentação, onde, nas palavras deles, a hipótese nula deve ser rejeitada cerca de 5% das vezes quando se usa um nível de confiança de 95%. Esse é o trabalho que a maioria dos times quer dizer quando fala em teste A/A, e é o que mais leem errado, porque aquela frase contém a dificuldade inteira. O comportamento correto de um sistema correto é produzir um resultado significativo de vez em quando.

O que um teste A/A pode e não pode te dizerUm teste A/A mede a variância da sua métrica para cálculos de poder e valida o pipeline de randomização, logging e análise. Ele não consegue confirmar a ausência de vieses pequenos, não valida a mudança que ainda não foi construída, e não certifica um sistema a partir de uma única rodada limpa.Um teste A/A é um detector de falha, e detector só reporta o que consegue verO que ele achaa variância real da sua métrica, no seu tráfegouma alocação diferente da que você pediulogging que perde evento em um braço e no outro nãoum hash que correlaciona braços entre experimentosuma taxa de rejeição longe do nível nominalO que ele não achaum viés menor do que a amostra resolvedefeito em código que o A/A não exercitanada, a partir de uma rodada só, sobre o sistemase a sua métrica é a métrica certaproblema que só aparece sob tratamento realA coluna da esquerda vale o tráfego. A da direita é por que “nosso A/A passou” não responde a “dá pra confiar nesse resultado”.
O valor de um A/A é assimétrico. Uma falha é evidência forte de defeito. Uma aprovação é evidência fraca de saúde, e o quão fraca depende inteiramente de quanto tráfego você deu a ele.

Por que um A/A significativo é o resultado esperado, não um alarme

Um teste a 95% de confiança é construído para rejeitar uma nula verdadeira 5% das vezes. Essa é a definição do limiar, não um defeito dele. Então a pergunta “nosso A/A voltou significativo?” é a pergunta errada. A certa é “nossa taxa de rejeição fica perto de 5% ao longo de muitas rodadas?”

Rode A/A suficiente e um significativo deixa de ser possível para virar provável:

Testes A/A rodados Chance de ao menos um voltar significativo
1 5,0%
2 9,8%
3 14,3%
5 22,6%
10 40,1%
20 64,2%
40 87,1%

Um time que roda um A/A semanal por um ano e trata cada semana significativa como incidente vai abrir umas duas ou três investigações sobre um sistema que está funcionando perfeitamente. Um time que roda um A/A, vê passar e declara a plataforma validada não aprendeu quase nada. O sinal de diagnóstico é a taxa, não a rodada. É também por isso que o A/A muito mais útil é um permanente, lido como taxa de rejeição de longo prazo, e não uma cerimônia avulsa antes do teste grande.

A direção do erro também importa. Uma taxa de rejeição materialmente acima de 5% quer dizer que algo está inflando as suas diferenças, e o levantamento de 2009 nomeia um culpado específico: robôs. Eles relatam casos em que robôs fizeram muitas métricas darem significativas quando não deveriam, com muito mais que 5% de falsos positivos num teste A/A, e notam que em alguns sites acredita-se que robôs geram até metade das páginas vistas. Uma taxa de rejeição materialmente abaixo de 5% também não é tranquilizadora, porque em geral significa variância superestimada, o que custa poder em silêncio em todo teste real que você roda.

Exemplo trabalhado: três rodadas de A/A e o que cada uma diz

Rode os números abaixo na calculadora enquanto lê. Cada um é um A/A no mesmo produto, a uma taxa base de conversão de 3%:

Calculadora de significância estatística
Controle (A)
Variação (B)
Controle (A) · Taxa-
Variação (B) · Taxa-
Melhora relativa-
valor-p-
IC 95% da diferença-

Teste z bilateral de duas proporções. "Sem significância" quase sempre quer dizer que falta amostra, não que as versões são iguais.

Rodada 1, a limpa. O controle recebe 40.000 usuários e 1.200 conversões (3,000%); o segundo braço recebe 40.130 usuários e 1.236 conversões (3,080%). A diferença é +0,08 ponto percentual, z = 0,66, valor-p 0,5096, intervalo de confiança de -0,16 a +0,32 ponto percentual. A divisão, 49,919% contra 50,081%, dá qui-quadrado 0,211, valor-p 0,646. Nada dispara. É assim que um A/A saudável se parece, e repare como aquele intervalo ainda é largo: ele é compatível com um viés real que vai de cerca de 5% relativo contra o segundo braço a cerca de 11% relativo a favor dele.

Rodada 2, a que “vence”. Os dois braços recebem 40.000 usuários; as conversões param em 1.200 e 1.300. Isso é +8,33% relativo, z = 2,03, valor-p 0,0422, intervalo de confiança de +0,01 a +0,49 ponto percentual. Formalmente significativo. A divisão é exatamente 50/50, qui-quadrado 0,000. Esta é a saída mais mal lida do assunto inteiro. Não existe tratamento, então o efeito não é real. Um braço teve mais sorte. A resposta correta é registrar e seguir, porque a tabela de taxas acima diz que isso acontece cerca de 1 rodada em 20 num sistema sem nada de errado. As respostas erradas são sair caçando um bug que não existe ou, pior, concluir que a plataforma “detectou uma diferença” e portanto funciona.

Rodada 3, a que importa. O controle recebe 40.000 usuários e 1.200 conversões; o segundo braço recebe 38.800 usuários e 1.210 conversões. A leitura de conversão está quieta: +3,95% relativo, z = 0,97, valor-p 0,3339, intervalo de -0,12 a +0,36 ponto percentual. Quem lê só o valor-p aprova esse teste. A divisão não está quieta: 50,761% contra 49,239% dá qui-quadrado 18,27, valor-p 0,0000191, muito além do limiar de 0,01 usado por convenção numa checagem de divisão. Cerca de 1.200 usuários que deveriam estar no segundo braço não estão lá.

Três rodadas de A/A lidas em duas checagens independentesA rodada um passa na checagem de conversão e na de divisão. A rodada dois reprova na de conversão por acaso com divisão perfeita, o que é esperado cerca de uma rodada em vinte. A rodada três passa na de conversão mas reprova na de divisão com valor-p de qui-quadrado de 0,0000191, e é a única das três que indica defeito real.As duas checagens respondem perguntas diferentes, e só uma delas achou bugrodadavalor-p de conversãovalor-p da divisãoo que significa1 limpa0,5096 passa0,646 passanenhum defeito detectável40.000 / 1.200 contra 40.130 / 1.236só nesta amostra2 sortuda0,0422 dispara1,000 passaruído, esperado 1 em 2040.000 / 1.200 contra 40.000 / 1.300registre, não investigue3 quebrada0,3339 passa0,0000191 disparadefeito real, pare e conserte40.000 / 1.200 contra 38.800 / 1.2101.200 usuários faltando num braço
A rodada 3 é a razão de fazer isso. Um time lendo só o valor-p de conversão teria aprovado um pipeline que estava perdendo usuários de um braço em silêncio, e depois rodado todo experimento seguinte em cima dele.

A checagem de divisão é a que paga o próprio custo

A razão de a rodada 3 ser a interessante é que as duas checagens não são redundantes. A leitura de conversão pergunta se a métrica difere. A checagem de divisão pergunta se a maquinaria entregou a alocação pedida, que é uma pergunta de encanamento que nenhuma comparação de métrica responde.

Fabijan e colegas, estudando divisão desigual de tráfego na Microsoft para o KDD 2019, encontraram que cerca de 6% dos experimentos na Microsoft apresentam um SRM, e observam que um produto rodando dez mil experimentos por ano pode esperar ver ao menos um por dia. O caso do MSN.com deles é especificamente uma história de A/A: um time observou um desbalanço num teste A/A, e a investigação achou um bug no serviço de atribuição em que o controle recebia um balde a menos que o necessário entre mil, de modo que um teste 50/50 estava na verdade montado como algo perto de 49,9/50,1, um desvio que eles descrevem, com razão, como não necessariamente um problema óbvio.

Esse caso também é uma aula sobre dimensionamento, porque um desvio de 0,1 ponto é muito difícil de ver:

Total de usuários no A/A Divisão observada a 49,9/50,1 Qui-quadrado Valor-p Apontado a 0,01?
80.000 39.920 / 40.080 0,32 0,572 não
200.000 99.800 / 100.200 0,80 0,371 não
500.000 249.500 / 250.500 2,00 0,157 não
1.000.000 499.000 / 501.000 4,00 0,046 não
2.000.000 998.000 / 1.002.000 8,00 0,0047 sim
5.000.000 2.495.000 / 2.505.000 20,00 0,0000077 sim

Um defeito desse tamanho precisa da ordem de dois milhões de usuários antes de uma checagem de rotina apontá-lo. Que é a leitura honesta de todo A/A limpo: ele descarta os vieses que a sua amostra conseguia ver, e não diz nada sobre os que ela não conseguia. A mecânica da checagem, os limiares e as causas-raiz usuais estão em SRM: divisão desigual de tráfego, e você pode rodar os seus próprios números no verificador de teste A/A grátis.

O artigo de 2019 também é útil pelo que diz sobre escopo. Ele lista três exigências para um serviço de atribuição: os usuários precisam ter a mesma probabilidade de ver cada variação, atribuições repetidas de um mesmo usuário precisam ser consistentes, e quando vários experimentos rodam não pode haver correlação entre eles. Violar qualquer uma das três pode causar um desbalanço, e um defeito no serviço de atribuição costuma aparecer em vários experimentos ao mesmo tempo, não em um. Então uma falha de divisão num A/A raramente é um problema local, e é exatamente isso que a torna valiosa de pegar ali.

Como dimensionar um A/A para que o resultado limpo signifique algo

Dimensionar um A/A é a mesma aritmética de dimensionar qualquer teste, com uma mudança de enquadramento: o efeito para o qual você calcula poder não é uma melhoria desejada, é o maior viés que você aceita deixar passar sem detectar. Escreva esse número primeiro, depois dimensione para ele.

Calculadora de tamanho de amostra
-Visitantes por variação
-Total (2 variações)
-Duração estimada

Cálculo por aproximação normal de duas proporções, 2 variações (50/50). Mexa nos campos e veja o impacto ao vivo.

A uma taxa base de 3%, veja o que um A/A limpo de fato descarta em diferentes tamanhos de amostra:

Usuários por braço Menor viés detectável a 80% de poder Em termos relativos
10.000 0,68 ponto percentual 22,5%
25.000 0,43 ponto percentual 14,2%
50.000 0,30 ponto percentual 10,1%
100.000 0,21 ponto percentual 7,1%
200.000 0,15 ponto percentual 5,0%
400.000 0,11 ponto percentual 3,6%

Leia essa tabela contra a rodada 1 lá em cima. Com 40.000 usuários por braço, aquele A/A tinha por volta de 68,0% de poder contra um viés relativo de 10% e cerca de 23,2% contra um de 5%. Em outras palavras, se a plataforma estivesse favorecendo um braço em 5% no silêncio, aquela rodada teria deixado passar em mais de três vezes em quatro. Chegar a 80% de poder para um viés relativo de 5% exige cerca de 207.938 usuários por braço. A mesma lógica vale para ler qualquer resultado inconclusivo, e está detalhada em efeito mínimo detectável.

Duas restrições práticas em cima da aritmética. Rode por pelo menos um ciclo semanal completo, para que tráfego de dia útil e de fim de semana estejam ambos dentro da janela em vez de cortados pela borda. E não pare o A/A cedo porque ele está parecendo limpo, pela mesma razão que você não pararia um teste real cedo: espiar um experimento em andamento repetidamente infla a taxa de falso positivo bem acima dos 5% nominais, que é exatamente o número que um A/A existe para medir. Esse mecanismo está em o problema do peeking.

Quando rodar um, e como ler o resultado

Situação Rodar um A/A? O que você está procurando
Ferramenta de experimentação nova, ou integração nova de uma existente Sim, antes do primeiro teste real Divisão correta, perda de evento, taxa de rejeição perto do nominal
Migração para novo pipeline de analytics ou data warehouse Sim Definições de métrica e joins que mudaram em silêncio
Randomização saiu do cliente para o servidor, ou o contrário Sim Consistência de atribuição em visitas repetidas
Um teste real produziu um resultado em que ninguém acredita Sim, mas como diagnóstico, não como veto Se o problema é a maquinaria e não o resultado
Rotineiramente, antes de cada experimento Não Tráfego gasto aqui é tráfego não gasto decidindo algo
Continuamente, em segundo plano O ideal, se a alocação couber Taxa de rejeição de longo prazo e estabilidade da divisão no tempo

E as regras de leitura, que importam mais que as de execução:

Erros comuns com testes A/A

Erro O que ele produz
Tratar um A/A significativo como prova de sistema quebrado Semanas depurando uma plataforma que está se comportando exatamente como desenhada
Tratar um A/A limpo como prova de sistema são Confiança falsa num pipeline por onde um viés pequeno passa direto
Checar só o valor-p de conversão, nunca a divisão A falha mais provável de ser real passa despercebida
Dimensionar o A/A por conveniência em vez de por viés tolerável Um resultado limpo que não descarta nada que alguém queira saber
Parar o A/A assim que ele parece limpo Peeking infla justamente a taxa de falso positivo que o teste existe para medir
Rodar o A/A numa semente compartilhada com um experimento no ar O A/A amostra a população daquele experimento em vez de sortear do zero
Reportar um braço do A/A como vencedor Um número sem causa por trás entra no registro de decisão
Rodar um A/A só uma vez, no lançamento da plataforma O pipeline que importa é o que você tem agora, não o que você tinha lá

Faça isso automático na Donnu

Um A/A só se paga se a checagem de divisão rodar toda vez e se a taxa de rejeição de longo prazo for algo que você consegue enxergar. A Donnu A/B roda a checagem de proporção de amostra em todo experimento, A/A ou não, e mostra uma divisão reprovada como sinalização de qualidade de dados que bloqueia a leitura, não como uma nota de rodapé embaixo do resultado. A atribuição é hasheada por experimento, então uma rodada de validação nunca herda a população de outro teste, e uma leitura inconclusiva reporta o intervalo de confiança, que é o que te diz quanto de viés aquela rodada conseguiu de fato descartar.

Comece um teste grátis de 14 dias e cheque a divisão do seu próximo experimento antes de ler o resultado.

Referências

Leia também: SRM: divisão desigual de tráfego · Significância estatística em teste A/B · Efeito mínimo detectável · O problema do peeking · Verificador de teste A/A grátis · Read in English

Perguntas frequentes

O que é um teste A/A?
Um teste A/A roda toda a sua maquinaria de experimentação a plena carga enquanto mostra exatamente a mesma experiência aos dois grupos. Kohavi e colegas (Data Mining and Knowledge Discovery, 2009), que também o chamam de teste nulo, descrevem dois usos: coletar dados para avaliar a variabilidade nos cálculos de poder, e testar o próprio sistema de experimentação, onde a hipótese nula deve ser rejeitada cerca de 5% das vezes a um nível de confiança de 95%. Qualquer diferença que ele reporte é, por construção, ruído ou defeito, porque não existe tratamento para causar uma diferença real.
Um teste A/A significativo quer dizer que o sistema está quebrado?
Não a partir de uma única rodada. A 95% de confiança, um sistema correto produz um A/A significativo cerca de 1 vez em 20 por desenho, então um resultado significativo é o comportamento esperado, não evidência de bug. O que importa é a taxa ao longo de muitas rodadas. Dez testes A/A dão cerca de 40,1% de chance de ao menos um voltar significativo, e vinte dão cerca de 64,2%. Julgue o sistema pela taxa de rejeição de longo prazo estar perto de 5%, e investigue uma rodada isolada só se a checagem de divisão também falhar.
Quanto tempo um teste A/A deve rodar?
O suficiente para detectar o tamanho de viés que você realmente se importa, o que costuma ser muito mais que os times esperam. A uma taxa base de 3% com 40.000 usuários por braço, o teste tem cerca de 68% de poder contra um viés relativo de 10%, mas só cerca de 23,2% contra um de 5%, então um resultado limpo nesse tamanho descarta muito pouco. Chegar a 80% de poder para um viés relativo de 5% exige cerca de 207.938 usuários por braço. Rode por pelo menos um ciclo semanal completo, para que o efeito de dia da semana caiba dentro da janela em vez de ficar cortado nela.
O que um teste A/A aprovado realmente prova?
Bem menos do que a maioria dos times supõe. Ele é um detector de falha, não um certificado. Um A/A limpo diz que o pipeline não produziu viés detectável no tamanho de amostra que você rodou, o que deixa muito espaço para um viés menor do que essa amostra consegue resolver. O caso do MSN.com documentado por Fabijan e colegas (KDD 2019) é a ilustração mais clara: um bug atribuiu ao controle um balde a menos que o necessário, virando um teste 50/50 em algo perto de 49,9/50,1, e uma divisão torta nesse nível precisa da ordem de dois milhões de usuários antes de um qui-quadrado apontar no limiar usual de 0,01.
Devo checar a divisão de tráfego ou a taxa de conversão?
As duas, e a checagem de divisão é a que paga o próprio custo. A leitura de conversão num A/A só dispara na taxa nominal de falso positivo e diz pouca coisa quando dispara. A checagem de divisão testa algo que a leitura de conversão não enxerga: se a randomização e o logging entregaram a alocação que você pediu. Fabijan e colegas (KDD 2019) encontraram que cerca de 6% dos experimentos na Microsoft apresentam SRM, e um defeito no serviço de atribuição costuma aparecer em vários experimentos ao mesmo tempo, não em um.
Posso rodar um teste A/A junto com experimentos reais?
Pode, e um A/A rodando permanentemente é o arranjo mais útil, desde que a atribuição dele seja sorteada de forma independente de todo outro experimento. Kohavi e colegas (2009) mostraram que alguns esquemas de hash falham exatamente nessa exigência de independência, então um A/A que compartilha semente com um teste no ar pode herdar a população daquele teste em vez de sortear do zero. Rode continuamente, alerte pela taxa de rejeição de longo prazo em vez de por qualquer janela isolada, e trate uma falha de divisão como incidente de plataforma.
Teste A/A é a mesma coisa que um teste A/B sem mudança?
Mecanicamente sim, e é justamente esse o ponto: o valor vem de colocar o pipeline inteiro sob carga com uma resposta certa conhecida. A diferença está em como você lê. Num teste A/B um resultado significativo é um achado candidato; num A/A ele só pode ser ruído ou defeito. Essa inversão é o que faz do A/A um diagnóstico, e é também por que um A/A nunca deve ser reportado com o vocabulário de um vencedor.