到 2015 2015年 7 月

30 卷數 7

測試回合-使用 C# 的線性回歸

James McCaffrey

James McCaffrey線性回歸問題的目標是預測基於一個或多個數值預測變數的值的數值變數的值。例如,你可能想要預測一個人基於他的教育水準,多年的工作經驗和性別的年度收入 (男性 = 0,女性 = 1)。

要預測的變數通常稱為因變數。預測變數通常稱為獨立變數。只是一個單一的預測變數時,這項技術是有時被稱為簡單線性回歸。當兩個或多個預測變數時,該技術通常被稱為多,或多變數的線性回歸。

看到這篇文章將走向何方是好方法是去看一看演示程式中圖 1。C# 演示程式預測基於教育、 工作和性別的年度收入。演示開始通過生成 10 合成資料項目目。教育水準是 12 和 16 之間的值。 工作經驗是 10 和 30 之間的值。 性是一個指示符變數在男性是參考值,編碼為 0,而女性編碼為 1。 收入,幾千塊錢,是在最後一列。在非演示的情況下,你可能會讀資料從文字檔中使用一個名為一些方法,如 MatrixLoad。

線性回歸使用 C#
圖 1 線性回歸使用 C#

生成的合成資料之後, 演示程式使用資料創建所謂的設計矩陣。設計矩陣是只是添加的所有 1.0 值領先列資料矩陣。有幾種不同的演算法,可以用於線性回歸; 一些可以使用原始資料矩陣,而他人使用一個設計矩陣。演示使用一種技術,需要一個設計矩陣。

創建設計矩陣後, 該演示程式查找值為四個係數 (12.0157、 1.0180、 0.5489、-2.9566)。係數有時稱為 b 值或 β 值。第一個值,12.0157,通常稱為截距。它是一個不與任何預測變數相關聯的常量。第二、 第三和第四個係數值 (1.0180、 0.5489、-2.9566) 是與教育相關聯­陽離子水準、 工作經驗和性別,分別。

在輸出的最後部分圖 1 使用係數的值來預測收入為假設有 14; 教育水準的人 12 年的工作經驗; 和其性別是 0 (男)。其中計算預測的收入是 32.86,像這樣:

income = 12.0157 + (1.0180)(14) + (0.5489)(12) + (-2.9566)(0)
                = 12.0157 + 14.2520 + 6.5868 + 0
                = 32.86

換句話說,要使用線性回歸預測,預測值乘以其相應的係數值,並總結。它是非常簡單。可以認為領先的截距值 (在示例中的 12.0157) 與始終具有一個值 1 預測變數相關係數的通知。 這一事實,部分地解釋了 1.0 值設計矩陣中的列。

線性回歸問題的實質計算使用的原始資料,或等價地,設計矩陣係數的值。這不是那麼容易的。演示使用一種叫做閉的式矩陣求逆,也稱為普通最小二乘方法技術。尋找係數的值替代技術包括反覆運算加權的最小平方法、 最大似然估計、 嶺回歸、 梯度下降和其他幾個。

圖 1,預測之前,該演示程式計算度量稱為 R 平方值,也被稱為係數的測定。R 平方是一個介於 0 和 1,描述預測模型與原始資料的吻合程度之間的值。這有時表述為,百分比變化的解釋模型。鬆散的解釋,越接近 R 平方是 1,預測模型就越好。演示的 0.7207 或 72%,會認為的價值相對較高 (好) 真實世界的資料資料。

這篇文章假設你有至少中間的 C# 程式設計技巧,但並不認為你知道任何關於線性回歸。該演示程式是太長,無法顯示其全部內容,但完整的原始程式碼是本文附帶的下載中提供。

瞭解線性回歸

線性回歸通常最好用圖來解釋。看看圖中圖 2。圖中的資料表示預測年收入只是單個變數,從多年的工作經驗。每個紅點對應一個資料點。例如,最左邊的資料項目有工作 = 10 和收入 = 32.06。線性回歸發現兩個係數:一個攔截,另一個用於工作變數。事實證明,係數的值是 27.00 和 0.43。

