Estatística

Teste de Permutação em Teste A/B: p-valor sem fórmula

O teste de permutação embaralha os rótulos e monta a distribuição nula com os seus próprios dados. Quando ele salva um teste A/B e quando não muda nada.

Ilustração plana de duas tigelas verdes lado a lado com pequenas pedras idênticas atravessando o ar em arco de uma para a outra, sobre fundo verde menta

O teste de permutação calcula o valor-p embaralhando os rótulos de controle e variação milhares de vezes em cima dos seus próprios dados, em vez de assumir que a diferença entre médias segue uma normal. Ele não é mais preciso sempre: numa divisão 50/50 com métrica bem comportada, ele devolve praticamente o mesmo número do teste z. Ele salva o resultado exatamente onde a aproximação normal quebra, e a simulação deste artigo mostra o tamanho do estrago: numa rampa de 1 por cento com receita por usuário, o teste z rejeitou 16,44 por cento dos testes A/A a um alfa nominal de 5 por cento, enquanto o teste de permutação ficou em 4,78 por cento. Este guia mostra como a conta funciona, onde ela importa, como rodar e o que ela não conserta. Faz parte do nosso guia completo de teste A/B e completa o que já dissemos sobre significância estatística.

A ideia do teste de permutação, em uma frase

Você tem 800 visitantes no controle com 24 conversões e 800 na variação com 36. A pergunta do teste é: se o rótulo “controle” ou “variação” não fizesse diferença nenhuma, com que frequência um sorteio aleatório desses 1.600 visitantes em dois grupos de 800 produziria uma diferença tão grande quanto a que você viu?

O teste z responde isso com uma fórmula que aproxima essa distribuição por uma normal. O teste de permutação responde a mesma pergunta literalmente: ele faz o sorteio, muitas vezes, e conta.

Como o teste de permutação monta a distribuição nulaDiagrama em três colunas. À esquerda, duas caixas empilhadas rotuladas controle e variação, com a diferença observada anotada ao lado. Ao centro, uma seta indica que as observações dos dois grupos são jogadas num balde único e os rótulos são embaralhados. À direita, três caixas menores empilhadas mostram três sorteios diferentes com diferenças embaralhadas, e abaixo delas uma linha diz que a fração de sorteios com diferença tão extrema quanto a observada é o valor-p.A permutação refaz o sorteio que você já fez, milhares de vezescontrole: 24 de 800variação: 36 de 800diferença observada1,5 ponto percentual1.600 observaçõesnum balde sórótulos embaralhadossorteio 1: diferença 0,4 ppsorteio 2: diferença 1,7 ppsorteio 3: diferença 0,9 ppe assim por 100.000 vezesvalor-p = fração dos sorteios cuja diferença embaralhada foi tão grande quanto a observadaneste caso, 14.667 de 100.000 sorteios
O procedimento inteiro. Nenhuma distribuição é assumida: a distribuição nula é construída a partir das observações que você já tem.

A justificativa formal é a mesma que sustenta o experimento. Guo, Lee e Toulis registram que a abordagem remonta a Fisher, em 1935, e que procedimentos desse tipo são válidos em amostra finita para distribuições de dados arbitrárias, porque exploram a variação conhecida na atribuição dos tratamentos, e não uma suposição sobre a população. Quem sorteou o tráfego foi você; o teste apenas repete esse sorteio.

Onde a fórmula fechada quebra

A resposta honesta é: menos vezes do que o folclore sugere. Um teste A/B típico, com divisão 50/50 e centenas de milhares de usuários, não precisa de permutação. Nós medimos isso.

O experimento simulado: receita por usuário, 4 por cento dos usuários compram, a compra segue uma lognormal, e o total de 20.000 usuários é dividido em proporções diferentes entre controle e variação. A métrica é violentamente assimétrica (o coeficiente de assimetria da amostra combinada fica em torno de 15, e a regra de bolso de Kohavi e coautores pediria cerca de 81.000 observações por braço só para a média ser aproximadamente normal). Rodamos milhares de testes A/A, ou seja, testes em que os dois braços vêm exatamente da mesma distribuição e qualquer resultado significante é falso positivo.

