簡要回顧:概念 簡單線性回歸建模背後的基本目標是從成對的 X 值和 Y 值(即 X 和 Y 測量值)組成的二維平面中找到最吻合的直線。一旦用最小方差法找到這條直線,就可以執行各種統計測試,以確定這條直線與觀測到的 Y 值的偏離量吻合程度。 線性方程(y = mx + b)有兩個參數必須根據所提供的 X 和 Y 數據估算出來,它們是斜率(m)和 y 軸截距(b)。一旦估算出這兩個參數,就可以將觀測值輸入線性方程,並觀察方程所生成的 Y 預測值。 要使用最小方差法估算出 m 和 b 參數,就要找到 m 和 b 的估計值,使它們對於所有的 X 值得到的 Y 值的觀測值和預測值最小。觀測值和預測值之差稱為誤差(yi - (mxi + b)),並且,如果對每個誤差值都求平方,然後求這些殘差的和,其結果是一個被稱為預測平方差的數。使用最小方差法來確定最吻合的直線涉及尋找使預測方差最小的 m 和 b 的估計值。 可以用兩種基本方法來找到滿足最小方差法的估計值 m 和 b。第一種方法,可以使用數值搜索過程設定不同的 m 和 b 值並對它們求值,最終決定產生最小方差的估計值。第二種方法是使用微積分找到用於估算 m 和 b 的方程。我不打算深入討論推導出這些方程所涉及的微積分,但我確實在 SimpleLinearRegression 類中使用了這些分析方程,以找到 m 和 b 的最小平方估計值(請參閱 SimpleLinearRegression 類中的 getSlope() 和 getYIntercept 方法)。 即使擁有了可以用來找到 m 和 b 的最小平方估計值的方程,也並不意味著只要將這些參數代入線性方程,其結果就是一條與數據良好吻合的直線。這個簡單線性回歸過程中的下一步是確定其余的預測方差是否可以接受。 可以使用統計決策過程來否決“直線與數據吻合”這個備擇假設。這個過程基於對 T 統計值的計算,使用概率函數求得隨機大的觀測值的概率。正如第 1 部分所提到的,SimpleLinearRegression 類生成了為數眾多的匯總值,其中一個重要的匯總值是 T 統計值,它可以用來衡量線性方程與數據的吻合程度。如果吻合良好,則 T 統計值往往是一個較大的值;如果 T 值很小,就應該用一個缺省模型代替您的線性方程,該模型假定 Y 值的平均值是最佳預測值(因為一組值的平均值通常可以是下一個觀測值的有用的預測值)。 要測試 T 統計值是否大到可以不用 Y 值的平均值作為最佳預測值,需要計算隨機獲得 T 統計值的概率。如果概率很低,那就可以不采用平均值是最佳預測值這一無效假設,並且相應地可以確信簡單線性模型是與數據良好吻合的。(有關計算 T 統計值概率的更多信息,請參閱第 1 部分。) 回過頭討論統計決策過程。它告訴您何時不采用無效假設,卻沒有告訴您是否接受備擇假設。在研究環境中,需要通過理論參數和統計參數來建立線性模型備擇假設。 您將構建的數據研究工具實現了用於線性模型(T 測試)的統計決策過程,並提供了可以用來構造理論和統計參數的匯總數據,這些參數是建立線性模型所需要的。數據研究工具可以歸類為決策支持工具,供知識工作者在中小規模的數據集中研究模式。 從學習的角度來看,簡單線性回歸建模值得研究,因為它是理解更高級形式的統計建模的必由之路。例如,簡單線性回歸中的許多核心概念為理解多次回歸(Multiple Regression)、要素分析(Factor Analysis)和時間序列(Time Series)等建立了良好的基礎。 簡單線性回歸還是一種多用途的建模技術。通過轉換原始數據(通常用對數或冪轉換),可以用它來為曲線數據建模。這些轉換可以使數據線性化,這樣就可以使用簡單線性回歸來為數據建模。所生成的線性模型將被表示為與被轉換值相關的線性公式。
概率函數 在前一篇文章中,我通過交由 R 來求得概率值,從而避開了用 PHP 實現概率函數的問題。我對這個解決方案並非完全滿意,因此我開始研究這個問題:開發基於 PHP 的概率函數需要些什麼。 我開始上網查找信息和代碼。一個兩者兼有的來源是書籍 Numerical Recipes in C 中的概率函數。我用 PHP 重新實現了一些概率函數代碼(gammln.c 和 betai.c 函數),但我對結果還是不滿意。與其它一些實現相比,其代碼似乎多了些。此外,我還需要反概率函數。 幸運的是,我偶然發現了 John Pezzullo 的 Interactive Statistical Calculation。John 關於概率分布函數的網站上有我需要的所有函數,為便於學習,這些函數已用 javascript 實現。 我將 Student T 和 Fisher F 函數移植到了 PHP。我對 API 作了一點改動,以便符合 Java 命名風格,並將所有函數嵌入到名為 Distribution 的類中。該實現的一個很棒的功能是 doCommonMath 方法,這個庫中的所有函數都重用了它。我沒有花費力氣去實現的其它測試(正態測試和卡方測試)也都使用 doCommonMath 方法。 這次移植的另一個方面也值得注意。通過使用 JavaScript,用戶可以將動態確定的值賦給實例變量,譬如: var PiD2 = pi() / 2 在 PHP 中不能這樣做。只能把簡單的常量值賦給實例變量。希望在 PHP5 中會解決這個缺陷。 請注意清單 1 中的代碼並未定義實例變量 — 這是因為在 JavaScript 版本中,它們是動態賦予的值。
清單 1. 實現概率函數 <?php // Distribution.php // Copyright John Pezullo // Released under same terms as PHP. // PHP Port and OO'fying by Paul Meagher class Distribution { function doCommonMath($q, $i, $j, $b) { $zz = 1; $z = $zz; $k = $i; while($k <= $j) { $zz = $zz * $q * $k / ($k - $b); $z = $z + $zz; $k = $k + 2; } return $z; } function getStudentT($t, $df) { $t = abs($t); $w = $t / sqrt($df); $th = atan($w); if ($df == 1) { return 1 - $th / (pi() / 2); } $sth = sin($th); $cth = cos($th); if( ($df % 2) ==1 ) { return 1 - ($th + $sth * $cth * $this->doCommonMath($cth * $cth, 2, $df - 3, -1)) / (pi()/2); } else { return 1 - $sth * $this->doCommonMath($cth * $cth, 1, $df - 3, -1); } } function getInverseStudentT($p, $df) { $v = 0.5; $dv = 0.5; $t = 0; while($dv > 1e-6) { $t = (1 / $v) - 1; $dv = $dv / 2; if ( $this->getStudentT($t, $df) > $p) { $v = $v - $dv; } else { $v = $v + $dv; } } return $t; } function getFisherF($f, $n1, $n2) { // implemented but not shown } function getInverseFisherF($p, $n1, $n2) { // implemented but not shown } } ?>
輸出方法 既然您已經用 PHP 實現了概率函數,那麼開發基於 PHP 的數據研究工具剩下的唯一難題就是設計用於顯示分析結果的方法。 簡單的解決方案是根據需要將所有實例變量的值都顯示到屏幕上。在第一篇文章中,當顯示燃耗研究(Burnout Study)的線性方程、T 值和 T 概率時,我就是這麼做的。能根據特定目的而訪問特定值是很有幫助的,SimpleLinearRegression 支持此類用法。 然而,另一種用於輸出結果的方法是將輸出的各部分系統化地進行分組。如果研究用於回歸分析的主要統計軟件包的輸出,就會發現它們往往是用同樣的方式對輸出進行分組的。它們往往有摘要表(Summary Table)、偏離值分析(Analysis Of Variance)表、參數估計值(Parameter Estimate)表和 R 值(R Value)。類似地,我創建了一些輸出方法,名稱如下: showSummaryTable() showAnalysisOfVariance() showParameterEstimates() showRValues() 我還有一個用於顯示線性預測公式的方法(getFormula())。許多統計軟件包不輸出公式,而是希望用戶根據上述方法的輸出構造公式。部分是由於您最後用來對數據建模的公式的最終形式可能由於下列原因而與缺省公式不同: Y 軸截距沒有有意義的解釋,或者 輸入值可能是經過轉換的,而您可能需要取消對它們的轉換以獲取最終的解釋。 所有這些方法都假定輸出媒介是網頁。考慮到您有可能希望用非網頁的其它媒介輸出這些匯總值,所以我決定將這些輸出方法包裝在一個繼承了 SimpleLinearRegression 類的類中。清單 2 中的代碼旨在演示輸出類的通用邏輯。為了使通用邏輯更突出,所以除去了實現各種 show 方法的代碼。
清單 2. 演示輸出類的通用邏輯 <?php // Html.php // Copyright 2003, Paul Meagher // Distributed under GPL include_once "slr/SimpleLinearRegression.php"; class SimpleLinearRegressionHTML extends SimpleLinearRegression { function SimpleLinearRegressionHTML($X, $Y, $conf_int) { SimpleLinearRegression::SimpleLinearRegression($X, $Y, $conf_int); } function showTableSummary($x_name, $y_name) {