與一個獨立的變數的線性回歸
圖 2 與一個獨立的變數的線性回歸

係數值確定的一條線,在藍色所示方程圖 2。線 (係數) 最小偏差平方和的實際資料點 (彝族) 和預測的資料點 (fi) 之間。兩個 10 偏差顯示帶有虛線在圖 2。顯示的第一個偏差是彝族-fi = 28.6 32.6 =-4.0。請注意偏差可以是正數或負數。如果偏差不平方,正片及負片可以相互抵消。

在圖圖 2 顯示如何簡單線性回歸,只是一個獨立的變數,作品。多元線性回歸延伸同樣的想法 — — 尋找偏差平方和的最小化的係數 — — 使用幾個獨立變數。

直觀地表示,線性回歸發現通過一組資料點的最佳線路。這最好的線可以用來預測。例如,在圖 2,如果一個假想的人有 25 年的工作經驗,她在藍線上的預測的收入會約 38。

最小二乘方程的求解

如果一個線性回歸問題有 n 預測變數,那麼 n + 1 係數必須找到值,一個用於每個預測加上的截距值。該演示程式使用最基本的技術來查找係數值。係數的值通常考慮使用有點令人生畏的方程所示圖 3。方程是不可能出現的最初的那麼複雜。

線性回歸係數解矩陣
圖 3 線性回歸係數解矩陣

希臘字母 β 類似于 B 的腳本和表示的係數值。請注意所有方程中的字母都在大膽,在數學中,指示他們代表多值的物件 (矩陣或陣列/向量) 而不是簡單的標量值 (純數位)。大寫的 X 表示設計矩陣。大寫的 X T 指數意味著設計矩陣的轉置。* 符號意味著矩陣乘法。-1 指數意味著矩陣求逆運算。大寫 Y 是一個列向量 (一個矩陣與一列) 的變數值。因此,求解係數的值實際上意味著理解矩陣運算。

在圖圖 4 說明傳遞矩陣轉置、 矩陣乘法和矩陣求逆運算。矩陣的轉置就互換的行和列。例如,假設您有一個 2 × 3 的矩陣,那就是,一個具有 2 行和 3 列。的轉置矩陣將 3 x 2 在原始矩陣的行成為轉置矩陣的列。

三矩陣運算用來尋找線性回歸係
圖 4 三矩陣運算用來尋找線性回歸係數

矩陣乘法可能看起來有點奇怪,如果你還沒有遇到過。如果你乘 (n x m) 大小矩陣倍 (m x p) 大小的矩陣,結果是 (n x p) 大小矩陣。例如,3 x 4 * 4 × 2 矩陣具有大小為 3 x 2。矩陣乘法的詳細的討論超出範圍的這篇文章,但一旦你看過幾個例子,這個過程是容易理解和容易在代碼中實現。

線性回歸係數值,為解決問題所需的第三個矩陣運算是矩陣求逆運算,即,不幸的是,難以把握,難以實施。對於這篇文章的目的,它就足以知道那矩陣的逆矩陣是定義只當矩陣具有相同數量的行和列 (方陣)。圖 4顯示一個 3 x 3 矩陣和它的逆矩陣。

有幾個可以用於查找矩陣的逆矩陣的演算法。該演示程式使用一種叫做杜利特爾的分解技術。

綜上所述,n 預測變數線性回歸問題是涉及尋找 n + 1 係數值。這可以用傳遞矩陣轉置、 矩陣乘法和矩陣求逆的矩陣。大動脈轉位和乘法很容易,但很難找到的矩陣的逆矩陣。

演示的程式結構

若要創建該演示程式,我發起Visual Studio,選擇主控台應用程式專案範本。我命名專案線性回歸。程式有沒有重大的.NET 框架依賴,因此,任何版本的Visual Studio工作。

