2017 年 2 月

第 32 卷,第 2 期

本文章是由機器翻譯。

測試回合 - 使用 C# 的符號檢驗

James McCaffrey

James McCaffrey標誌測試最常用 」 之前和之後 」 的資料,而您想要判斷是否有某種形式之效果的統計的辨識項。概念最佳範例所說明。假設您在製藥公司使用,而且想要知道新的權數遺失藥物是否有效。您會取得您藥物用於幾週以來的八個名冊。您看看您八個科目的加權之前, 和之後的實驗。說出六個超出八個的主體遺失權重。有實心統計的辨識項,建議您藥物運作嗎?

減重是傳統的正負號的測試範例,但測試適用於許多 it 和軟體的情況,太。假設您有 40 Web 伺服器的機器,並套用軟體修補程式,設計目的是改善效能。您衡量回應時間之前和之後套用修補程式。您能什麼認為如果 32 部伺服器顯示達到最佳效能,兩部伺服器會顯示任何變更,而且六部伺服器顯示較差的效能?

若要查看這篇文章方向的位置,最好是示範程式中查看**[圖 1**。閱讀這篇文章之後,您必須確實掌握什麼類型的問題可以解決標誌測試,知道到底該如何執行使用 C# 符號測試和了解如何解譯登測試的結果。所有來源的程式碼示範程式會顯示在這篇文章。您也可以在本文所附的程式碼下載中取得完整的範例程式。

使用 C# 號測試
[圖 1 號測試使用 C#

示範程式會設定八組之前和之後資料的目標是判斷某些權數遺失品是否有影響,或不。從資料中,六個科目未顯示權數遺失,但是兩項主題示範權數增加。示範程式會計算機率 「 副作用 」 是 0.1445。您解譯結果,比方說,是由 「 這項資料顯示的弱式指示 (p = 0.8555) 的加權遺失工作有影響。 」

本文假設您有至少中繼程式設計技能,但不會假設您知道標誌測試。示範程式碼以 C# 撰寫,並依賴.NET System.Numerics 命名空間,因此您將需要 Microsoft.NET Framework 4 (2010年發行) 或更新版本。

示範程式結構

若要建立示範程式我啟動 Visual Studio,並從新的專案] 功能表項目選取 C# 主控台應用程式範本。我命名為 SignTestUsingCSharp 的專案。範本程式碼載入 [編輯器] 視窗之後,我以滑鼠右鍵按一下 [方案總管] 視窗中的 Program.cs 檔案並重新將檔案命名為 SignTestProgram.cs,然後允許類別程式重新命名為我的 Visual Studio。

接下來,我以滑鼠右鍵按一下專案名稱,然後選取 [新增 |參考項目。從組件 |Framework] 清單中,已選取 System.Numerics 命名空間並按下 [確定] 以將它加入至我的專案。在編輯器視窗的頂端,刪除所有 using 陳述式,但參考最上層系統的一個命名空間,然後再加入 using 陳述式來參考 System.Numerics 命名空間。

程式的整體結構所示**[圖 2**。為了簡單起見,程式會使用嚴格的靜態方法,而不是物件修正程式設計 (OOP) 方法。方法 DoCounts 和 ShowVector 都是公用程式協助程式。計算不影響機率的工作是由 BinomRightTail 方法執行。方法 BinomProb 和選擇都是協助程式 BinomRightTail。

[圖 2 號測試示範程式結構

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) { . . }
  }
}

顯示數個入門的訊息之後, Main 方法會設定,並顯示示範登測試資料︰

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");

在非示範的案例中的任何項目大於 30 的資料組,您可能必須在文字中所儲存的資料檔案,而且您會撰寫的 helper 方法,來讀取和儲存資料。使用平行陣列時,最常見的方法進行簽署測試。

接下來,範例將使用 DoCounts 方法來計算的項目組,其中沒有加權,「 成功 」 降低,而的加權數目增加時,「 失敗 」:

