Février 2017
Volume 32, numéro 2
Cet article a fait l'objet d'une traduction automatique.
Série de tests - Le test des signes avec C#
Par James McCaffrey
Le test de connexion est généralement utilisé dans les situations où vous disposez de données « avant et après » et vous souhaitez déterminer s’il existe une preuve statistique d’un effet quelconque. La meilleure façon d'expliquer cette notion est d'étudier un exemple. Supposons que vous travaillez dans une entreprise pharmaceutique et souhaitez savoir si un nouveau médicament perdre du poids est efficace. Vous obtenez huit volontaires pour utiliser votre médicament pendant plusieurs semaines. Vous allez examiner les poids de vos huit sujets avant et après l’expérience. Disons que six des huit du poids sujets perdues. Existe-t-il une preuve statistique solide pour suggérer que le médicament a fonctionné ?
Perte de poids est un exemple de test de connexion classique, mais le test s’applique dans l’informatique de nombreux scénarios et de logiciels, trop. Supposons que vous disposez de 40 ordinateurs de serveur Web et que vous appliquez un correctif logiciel conçu pour améliorer les performances. Vous mesurez le temps de réponse avant et après avoir appliqué le correctif. Ce que vous pouvez conclure si 32 serveurs vous a montré les meilleures performances, deux serveurs ont montré aucune modification, et six serveurs a montré la dégradation des performances ?
La meilleure façon de voir où cet article est en venir est de jeter un œil dans le programme de démonstration Figure 1. Après avoir lu cet article, vous aurez une compréhension solide de quel type de problème, le test de connexion résout, savent exactement comment effectuer un test de connexion à l’aide de c# et comprendre comment interpréter les résultats d’un test de connexion. Tout le code source du programme de démonstration est présentée dans cet article. Vous pouvez également obtenir le programme de démonstration complète dans le téléchargement de code qui accompagne cet article.
Figure 1 le Test de connexion à l’aide de c#
Le programme de démonstration définit huit paires de données avant et après où l’objectif est de déterminer si certains régime de perte de poids a un effet ou non. À partir des données, six matières affichait une pondération perte, mais les deux objets ont montré une augmentation du poids. Le programme de démonstration calcule la probabilité de « aucun effet » pour être 0.1445. C’est à vous d’interpréter les résultats, par exemple, « données montrent une indication faible (p = 0.8555) que l’effort de perte de poids a eu un effet. »
Cet article suppose que vous disposez d’au moins intermédiaires de compétences en programmation, mais ne suppose pas que vous connaissez un peu le test de connexion. Le code de démonstration est écrit en c# et s’appuie sur l’espace de noms .NET System.Numerics, vous devez donc le Kit de développement Microsoft .NET Framework 4 (publiée en 2010) ou version ultérieure.
La Structure de programme de démonstration
Pour créer le programme de démonstration, je lancé Visual Studio et sélectionné le modèle d’Application Console c# à partir de l’élément de menu Nouveau projet. J’ai nommé le projet SignTestUsingCSharp. Après que le code du modèle chargé dans la fenêtre de l’éditeur, j’ai cliqué sur le fichier Program.cs dans la fenêtre Explorateur de solutions renommé le fichier SignTestProgram.cs, puis autorisé Visual Studio renommer la classe Program pour moi.
Ensuite, j’ai cliqué sur le nom du projet et sélectionné Ajouter | Élément de référence. À partir des assemblys | Liste de Framework, j’ai sélectionné de l’espace de noms System.Numerics et cliqué sur OK pour l’ajouter à mon projet. En haut de la fenêtre de l’éditeur, j’ai supprimé toutes les instructions using sauf référençant le système de niveau supérieur pour l’espace de noms, puis j’ai ajouté un à l’aide l’instruction pour référencer l’espace de noms System.Numerics.
La structure générale du programme est présentée dans Figure 2. Pour plus de simplicité, le programme utilise une approche de la méthode statique strictement plutôt que d’une approche à orientation objet de programmation (OOP). Méthodes DoCounts et ShowVector sont des « helpers » de l’utilitaire. Le travail du calcul de la probabilité sans effet est effectué par la méthode BinomRightTail. Méthodes BinomProb et choisissez sont les aides pour BinomRightTail.
Structure du programme de démonstration figure 2 connexion Test
using System;
using System.Numerics;
namespace SignTestUsingCSharp
{
class SignTestProgram
{
static void Main(string[] args)
{
Console.WriteLine("\nBegin Sign Test demo \n");
// All calling statements go here
Console.WriteLine("\n\nEnd Sign Test demo \n");
Console.ReadLine();
}
static int[] DoCounts(double[] before,
double[] after) { . . }
static void ShowVector(string pre, double[] v,
int dec, string post) { . . }
static double BinomProb(int k, int n,
double p) { . . }
static double BinomRightTail(int k, int n,
double p) { . . }
static BigInteger Choose(int n, int k) { . . }
}
}
Après l’affichage de quelques messages d’introduction, la méthode Main configure et affiche les données de démonstration d’un test de connexion :
double[] before = new double[] { 70, 80, 75, 85, 70, 75, 50, 60 };
double[] after = new double[] { 65, 78, 72, 87, 68, 74, 48, 63 };
Console.WriteLine("The weight data is: \n");
ShowVector("Before: ", before, 0, "");
ShowVector("After : ", after, 0, "\n");
Dans un scénario non démonstration avec toute valeur supérieure à des paires de données environ 30 que vous aurait probablement des données stockées dans un fichier texte fichier et vous devez écrire une méthode d’assistance pour lire et stocker les données. Utilisation des tableaux parallèles d’est l’approche la plus courante lors de l’exécution d’un test de connexion.
Ensuite, la démonstration utilise la méthode DoCounts pour compter le nombre de paires élément où il y avait une diminution des poids, « réussite », et le nombre de poids augmente, un « échec » :
int[] counts = DoCounts(before, after);
Console.WriteLine("Num success = " + counts[2]);
Console.WriteLine("Num failure = " + counts[0]);
La valeur de retour est un tableau où la cellule 0 conserve le nombre d’échoue (augmentation du poids), la cellule 1 contient le nombre où il n’y avait aucune modification et cellule 2 contient le nombre de réussites (réduction de poids). Jours avant que les ordinateurs ont été facilement disponibles, les nombres ont été effectuées manuellement en plaçant un signe « + » en regard de réussites et un «- » en regard des échecs. C’est pourquoi le test de connexion nommé car il s’agit. Pour les données de démonstration, l’approche manuelle ressemblerait à :
Before: 70 80 75 85 70 75 50 60
After : 65 78 72 87 68 74 48 63
+ + + - + + + -
Notez que le test de connexion ne prend pas en compte l’importance d’épaisseur augmentation ou diminution. Ensuite, la démonstration prépare l’appel au test de connexion comme suit :
int k = counts[2];
int n = counts[0] + counts[2];
Console.WriteLine("k = " + k + " n = " + n + " p = 0.5");
K variable conserve le nombre de réussites. N variable conserve le nombre total de paires de données. Dans ce cas, il n’existe aucune instance où les poids avant et après sont égales. Dans ce cas, l’approche la plus courante consiste à balancer ties. Toutefois, dans certaines situations, il pourrez que vous souhaitez inclure ties en tant que succès ou échecs. Par exemple, dans un programme de perte de poids, aucune modification de poids ne peut probablement être considéré comme un échec.
La méthode Main se termine par :
double p_value = BinomRightTail(k, n, 0.5);
Console.WriteLine("\nProbability of 'no effect' is " + p_value.ToString("F4"));
Console.WriteLine("Probability of 'an effect' is " + (1 - p_value).ToString("F4"));
Le test de connexion est en fait un exemple spécifique de l’essai binomiale plus général. Fonction définie par le programme BinomRightTail accepte le nombre de succès, le nombre de paires de données et une valeur de probabilité, 0,5 dans ce cas. Lorsqu’un test binomial utilise 0,5 pour le paramètre de probabilité, il est un test de connexion, comme je l’expliquerai plus loin.
Présentation de la fonction choisir
Le test de connexion utilise la distribution binomiale, qui à son tour utilise la fonction Choose. La fonction Choose (n, k) renvoie le nombre de façons de sélectionner k éléments parmi n éléments. Par exemple, choisir (5, 3) est le nombre de possibilités, que vous pouvez sélectionner les trois éléments de cinq éléments. Supposons que les cinq éléments sont (A, B, C, D, E). Il existe 10 façons de sélectionner trois éléments :
(A, B, C), (A, B, D), (A, B, E), (A, C, D), (A, C, E),
(A, D, E), (B, C, D), (B, C, E), (B, D, E), (C, D, E)
La fonction est de choisir défini Choose (n, k) = n ! / [k! * (n-k)!] où le « ! » caractères signifie la factorielle. Ainsi :
Choose(5, 3) = 5! / (3! * 2!) = (5 * 4 * 3 * 2 * 1) / (3 * 2 * 1) *
(2 * 1) = 120 / 12 = 10
L’implémentation de la fonction choisir est délicat, car la valeur de retour peut être fusionnelles élevée pour les valeurs moyenne de n et k. Par exemple :
Choose(100, 25) = 242,519,269,720,337,121,015,504
Afin de retourner les valeurs de très grande taille qui peuvent se produire dans le test de connexion, le programme de démonstration utilise le type BigInteger dans l’espace de noms System.Numerics. L’implémentation de démonstration de choisir utilise deux astuces mathématiques pour plus d’efficacité. Tout d’abord, il s’avère, Choose (n, k) = Choose (n, n-k). Par exemple :
Choose(10, 7) = Choose(10, 3)
À l’aide de la plus petite valeur de k faire moins de calculs. Deuxièmement, il existe une autre définition de choisir l’explique parfaitement par exemple :
Choose(10, 3) = (10 * 9 * 8) / (3 * 2 * 1)
Dans les mots, le dénominateur est simplement k ! et le numérateur fait simplement la première k de n ! équation et termes d’annulent l’opération. Assembler ces idées, de choisir l’implémentation de démonstration est présentée dans Figure 3.
Figure 3 la fonction Choose
static BigInteger Choose(int n, int k)
{
if (n == k) return 1; // Required special case
int delta, iMax;
if (k < n - k) { // Ex: Choose(100,3)
delta = n - k;
iMax = k;
}
else { // Ex: Choose(100,97)
delta = k;
iMax = n - k;
}
BigInteger ans = delta + 1;
for (int i = 2; i <= iMax; ++i)
ans = (ans * (delta + i)) / i;
return ans;
}
Présentation de la Distribution binomiale
La clé pour comprendre comment implémenter et interpréter le test de connexion est de comprendre la distribution binomiale. Par exemple, elle est mieux expliquée. Imaginez que vous ayez une médaille biaisée où, lorsque retournée, la probabilité d’obtenir une tête est 0,6 et la probabilité d’obtenir une fin est 0,4, et supposons que vous définissiez un succès que d’obtenir un début. Si vous inversez la monnaie n = 8 heures, la distribution binomiale vous donne la probabilité d’obtenir exactement k n essais réussis où la probabilité de réussite d’un seul essai est p = 0,6 dans cet exemple.
La probabilité d’obtenir exactement huit têtes et zéro arrive à la fin dans les retournements de huit est la probabilité d’obtenir huit têtes consécutifs, ce qui est :
Pr(X = 8) = 0.6 * 0.6 * 0.6 * 0.6 * 0.6 * 0.6 * 0.6 * 0.6 = (0.6)^8 * (0.4)^0 = 0.0168
Pour obtenir exactement sept têtes de huit retournements, vous pouvez obtenir sept têtes plus unilatérale sur n’importe lequel des huit inverse. Il existe huit combinaisons :
Pr(X = 7) = Choose(8, 1) * [ (0.6)^7 * (0.4)^1 ] = 8 * 0.0280 * 0.4 = 0.0896
L’équation générale pour la probabilité d’obtenir exactement k n essais réussis où p est la probabilité de réussite d’un essai unique est la suivante :
P(X = k) = Choose(n, k) * p^k * (1-p)^n-k
Dans le cas de test de connexion, p est toujours 0,5 donc 1-p est également 0,5 et l’équation simplifie pour :
P(X = k) = Choose(n, k) * (0.5)^n
Pour les données de démonstration, il y a n = 8 essais (paires de données) et il y a k = 6 succès (pertes de poids), donc la probabilité d’obtenir exactement six réussites est :
P(X = 6) = Choose(8, 6) * (0.5)^8 = 28 * 0.0039 = 0.1094
Les probabilités d’obtenir exactement comprise entre zéro et huit essais huit réussis lorsque p = 0,5 sont affichés dans le graphique de Figure 4.
L’implémentation d’une fonction qui retourne la probabilité est simple :
static double BinomProb(int k, int n, double p)
{
// Probability of k "successes" in n trials
// if p is prob of success on a single trial
BigInteger c = Choose(n, k);
double left = Math.Pow(p, k);
double right = Math.Pow(1.0 - p, n - k);
return (double)c * left * right;
}
Figure 4 la Distribution binomiale pour n = 8 et p = 0,5
La démonstration définit une fonction binomiale générale accepte p en tant que paramètre. Une alternative consiste à définir une version qui part du principe que p = 0,5 et simplifiez le calcul comme décrit précédemment. La démonstration n’a aucune vérification des erreurs. Par exemple, dans un environnement de production il faudrait probablement faire que k<= n; neither k nor n are negative; and p is between 0.0 and 1.0. n;="" neither="" k="" nor="" n="" are="" negative;="" and="" p="" is="" between="" 0.0="" and=""></= n; neither k nor n are negative; and p is between 0.0 and 1.0.>
L’implémentation du Test de connexion
L’idée du test de connexion consiste à calculer la probabilité que n’a eu aucun effet. Conceptuellement, cela signifie que la différence entre une valeur avant et après sont devenus le purement par hasard. Point de vue mathématique, cela signifie que la probabilité d’une augmentation ou une diminution est 0,5.
Le test de connexion suppose qu’il n’existe aucun effet, puis calcule la probabilité que le nombre de réussites observé avez pu se produire sous cette hypothèse. Dans le cas des données de démonstration où il y a huit essais de six réussis (pertes de poids), plutôt que de calculer la probabilité de six exactement succès comme vous pouvez le deviner, vous calculez la probabilité de succès de six ou plus. Cette idée est plutôt subtile.
Calculer la probabilité de Ko ou plus de succès est parfois appelé un test de fin de la droite. Par conséquent, pour implémenter le test de connexion, vous calculez la probabilité de Ko ou plus de succès en calculant la probabilité d’exactement les réussites k plus k + 1 réussites, plus k + 2 réussites et ainsi de suite. La démonstration met en œuvre comme :
static double BinomRightTail(int k, int n, double p)
{
// Probability of k or more successes in n trials
double sum = 0.0;
for (int i = k; i <= n; ++i)
sum += BinomProb(i, n, p);
return sum;
}
Tout ce qui est nécessaire pour effectuer un test de connexion sont des fonctions facultatives pour compter le nombre de réussites et d’afficher les valeurs. La démonstration définit la méthode de comptage en tant que :
static int[] DoCounts(double[] before, double[] after)
{
int[] result = new int[3];
for (int i = 0; i < before.Length; ++i) {
if (after[i] > before[i])
++result[0]; // Fail
else if (after[i] < before[i])
++result[2]; // Success
else
++result[0]; // Neither
}
return result;
}
La méthode d’affichage d’assistance est :
static void ShowVector(string pre, double[] v, int dec, string post)
{
Console.Write(pre);
for (int i = 0; i < v.Length; ++i)
Console.Write(v[i].ToString("F" + dec) + " ");
Console.WriteLine(post);
}
Une conception alternative consiste à combiner les calculs de comptage et binomiale réussite-échec dans une méthode de métadonnées supérieure.
Pour résumer
Vous devez toujours interpréter les résultats d’un test de connexion avec précaution. Il est préférable par exemple, « le test de connexion suggère qu’il existe un effet, » plutôt que, « il est un effet ».
Le problème de l’exemple est appelé un test à un côté ou un point. Étant donné que cet exemple impliqué une expérience de perte de poids, un effet est plus pertes de poids (succès) que vous obtenez par hasard. Vous pouvez également effectuer un double, également appelé bilatérale, test de connexion. Par exemple, supposons que vous effectuez une expérience avec une sorte de douleurs. Dans le cadre de votre expérience, vous mesurer vos sujets de test avant et après l’expérience. Vous n’avez aucune raison de croire que les médicaments DOULEUR affectera le poids. En d’autres termes, un effet serait une perte de poids ou par un gain de poids.
La partie la plus délicate du test de connexion consiste à conserver vos définitions clair. Il existe toute confusion potentielle, car il existe plusieurs symétries dans tous les problèmes. Vous pouvez définir un succès qu’une augmentation ou réduire une valeur après. Par exemple, dans l’exemple de la perte de poids, un succès est une diminution de la valeur sur. Mais si vos données représentent les résultats de test sur un certain type d’examen avant et après avoir étudié, un succès est probablement défini comme une augmentation de la valeur sur.
Le test de connexion est un exemple de ce que l'on appelle un test statistique non paramétrique. En partie, cela signifie que le test de connexion ne fait pas d’hypothèses concernant la distribution des données à l’étude. Au lieu d’utiliser un test de connexion, il est possible d’utiliser ce que l'on appelle un test t apparié. Toutefois, le test t suppose que les données de population ont une distribution normale (gaussienne en cloche), ce qui serait presque impossible de vérifier avec une taille de petit jeu de données. Pour cette raison, lorsque je souhaite examiner avant et après les données, je vais généralement utiliser un test de connexion au lieu d’un test t apparié.
Récupération d’urgence. James McCaffreytravaille pour Microsoft Research à Redmond, Wash. Il a travaillé sur plusieurs produits Microsoft, y compris Internet Explorer et Bing. Dr. James McCaffrey peut être atteint à jammc@microsoft.com.
Je remercie les experts techniques Microsoft qui son article : Chris Lee et Kirk Olynyk