Pourquoi et comment utiliser le tracé Bland-Altman pour les tests A /B / Python + code

Pourquoi utiliser le tracé Bland-Altman

Le tracé Bland-Altman provient de l’industrie médicale afin de comparer la mesure pour deux instruments. Le premier objectif de John Martin Bland & Douglas Altman était de répondre à cette question :

Les deux méthodes de mesure s’accordent-elles suffisamment ? – D. G. ALTMAN et J. M. FADE

Si c’est le cas, cela signifie que si vous disposez de deux instruments dont l’un est l’état de la technique à un coût élevé et le second est 10 fois moins cher, les résultats obtenus par la méthode la moins chère sont-ils comparables à la référence et pourraient-ils être remplacés avec une précision suffisante? Par exemple, la fréquence cardiaque fournie par une montre connectée à 20 $ est-elle suffisamment précise à la suite d’un électrocardiogramme? Le deuxième objectif était de produire une méthode où les résultats seraient facilement compréhensibles pour les non-statisticiens.

En analytique, le test A/B (aussi connu sous le nom de Champion-Challenger) est une méthodologie courante de test permettant de comparer les résultats d’une nouvelle action / d’un nouveau traitement / d’un nouveau design / … sur population_A à population_B ayant l’action actuelle. Une fois que nous avons les résultats du test, ils doivent être analysés et présentés à une équipe décisionnelle composée principalement de non-statisticiens. C’est pourquoi le tracé Fade-Altman est pertinent car il comparera les résultats du test A / B sur un tracé avec toutes les mesures statistiques affichées de manière compréhensible.

Dans leur article, ils ont également montré pourquoi le coefficient de corrélation, le test statistique de comparaison moyenne et la régression sont inappropriés pour décider de l’accord de deux mesures qui seraient dans notre cas de test A / B pour décider de la puissance du challenger par rapport à celle du champion.

Les données utilisées

Pour cet article, j’utiliserai un jeu de données disponible sur Kaggle (issu d’un projet DataCamp) appelé « Test A/B des Jeux Mobiles avec des chats Cookies ». Le lien se trouve dans la partie références.

Cookie Cats est un jeu de puzzle mobile populaire où, au fur et à mesure qu’un joueur progresse dans les niveaux, il rencontrera des « portes » qui le forceront à attendre un certain temps avant de continuer à jouer ou de faire un achat. Dans une telle industrie, la rétention est l’un des paramètres clés et l’équipe en charge du jeu verrait l’impact si la première porte était déplacée du niveau 30 au niveau 40 sur la rétention à 7 jours. Pour voir le comportement d’un tel mouvement, ils ont fait un test A / B et ils nous ont fourni l’ensemble de données de ces résultats. Nous verrons comment l’intrigue Fade-Altman répondra à la question suivante :  » Comment analyser les résultats A/B sur le niveau de rétention à 7 jours lorsque le temps d’attente passe du niveau 30 au niveau 40 ? »

L’ensemble de données est composé de 90.189 lignes où nous avons l’identifiant unique du joueur, la version du test A / B (temps d’attente à gate_30 /gate_40), la somme des tours de jeu, retention_1 est un dicton booléen si le joueur est revenu le lendemain et retention_7 est un dicton booléen si le joueur est revenu après 7 jours. Afin d’avoir les données pertinentes pour répondre à notre question, il est nécessaire de faire un peu de nettoyage. Je ne garderai que le client ayant un retention_1= True (car si retention_1 = False, retention_7 est également Faux), un nombre de tours de jeu ≥ 30 (car s’ils ne vont pas jusqu’à 30, ils ne seront pas impactés par la porte) et un nombre de tours de jeu < 170 (car si on considère la durée d’une partie = 5 minutes, si un joueur joue 2 heures par jour pendant 7 jours, il jouera 120 * 7/5 = 168 parties. Un nombre plus élevé serait considéré comme une utilisation anormale). Après ce filtre, l’ensemble de données est composé de 20.471 lignes comme Figure1 ci-dessous. De plus, l’ensemble de données est également équilibré entre gate_30 & gate_40.

Figure1. Jeu de données CookieCats

Comment est construit le tracé Bland-Altman

Nous verrons dans cette section comment adapter le tracé Bland-Altman d’origine afin de l’appliquer à un test A/B. Tout d’abord, je vais expliquer comment l’intrigue est-elle construite dans sa version originale, puis, je vais expliquer comment la construire avec les données de nos tests A / B.

Du fait que le tracé original de Bland-Altman compare la mesure de 2 instruments, ils ont la même longueur par conception. Par exemple, avec la mesure de la fréquence cardiaque entre la montre $20 connect et l’électrocardiogramme, les mesures sont prises en même temps avec les mêmes conditions qui conduisent à avoir le même nombre de mesures pour les 2 méthodes. Nous pouvons donc représenter la ligne de chaque ensemble de données comme une expérience comme sur l’exemple de la Figure2 ci-dessous.