int[] counts = DoCounts(before, after);
Console.WriteLine("Num success = " + counts[2]);
Console.WriteLine("Num failure = " + counts[0]);

傳回值是陣列,其中的資料格 0 保留失敗 (權數增加) 的計數、 資料格 1 保留其中沒有變更,而資料格 2 保留的成功 (加權減少) 其計數的計數。以天為單位電腦可供輕鬆地使用之前, 計數以手動方式完成放旁邊成功"+"符號和"-"旁邊失敗。這是因為它是名為標誌測試的原因。示範資料,手動的方式應該像這樣︰

Before:  70 80 75 85 70 75 50 60
After :  65 78 72 87 68 74 48 63
         +  +  +  -  +  +  +  -

請注意登測試未列入考量的權數增加或減少大小。接下來,示範準備標誌測試,像這樣的呼叫︰

int k = counts[2];
int n = counts[0] + counts[2];
Console.WriteLine("k = " + k + " n = " + n + " p = 0.5");

變數 k 保存成功次數的計數。變數 n 保存資料組總數。在此情況下,沒有相等的之前和之後加權所在的執行個體。在這種情況下,最常見的方法是擔憂繫結。不過,在某些情況下您可能想要包含繫結為成功或失敗。比方說,在權數遺失程式中,不會變更權數會可能被視為失敗。

Main 方法已結束︰

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"));

標誌測試是實際上更一般的二項測試的特定範例。程式定義的函數 BinomRightTail 在此情況下接受資料組的數目和機率值 0.5 的成功數目。二項測試會使用機率參數 0.5,時標誌測試,如很快會討論到。

了解選擇函式

標誌測試會使用二項分配,它會使用 [選擇函式。選擇 (n、 k) 函數會傳回數種方法來從 n 個項目選取 k 項目。例如,(5,3) 的選擇是方法讓您可以選取三個項目從五個項目數目。假設五個項目都是 (A、 B、 C、 D、 E)。有 10 個方式可選取三個項目︰

(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)

[選擇函式會定義選擇 (n k) = n !/ [k! * (n-k)!]其中"!"字元表示階乘。那麼

Choose(5, 3) = 5! / (3! * 2!) = (5 * 4 * 3 * 2 * 1) / (3 * 2 * 1) *
  (2 * 1) = 120 / 12 = 10

選擇函式的實作相當困難,因為傳回的值可以是即使一般值 n 和 k astronomically 大。例如:

Choose(100, 25) = 242,519,269,720,337,121,015,504

為了傳回非常大的值可能會發生登測試中,示範程式會使用 BigInteger 類型 System.Numerics 命名空間中。示範的選擇是使用實作兩個數學技巧的效率。首先,其實,選擇 [(n k) = 選擇 (n,n-k)。例如:

Choose(10, 7) = Choose(10, 3)

您可以使用較小的 k 值來執行較少的計算。第二,是選擇最適合所範例所說明的替代定義︰

Choose(10, 3) = (10 * 9 * 8) / (3 * 2 * 1)

就分母是只是 k !並用分子只是第一個 k 使用條款 n !方程式和許多詞彙取消。將這些想法放在一起,示範實作的選擇會顯示在**[圖 3**。

[圖 3 選擇函式

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;
}

了解分配

要了解如何實作及解譯登測試關鍵在於瞭解二項式分佈。它最能說明範例。假設有誤的穩固性,當翻轉,取得標頭的機率是 0.6 而取得結尾的機率均為 0.4,並假設您定義成功取得標頭。如果您翻轉們 n = 8 倍,分配可讓您取得其中一個試用版的成功機率為 p 的 n 實驗完全 k 成功的機率 = 0.6,在此範例中。

在八個翻轉取得完全八個標頭和零的情況下連接結尾的機率是機率取得八個連續的標頭,也就是︰

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

在八個翻轉中取得完全七個標頭中,您可以取得七個讀寫頭加上一個結尾的任何八翻轉。有八個組合︰

Pr(X = 7) = Choose(8, 1) * [ (0.6)^7 * (0.4)^1 ] = 8 * 0.0280 * 0.4 = 0.0896

取得其中 p 單一的試用版機率的 n 個實驗完全 k 成功的機率的一般公式是成功的︰

P(X = k) = Choose(n, k) * p^k * (1-p)^n-k

在簽署測試 p 一律須也是 0.5,1-p 0.5 和方程式簡化了︰

P(X = k) = Choose(n, k) * (0.5)^n

因此示範資料,會有 n = 8 試用版 (配對的資料) 而且有 k = 6 成功 (權數損失),以便取得完全六個成功的機率是︰

P(X = 6) = Choose(8, 6) * (0.5)^8 = 28 * 0.0039 = 0.1094

取得完全零到八個實驗八成功的機率時 p = 0.5 會顯示在圖形中**[圖 4**。

實作會傳回二項式機率的函式非常簡單︰

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;
}

二項分配,n = 8 和 p = 0.5
[圖 4] 分配 n = 8 和 p = 0.5

示範定義接受 p 做為參數的一般二項式函式。另一個方法是定義版本假設 p = 0.5 和簡化計算,如先前所述。示範具有錯誤檢查。比方說,在生產環境中就可能要確定 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.>

實作號測試

標誌測試的概念是要計算機率已沒有作用。在概念上來說這表示完全由機會發生之前值,則包含的值之間的任何差異。以數學方式,這表示增加或減少的機率為 0.5。

標誌測試假設沒有任何作用,則會計算成功觀察到的數目可能已發生在這假設下的機率。示範資料案例的其中有個八個實驗六個成功 (權數損失),而是只計算完全六個成功的機率,您或許已經猜到,因為您計算的六個或多個成功的機率。這個構想是而難以察覺。

計算的 k 或更多的成功機率有時稱為右邊結尾測試。因此若要實作標誌測試,您計算 k 或多個成功的機率計算完全 k 成功加上 k + 1 成功,再加上 k + 2 成功的機率,依此類推。示範實作為︰

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;
}

所有所需完成簽署測試都是選擇性的函式來計算次數,並顯示值。示範計數方法定義為︰

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;
}

協助程式顯示方法是︰

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);
}