範本代碼載入到編輯器中,在解決方案資源管理器視窗中之後, 我在 Program.cs 檔上右擊,改名為 LinearRegressionProgram.cs。 我允許Visual Studio汽車­論述重命名類程式。在編輯器視窗的頂部,我刪除了所有使用除了引用頂級 System 命名空間的語句。

演示程式,與一些少量的編輯,以節省空間,整體結構在圖 5。所有程式控制邏輯都是在 Main 方法中。該演示程式使用靜態方法,而不是一種物件導向的方法。

圖 5 線性回歸演示程式結構

using System;
namespace LinearRegression
{
  class LinearRegressionProgram
  {
    static void Main(string[] args)
    {
      Console.WriteLine("Begin linear regression demo");
      // Generate synthetic data
      // Create design matrix
      // Solve for LR coefficients
      // Calculate R-squared value
      // Do a prediction
      Console.WriteLine("End linear regression demo");
      Console.ReadLine();
    }
    static double Income(double x1, double x2,
      double x3, double[] coef) { . . }
    static double RSquared(double[][] data,
      double[] coef) { . . }
    static double[][] DummyData(int rows,
      int seed) { . . }
    static double[][] Design(double[][] data) { . . }
    static double[] Solve(double[][] design) { . . }
    static void ShowMatrix(double[][] m, int dec) { . . }
    static void ShowVector(double[] v, int dec) { . . }
    // ----------
    static double[][] MatrixTranspose(double[][] matrix)
      { . . }
    static double[][] MatrixProduct(double[][] matrixA,
      double[][] matrixB) { . . }
    static double[][] MatrixInverse(double[][] matrix)
      { . . }
    // Other matrix routines here
  }
} // ns

方法收入返回預測的收入與受教育程度、 工作經驗和性別,利用係數值的陣列值的輸入參數。方法 RSquared 返回從資料和係數模型 R 平方值。方法 DummyData 生成用於演示的綜合資料。

設計方法接受一個矩陣資料並返回 1.0 值領先列增廣的設計矩陣。方法解決接受設計矩陣,然後使用矩陣運算來尋找線性回歸係數。

最艱難的工作是通過一套執行矩陣操作的靜態方法。演示程式中最簡單的方法,作為陣列的陣列定義了一個矩陣。替代方法是創建一個程式定義的矩陣類,但方法我認為是不必要的複雜。有時普通陣列均優於程式定義的物件。

方法 MatrixTranspose 返回矩陣的移位。方法 MatrixProduct 返回兩個矩陣相乘的結果。方法 MatrixInverse 返回的矩陣的逆矩陣。演示了許多的説明器方法。尤其是,MatrixInverse 方法調用 MatrixDuplicate、 MatrixDecompose 和 HelperSolve 的説明器方法。

解決方法

線性回歸演示程式的心是解決的方法。該方法的定義的開頭:

static double[] Solve(double[][] design)
{
  int rows = design.Length;
  int cols = data[0].Length;
  double[][] X = MatrixCreate(rows, cols - 1);
  double[][] Y = MatrixCreate(rows, 1);
...

單個輸入的參數是一個設計矩陣。你可能想要考慮另一種方法是通過來源資料矩陣,然後調用説明器方法的設計使設計矩陣的求解。説明器方法 MatrixCreate 分配空間,並返回一個與指定的行和列數的矩陣。本地 X 矩陣持有獨立變數 (與領先的 1.0 值) 的值。當地的 Y 矩陣只有一列和保存的值的變數 (在這個演示中的年度收入)。

接下來,使用設計矩陣中的值來填充矩陣 X 和 Y 中的儲存格:

int j;
for (int i = 0; i < rows; ++i)
{
  for (j = 0; j < cols - 1; ++j)
  {
    X[i][j] = design[i][j];
  }
  Y[i][0] = design[i][j]; // Last column
}

請注意,索引變數 j 宣佈外嵌套的 for 迴圈,所以它可以用來填充 Y 矩陣。用手中的 X 和 Y 矩陣,線性回歸係數可以發現方程所示圖 3:

...
  double[][] Xt = MatrixTranspose(X);
  double[][] XtX = MatrixProduct(Xt, X);
  double[][] inv = MatrixInverse(XtX);
  double[][] invXt = MatrixProduct(inv, Xt);
  double[][] mResult = MatrixProduct(invXt, Y);
  double[] result = MatrixToVector(mResult);
  return result;
} // Solve