divisão controle/variação usuários no controle usuários na variação teste z: cauda “variação pior” teste z: cauda “variação melhor” teste z: total permutação: total réplicas
50/50 10.000 10.000 2,40% 2,45% 4,85% 5,00% 4.000
80/20 16.000 4.000 3,45% 1,27% 4,72% 4,13% 4.000
90/10 18.000 2.000 5,43% 0,75% 6,18% 5,12% 6.000
99/1 19.800 200 16,35% 0,09% 16,44% 4,78% 8.000

O nominal é 5 por cento no total e 2,5 por cento em cada cauda. Leia a tabela de cima para baixo:

Na divisão 50/50, o teste z está certo. 4,85 por cento contra um alvo de 5 por cento, com as duas caudas equilibradas, mesmo com assimetria de 15 e uma amostra sete vezes menor do que a regra de bolso pediria. Isso não é sorte: Kohavi e coautores fazem exatamente essa ressalva no artigo em que publicam a regra. Com divisão de tamanhos iguais, a distribuição da diferença fica aproximadamente simétrica, e é perfeitamente simétrica com assimetria zero sob a hipótese nula, então a regra deixa de dar um limite inferior útil. A assimetria da métrica se cancela entre os dois braços.

Conforme a divisão desequilibra, as caudas se desequilibram junto. Em 90/10 o total ainda parece quase aceitável (6,18 por cento), mas ele esconde uma cauda de 5,43 por cento contra 0,75 por cento. Ou seja: o teste erra quase sempre para o mesmo lado, declarando que o braço pequeno está pior.

Em 99/1 o resultado é indefensável. Um em cada seis testes A/A produz um resultado significante, e 16,35 dos 16,44 pontos vêm da cauda “o braço de 1 por cento está pior”. O teste de permutação, nos mesmos dados, ficou em 4,78 por cento, dentro do erro Monte Carlo da simulação (com 8.000 réplicas, o erro-padrão em torno de 5 por cento é 0,24 ponto percentual).

Falso positivo real em testes A/A por divisão de tráfegoGráfico de barras agrupadas com quatro grupos no eixo horizontal, um para cada divisão de tráfego: 50 barra 50, 80 barra 20, 90 barra 10 e 99 barra 1. Em cada grupo há duas barras, a escura para o teste z e a clara para o teste de permutação. Uma linha tracejada horizontal marca o nível nominal de 5 por cento. As barras do teste z ficam em 4,85, 4,72, 6,18 e 16,44 por cento, crescendo muito no último grupo. As barras da permutação ficam em 5,00, 4,13, 5,12 e 4,78 por cento, todas próximas da linha de 5 por cento.Quanto mais desigual a divisão, mais o teste z se afasta do alfa que promete0%5%10%15%alfa nominal de 5%50/504,855,0080/204,724,1390/106,185,1299/116,444,78teste zteste de permutação
Taxa real de falso positivo em testes A/A com receita por usuário fortemente assimétrica, 20.000 usuários por réplica. Quanto mais desigual a divisão, mais o teste z se distancia do nível que promete.

A conclusão prática é específica e não é “abandone o teste z”. É: em rampa de exposição, que é justamente quando você roda 1 por cento ou 5 por cento do tráfego numa variação nova, a leitura por aproximação normal de uma métrica de receita é o pior cenário possível, e ela erra sistematicamente contra a variação. É o mesmo cuidado que já pedimos ao falar de SRM e divisão desigual de tráfego, só que aqui o problema não é o sorteio, é a leitura.

O exemplo trabalhado: um teste de baixo tráfego