替代的設計是結合成較大的中繼方法成功失敗計數與二項式計算。

總結

您永遠應該小心解譯登測試的結果。最好是說: 「 沒有效果,請登測試建議 」 而,比 「 沒有作用。 」

範例問題就稱為單側,或單尾的測試。由於此範例涉及權數遺失實驗,結果會是更多加權損失 (成功) 不是巧合,您會取得。您也可以執行雙面,也稱為雙尾標誌測試。例如,假設您正在做實驗,其具有某種形式的痛苦醫藥。您的實驗的一部分,您會衡量測試主題之前和之後的實驗。您有沒有理由認定痛苦醫藥會影響權數。換句話說,效果是加權遺失或較的粗細。

標誌測試最棘手的部分讓您定義清除。沒有造成混淆,因為每個問題中有多個 symmetries。您可以增加定義成功,或減少則包含的值。比方說,在權數遺失範例中,成功是降低則包含值。但如果您的資料代表某種測驗上的測驗分數之前和之後研究,就有可能增加則包含值定義成功。

標誌測試是所謂的非參數化的統計測試範例。也就是說,部分簽署測試不會進行任何假設正在研究資料的分佈。除了使用標誌測試,就可以使用了稱為成對的 t 檢定。不過,t 檢定假設人口資料幾乎不可能確認小型資料集大小一般 (高斯,鐘形) 分佈。因此,當我想要調查之前和之後的資料,我將通常使用標誌測試而不是成對的 t 檢定。


Dr。James McCaffrey適用於在美國華盛頓州 Redmond 的 Microsoft Research 他曾在數個 Microsoft 產品,包括 Internet Explorer 和 Bing。Dr。可以連線到 McCaffrey jammc@microsoft.com

感謝 Microsoft 技術專家者他的文章︰ Chris Lee 和 Kirk Olynyk