Figure2. Mesure de l’instrument par expérience

C’est là que nous rencontrons le premier « point douloureux ». Un test A / B est considéré comme une expérience unique alors que comme nous le voyons ci-dessus, nous avons besoin de plusieurs expériences pour construire l’intrigue. Pour contourner cette limitation, nous allons créer à partir du test A / B plusieurs échantillons amorçés ayant tous les deux la même longueur & différente.

Nous générons 300 entiers aléatoires non uniques entre 200 et 1.000. Ces entiers représenteront la longueur de chaque échantillon bootstrap et afin de bénéficier des propriétés statistiques du bootstrap, chaque entier aléatoire non unique est dupliqué 50 fois. Ces nombres sont utilisés pour avoir une diversité d’échantillon, mais ils sont arbitraires et la longueur dépend de la taille de l’ensemble de données d’origine. Ces 15.000 (300 * 50) échantillons bootstrappés d’une longueur comprise entre 200 et 2.000 sont obtenus par un échantillonnage aléatoire avec un remplacement de l’ensemble de données d’origine et ils sont concaténés ensemble. Il peut être représenté comme la Figure3.

Figure3. Construction d’un ensemble de données amorçé

Le code suivant crée l’ensemble de données amorçé à partir des données d’origine (attention, cela peut prendre du temps car l’ensemble de données amorçé a une longueur de 9.184.350 lignes {en changeant l’état aléatoire, nous aurions en moyenne (((200+1.000)/2)*300*50 = 9.000.000 lignes }).

Ensuite, nous groupons par n_échantillon (l’id de chaque 15.000 échantillon bootstrap), n_sample_2 (la longueur de chaque échantillon bootstrap) et la version afin d’avoir la somme de la rétention du joueur à 7 jours par portes comme sur la figure 4.

Figure4. Ensemble de données bootstrappées après groupepar

On peut lire cette sortie comme suit : l’échantillon bootstrapped n°0/14.999 est composé de 564 lignes où 98 joueurs jouent encore à 7 jours avec un temps d’attente à gate_30 tandis que 105 joueurs jouent encore à 7 jours avec un temps d’attente à gate_40.

Ensuite, nous utilisons une propriété statistique du boostrap disant que la moyenne d’un échantillon bootstrap est un bon estimateur de la vraie moyenne d’une distribution. Nous faisons un groupe par n_sample_2 et version afin d’avoir pour chaque longueur d’échantillon unique le nombre moyen de rétention des joueurs à 7 jours par portes comme sur la figure 5.

Figure5. Nombre moyen de joueurs jouant encore à 7 jours pour chaque longueur d’échantillon unique et par portes

Nous pouvons lire cette sortie comme: lorsque l’échantillon a 200 lignes, il y a en moyenne 34,60 joueurs qui jouent encore à 7 jours avec un temps d’attente à gate_30 tandis que 34,38 joueurs qui jouent encore à 7 jours avec un temps d’attente à gate_40.

Ensuite, nous décompressons la base de données afin d’avoir l’ensemble de données dans un format plus clair que la Figure6.

Figure6. Version non découpée de l’ensemble de données

À ce stade, nous disposons de toutes les informations nécessaires pour construire le tracé de Bland-Altman et la représentation de l’ensemble de données est la même que dans la Figure2 ci-dessus.

Le tracé Fade-Altman est composé de 2 axes. L’axe X est la moyenne des deux méthodes à comparer. Il en est ainsi pour chaque ligne : (gate_30i + gate_40i) / 2 ||| L’axe y est la différence entre la méthode A et la méthode B. C’est donc pour chaque ligne: (gate_30i -gate_40i) ||| Et voici le deuxième « point douloureux » que nous avons. En gardant l’axe y tel quel, l’augmentation de la taille des échantillons augmentera la variabilité des différences. Par conséquent, la mesure statistique que nous obtiendrons plus tard sera surestimée par les échantillons les plus importants. Pour contourner cette limitation, nous représenterons l’axe y en pourcentage. Pour ce faire, le calcul de y est pour chaque ligne: ((gate_30i -gate_40i) *100 /((gate_30i + gate_40i) /2) ||| L’ensemble de données ressemble à Figure7.

Figure7. x & axe y

Nous devons vérifier que l’axe y est normalement distribué afin de faire confiance à l’intervalle de confiance qui sera affiché. Vous pouvez l’évaluer en utilisant le test de shapiro-wilk ou au moins avec un histogramme. Si la distribution n’est pas normale, vous pouvez effectuer une transformation telle qu’une transformation logarithmique. Dans notre cas, je considère la distribution comme normale.

Figure8. Histogramme de l’axe y

Le Fade-Altman est composé de 3 lignes (voir Figure9):

  • les valeurs moyennes de y
  • la borne supérieure du y de l’intervalle de confiance (ici à 95% étant donné le 1,96)
  • la borne inférieure du y de l’intervalle de confiance (à 95%)

Figure9. Valeurs du tracé de Bland-Altman

Que nous mettons tous ensemble, le paquet pyCompare permet de dessiner le tracé de Bland-Altman de manière très simple sans avoir à construire de base de données:

Il faut d’abord la méthode A (le champion) puis la méthode B (le challenger). Ensuite, si pourcentage = Vrai, il fera automatiquement le calcul que nous avons fait ci-dessus. Il y a d’autres paramètres dont nous discuterons plus tard.

Comment interpréter le tracé Fade-Altman pour le test A / B

Nous y sommes! Voici la figure du tracé Fade-Altman pour les tests A / B générés par le code ci-dessus:

Figure10. Graphique de Bland-Altman appliqué pour le test A / B

Tout d’abord, la moyenne et l’intervalle de confiance de la moyenne (bande bleu clair) sont différents de 0 (plus élevé dans notre cas). Ce qui signifie que le niveau de rétention (nommé biais dans le document d’origine) de gate_30 et gate_40 sont significativement différents. En raison du fait que 2,93 > 0 cela signifie qu’un > B <— > Champion > Challenger et par conséquent qu’une période d’attente sur gate_30 fournit une rétention plus grande qu’une période d’attente sur gate_40.

Les deux barres de saumon représentent l’intervalle de confiance à 95% (nommé limite d’accord dans l’article original) en disant que nous sommes convaincus que 95% des valeurs seront comprises entre. Dans notre exemple, c’est très puissant car on peut dire que la rétention de gate_30 sera presque toujours plus grande que celle de gate_40.

Comme vous pouvez le voir, il y a 2 valeurs au-dessus de la bande supérieure du saumon et 4 en dessous de la bande inférieure, soit 6/300 = 0,02 < 0.05 donc parce que nous sommes certains que 95% des valeurs sont dans les 2 limites, 5% peuvent être au-dessus ou en dessous et dans notre cas cela représente 2% alors c’est parfaitement normal 😉

Dans le paquet pyCompare il y a le paramètre limitOfAgreement qui vise à changer les limites de confiance. Ici, une question pertinente serait: « À quel pourcentage puis-je être sûr que la rétention de gate_30 sera toujours plus grande que celle de gate_40? »Pour répondre à cette question, la limite la plus basse doit être égale à 0, nous devons donc trouver la bonne valeur pour avoir 0 comme nous pouvons le voir dans le code ci-dessous qui fournit la Figure11:

Figure11. Sortie lors de la modification du paramètre

de limitOfAgreement, nous voyons que lorsque limitOfAgreement = 1,55, la limite est presque égale à 0. Ensuite, nous devons vérifier dans la table de distribution normale la valeur à 1,55 qui est 0,9394, nous sommes donc sûrs de ((1-0.9394)*2)*100 = 87.88% que la rétention de gate_30 sera toujours plus grande que celle de gate_40

Un dernier point à ajouter est que quelle que soit la valeur moyenne de l’échantillon, ils sont uniformément représentés sur le graphique ce qui signifie que l’interprétation que nous faisons est généralisée quelle que soit la taille de l’échantillon. En effet, si nous avions vu une sorte de représentation conique des valeurs, nous aurions pu conclure que la taille de l’échantillon a un impact sur les résultats, nous ne pouvons donc pas avoir d’interprétation valide.

Conclusion

Nous avons vu pourquoi il peut être pertinent d’utiliser le tracé Bland-Altman afin d’avoir une vue sur les résultats d’un test A / B sur un tracé simple, comment créer le tracé à partir d’un test A / B et comment l’interpréter. Cela ne fonctionne qu’en cas de normalité de la différence cependant il faudra transformer les données.

De plus, j’ai vérifié l’application et les portes semblent être sur gate_40 alors que nous avons prouvé que la rétention à 7 jours était meilleure à 30. Dans ce cas, cela montre que la rétention n’est peut-être pas la meilleure mesure à suivre par rapport à la rentabilité!

D. G. Altman et J. M. Bland, Mesure en médecine: l’Analyse des Études de Comparaison de Méthodes, Le Statisticien 32 (1983) 307-317

https://projects.datacamp.com/projects/184 OU https://www.kaggle.com/yufengsui/mobile-games-ab-testing

D. G. Altman et J. M. Bland, Méthodes Statistiques pour Évaluer l’Accord entre Deux Méthodes de Mesure Clinique, The Lancet 327 (1986) 307-310

D. Giavarina, Comprendre l’analyse fade d’Altman, Biochemia Medica 25 (2015) 141-151

You might also like

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.