O segundo lugar onde a fórmula fechada erra é o mais comum de todos: contagens pequenas. Considere um teste de baixo volume, 800 visitantes por variação, 24 conversões no controle (3,000 por cento) e 36 na variação (4,500 por cento), um ganho relativo aparente de 50 por cento.

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.

Colando esses números na calculadora acima, o teste z devolve z de 1,5791, valor-p de 0,11432 e intervalo de 95 por cento da diferença de menos 0,3604 a mais 3,3604 pontos percentuais. Sem significância.

Rodando o teste de permutação nos mesmos dados, com 100.000 embaralhamentos, 14.667 deles produziram uma diferença absoluta tão grande quanto a observada. O valor-p sai em 0,14668.

Aqui a conta tem uma checagem forte disponível: no caso binário com as marginais fixas, o teste de permutação converge para o teste exato de Fisher, que é calculável analiticamente pela distribuição hipergeométrica. O valor exato é 0,147193. A nossa aproximação Monte Carlo ficou a 0,00051 dele, e o erro-padrão Monte Carlo esperado com 100.000 embaralhamentos é 0,00112. A permutação acertou o alvo dentro de meio erro-padrão.

método valor-p como foi obtido
teste z (aproximação normal) 0,11432 fórmula fechada, a mesma da calculadora acima
qui-quadrado com correção de Yates 0,14776 fórmula fechada com correção de continuidade
permutação Monte Carlo, 100.000 sorteios 0,14668 embaralhamento dos rótulos
teste exato de Fisher 0,14719 hipergeométrica, sem simulação

A leitura: a aproximação normal devolve um valor-p 22 por cento menor do que o exato, e é sempre nessa direção com contagens desse tamanho. Num teste que já não é significante, isso é irrelevante. Num teste que ficou em 0,048 pela fórmula e 0,061 pelo exato, isso é a diferença entre publicar uma variação e não publicar. Repare também que a correção de Yates, que é fórmula fechada e roda em uma linha, chegou a 0,14776, praticamente no exato: em tabela 2 por 2 ela é um substituto barato e muito bom para a permutação. Isso é especialmente relevante para quem faz CRO em site de baixo tráfego, onde dezenas de conversões é o cenário normal e não a exceção.

Como rodar, em 15 linhas

O algoritmo cabe numa função. Este é o código que gerou os números acima, e ele não depende de biblioteca nenhuma:

function permutationP(controle, variacao, B, rand) {
  const balde = controle.concat(variacao);
  const n = balde.length, nA = controle.length;
  const media = (a) => a.reduce((s, x) => s + x, 0) / a.length;
  const observado = Math.abs(media(variacao) - media(controle));
  let extremos = 0;
  for (let k = 0; k < B; k++) {
    for (let i = n - 1; i > 0; i--) {          // embaralha o balde
      const j = Math.floor(rand() * (i + 1));
      [balde[i], balde[j]] = [balde[j], balde[i]];
    }
    let somaA = 0; for (let i = 0; i < nA; i++) somaA += balde[i];
    let somaB = 0; for (let i = nA; i < n; i++) somaB += balde[i];
    const dif = Math.abs(somaB / (n - nA) - somaA / nA);
    if (dif >= observado - 1e-12) extremos++;
  }
  return (extremos + 1) / (B + 1);            // Phipson e Smyth, 2010
}

Três detalhes que separam a implementação certa da errada:

O mais 1 no numerador e no denominador não é uma manha, é a conta correta. Phipson e Smyth mostraram que a versão ingênua, dividir a contagem por B, subestima o valor-p em cerca de 1 sobre B e aumenta a taxa de erro tipo I do teste. O argumento dos autores é que a permutação não estima a probabilidade de cauda de uma distribuição contínua: ela gera uma distribuição nula discreta exata, e a estatística observada é ela mesma um dos resultados possíveis. Somar 1 aos dois lados também elimina o absurdo de reportar valor-p exatamente zero.