在這個演示中,矩陣 X 有大小 10 x 4,因此,其轉置,Xt,具有大小為 4 x 10。Xt 和 X 產品具有大小為 4 x 4 和逆,inv,還具有大小為 4 x 4。一般情況下,為 n 的獨立預測變數,你需要找到與大小 (n + 1) x (n + 1) 矩陣的逆矩陣反演技術在使用時有線性回歸問題。這意味著反演技術不適合具有大量的預測變數的線性回歸問題。

4 x 4 的逆矩陣和 4 x 10 轉置矩陣,在代碼中,invXt 的產品具有大小為 4 x 10。InvXt 和 10 x 1 Y 矩陣,mResult ("矩陣結果") 在代碼中,該產品具有大小為 4 x 1。這些值是您需要的係數。為方便起見,單個列 Y 矩陣中的值被轉移到普通陣列使用 helper 方法 MatrixToVector。

計算 R 平方

如前所述,R 平方度量是如何很好的實際資料點擬合計算的迴歸線的措施。在數學術語中,R 平方定義為 R2 = 1-(SSres / SStot)。SSres 一詞通常被稱為"殘差平方和"。它是實際的 Y 值和預測的 Y 值,差值的平方的總和,如圖中所示圖 2。SStot 一詞是"總平方和"。它的平方的總和不同­之間每個實際的 Y 值和平均值 (平均) 的所有實際的 Y 值。

線性回歸中的 R 平方度量也被稱為係數的測定和有關,但從另一個不同統計度量名叫 r 平方 ("小 r-平方")。R 平方來解釋是有點棘手,取決於所調查的特定的問題領域。為自然科學和社會科學,在那裡資料通常是混亂的、 不完整,R 平方值為 0.6 或更通常被認為相當不錯。

那裡是替代措施的說明稱,調整的回歸模型的方差 R 平方。這個度量指標考慮到預測變數數目和的資料項目的數目。大多數情況下,使用普通的 R 平方值是不夠好,要得到一個線性回歸模型的預測品質的想法。

總結

如果你搜索互聯網如何進行線性迴歸分析,使用一種程式設計語言的示例,你不會找到很多引用。我認為有兩個主要原因為這缺乏相關的資訊。首先,求解線性回歸係數使用矩陣運算相當困難,主要是因為矩陣反轉操作。在某些方面,我認為該演示程式中寫過的最複雜的代碼常式的 MatrixInverse 方法。第二,有很多現有獨立的工具,可以執行線性回歸,特別是 Excel 試算表程式及其資料分析載入項中。 它是相對罕見,需要在軟體系統中直接嵌入線性回歸解決方案代碼。

幾十年來研究了線性回歸,有許多方法來擴展技術。例如,您可以引入所謂的組合兩個或多個預測變數的交互作用。這些擴展有時也稱為一般的線性模型,以區別于線性回歸的基本形式。

在我看來,線性回歸是經典統計的"Hello World"技術。並沒有明確,公認的經典統計和機器學習之間的區別,但我傾向于認為經典統計技術作為那些第一次進行了數學家在 20 世紀初開始。在我心中,機器學習技術,神經網路分類,像是那些更近,首先出現在 20 世紀 50 年代。經典統計線性回歸到一種機器學習技術叫做 logistic 迴歸分析,已運行測試的幾個列的主題密切相關。


Dr. James McCaffreyy* 適合在雷德蒙的微軟研究院  他曾在幾個 Microsoft 產品包括 Internet Explorer 和冰。 博士。 麥卡弗裡可達到 jammc@microsoft.com。*

感謝以下的微軟研究院技術專家對本文的審閱:Charles派克