A estatística tem que ser recalculada em cada sorteio, inclusive o denominador. Se você fixar a variância estimada nos dados originais e só embaralhar as médias, perde a propriedade que faz o método funcionar.

Use maior ou igual, não maior. A comparação com a estatística observada precisa incluir os empates, senão o teste fica anticonservador em métricas discretas.

Quantos embaralhamentos

A permutação Monte Carlo tem um erro próprio, e ele é fácil de dimensionar: o número de sorteios extremos é uma binomial, então o erro-padrão de um valor-p estimado em p é a raiz de p vezes (1 menos p) sobre B.

embaralhamentos (B) erro-padrão em p perto de 0,05 meia largura do IC 95% menor valor-p possível
999 0,00690 0,01351 0,001000
9.999 0,00218 0,00427 0,000100
99.999 0,00069 0,00135 0,000010
999.999 0,00022 0,00043 0,000001

Com mil embaralhamentos, um valor-p estimado em 0,05 vem com um intervalo que vai de 0,036 a 0,064: você não sabe de que lado do limiar está. Dez mil já resolvem a decisão binária de significância. Cem mil valem quando você vai publicar o número, e só fazem diferença real quando o valor-p é pequeno. E note a última coluna: o menor valor-p que você consegue reportar é 1 sobre (B mais 1), então “p menor que 0,001” exige no mínimo 999 embaralhamentos, por definição, independentemente do quanto os dados são convincentes.

O que a permutação não conserta

Esta é a parte que os textos entusiasmados costumam pular. O teste de permutação corrige uma coisa: a aproximação da distribuição nula. Ele não corrige nada do que vem antes dela.

O que o teste de permutação cobre e o que fica de foraDiagrama de uma faixa horizontal dividida em cinco etapas de um teste A/B, da esquerda para a direita: sorteio do tráfego, coleta e rastreamento, definição da métrica, cálculo da distribuição nula e decisão. Apenas a quarta etapa, cálculo da distribuição nula, está destacada em cor sólida com a marcação de que é o que a permutação conserta. As outras quatro estão em cinza claro com a marcação de que continuam sendo responsabilidade do desenho do experimento.A permutação atua numa etapa só do teste1. sorteiodo tráfego2. coleta erastreamento3. definiçãoda métrica4. distribuiçãonula5. decisãode negócioa permutação conserta estaSRM, perda de rastreamento, interferência e métrica errada continuam intactose nenhum embaralhamento os revela
O teste de permutação troca a fórmula da distribuição nula pela distribuição empírica. Tudo o que acontece antes disso continua sendo problema do desenho.

Em concreto:

Checklist de aplicação

  1. Divisão 50/50 e métrica binária com centenas de conversões por braço: use a fórmula. A permutação não vai mudar a terceira casa decimal.
  2. Menos de umas 100 conversões por braço: confira o valor-p com Fisher exato ou qui-quadrado com Yates antes de decidir. São fórmulas fechadas e a diferença já é material.
  3. Métrica contínua ou de contagem com divisão desigual (rampa de 1, 5 ou 10 por cento): permutação, sem discussão. É onde o teste z erra mais, e erra sempre contra o braço pequeno.
  4. Estatística sem fórmula fechada (diferença de medianas, diferença de quantis, razão de razões): permutação para o valor-p, bootstrap para o intervalo.
  5. Embaralhe na unidade do sorteio. Se sorteou usuário, permute usuários inteiros, com todos os eventos deles juntos.
  6. Fixe a semente do gerador e publique B. Um valor-p Monte Carlo sem o número de embaralhamentos é um número sem precisão declarada.
  7. Use (b mais 1) sobre (B mais 1). Sempre.

Faça isso automático na Donnu

O motivo pelo qual quase ninguém roda teste de permutação não é teórico, é operacional: exige guardar as observações no nível da unidade de sorteio, e não só os totais agregados. Quem só tem “visitantes e conversões” numa planilha não consegue permutar nada, porque a informação individual já foi jogada fora na agregação.

A Donnu guarda o evento no nível do usuário sorteado, então a distribuição nula empírica é calculável sobre qualquer métrica do experimento, não só sobre a taxa de conversão. Na prática isso significa poder ler uma rampa de 1 por cento sem o viés de 16 por cento de falso positivo que a tabela deste artigo mostra, e poder testar diferença de mediana sem inventar uma fórmula para ela. Se você está começando agora, comece pelo mais barato: rode a calculadora de significância e, se a contagem for baixa, confira com Yates antes de decidir.

Referências

Leia também: Significância estatística em teste A/B · Outliers e capping · Unidade de sorteio · CRO para sites de baixo tráfego · SRM e divisão desigual · Calculadora de significância · Read in English

Perguntas frequentes

O que é um teste de permutação em teste A/B?
É um jeito de calcular o valor-p sem usar fórmula fechada. Você junta as observações dos dois grupos num único balde, sorteia repetidas vezes quais delas ficariam no controle e quais na variação, recalcula a diferença em cada sorteio e vê em que fração dos sorteios a diferença embaralhada foi tão grande quanto a que você observou de verdade. Essa fração é o valor-p. A ideia é de Fisher, em 1935, e é a mesma aleatorização que você já usou para montar o experimento.
Quando o teste de permutação muda o resultado de um teste A/B?
Quando a aproximação normal do teste z está ruim. Isso acontece em duas situações típicas: contagens pequenas (dezenas de conversões, não milhares) e divisão de tráfego muito desigual em métrica assimétrica, como uma rampa de 1 por cento em receita por usuário. Na simulação deste artigo, com divisão 99/1, o teste z rejeitou 16,44 por cento dos testes A/A a um alfa nominal de 5 por cento, e o teste de permutação rejeitou 4,78 por cento.
Quantas permutações são necessárias?
Depende da precisão que você quer perto do seu limiar de decisão. Com 10.000 permutações, o erro-padrão de um valor-p perto de 0,05 é 0,0022, ou seja, o intervalo de 95 por cento em torno da estimativa tem meia largura de 0,0043. Com 1.000 permutações essa meia largura sobe para 0,0135, larga demais para decidir em cima de 0,05. Para publicar um valor-p abaixo de 0,001 você precisa de pelo menos 999 permutações, porque o menor valor possível é 1 dividido por (B mais 1).
Por que somar 1 no numerador e no denominador do valor-p?
Porque a estatística observada é ela própria uma das permutações possíveis. Phipson e Smyth mostraram que a conta ingênua, dividir a contagem pelo número de permutações, subestima o valor-p em cerca de 1 sobre o número de permutações e aumenta o erro tipo I do teste. A forma correta é somar 1 aos dois: (b mais 1) dividido por (B mais 1). Isso também impede o resultado absurdo de um valor-p exatamente zero.
Teste de permutação resolve viés de amostragem ou SRM?
Não. Ele conserta a aproximação da distribuição nula, e só isso. Se o sorteio quebrou, se um dos grupos perdeu eventos por falha de rastreamento ou se existe interferência entre as variações, os dados já estão contaminados antes da conta, e embaralhar rótulos contaminados devolve um valor-p corretamente calculado sobre um experimento errado. A hipótese que o teste de permutação exige é a de permutabilidade sob a nula, e ela cai junto com o sorteio.
Qual a diferença entre permutação e bootstrap?
A permutação embaralha rótulos sem repor e responde uma pergunta de teste: qual a chance de ver uma diferença desse tamanho se o rótulo não importasse. O bootstrap reamostra com reposição dentro de cada grupo e responde uma pergunta de estimativa: qual a incerteza em torno do efeito medido. Na prática você usa os dois, permutação para o valor-p e bootstrap para o intervalo de confiança, porque a permutação sozinha não entrega intervalo.