熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> PHP編程 >> 正文

PHP實現簡單線性回歸之數學庫的重要性

2013-11-15 12:24:03  來源: PHP編程 

  與其它開放源碼語言(比如 Perl 和 Python)相比PHP 社區缺少強有力的工作來開發數學庫

  造成這種狀況的一個原因可能是由於已經存在大量成熟的數學工具這可能阻礙了社區自行開發 PHP 工具的工作例如我曾研究過一個功能強大的工具 S System它擁有一組令人印象深刻的統計庫專門被設計成用來分析數據集並且在 年由於其語言設計而獲得了 ACM 獎如果 S 或者其開放源碼同類 R 僅僅是一個 exec_shell 調用那麼為何還要麻煩用 PHP 實現相同的統計計算功能呢?有關 S System它的 ACM 獎或 R 的更多信息請參閱相關參考資料

  難道這不是在浪費開發人員的精力嗎?如果開發 PHP 數學庫的動機是出自節省開發人員的精力以及使用最好的工具來完成工作那麼 PHP 現在的課題是很有意義的

  另一方面出於教學動機可能會鼓勵對 PHP 數學庫的開發對於大約 % 的人來說數學是個值得探索的有趣課題對於那些同時還熟練應用 PHP 的人來說PHP 數學庫的開發可以增強數學學習過程換句話說不要只 閱讀有關 T 測試的章節還要 實現一個能計算相應的中間值並用標准格式顯示它們的類

  通過指導和訓練我希望證明開發 PHP 數學庫並不是一項很難的任務它可能代表一項有趣的技術和學習難題在本文中我將提供一個 PHP 數學庫示例名為 SimpleLinearRegression 它演示了一個可以用來開發 PHP 數學庫的通用方法讓我們從討論一些通用的原則開始這些原則指導我開發這個 SimpleLinearRegression 類

  指導原則

  我使用了六個通用原則來指導 SimpleLinearRegression 類的開發

  每個分析模型建立一個類 
使用逆向鏈接來開發類 
預計有大量的 getter 
存儲中間結果 
為詳細的 API 制定首選項 
盡善盡美並非目標

  讓我們更詳細地逐條研究這些指導方針

每個分析模型建立一個類

  每種主要的分析測試或過程應當有一個名稱與測試或過程名相同的 PHP 類這個類包含了輸入函數計算中間值和匯總值的函數和輸出函數(將中間值和匯總值用文本或圖形格式全部顯示在屏幕上)

  使用逆向鏈接來開發類

  在數學編程中編碼的目標通常是分析過程(比如 MultipleRegression TimeSeries 或 ChiSquared )所希望生成的標准輸出值從解決問題的角度出發這意味著您可以使用逆向鏈接來開發數學類的方法

  例如匯總輸出屏幕顯示了一個或多個匯總統計結果這些匯總統計結果依賴於中間統計結果的計算這些中間統計結果又可能會涉及到更深一層的中間統計結果以此類推這個基於逆向鏈接的開發方法導出了下一個原則

  預計有大量的 getter

  數學類的大部分類開發工作都涉及到計算中間值和匯總值實際上這意味著如果您的類包含許多計算中間值和匯總值的 getter 方法您不應當感到驚訝

  存儲中間結果

  將中間計算結果存儲在結果對象內這樣您就可以將中間結果用作後續計算的輸入在 S 語言設計中實施了這一原則在當前環境下通過選擇實例變量來表示計算得到的中間值和匯總結果從而實施了該原則

  為詳細的 API 制定首選項

  當為 SimpleLinearRegression 類中的成員函數和實例變量制定命名方案時我發現如果我使用較長的名稱(類似於 getSumSquaredError 這樣的名稱而不是 getYY )來描述成員函數和實例變量那麼就更容易了解函數的操作內容和變量所代表的意義

  我沒有完全放棄簡寫名稱但是當我用簡寫形式的名稱時我得設法提供注釋以完整闡述該名稱的含義我的看法是高度簡寫的命名方案在數學編程中很常見但它們使得理解和證明某個數學例程是否按部就班更為困難而原本不必造成此種困難

  盡善盡美並非目標

  這個編碼練習的目標不是一定要為 PHP 開發高度優化和嚴格的數學引擎在早期階段應當強調學習實現意義重大的分析測試以及解決這方面的難題

  實例變量

  當對統計測試或過程進行建模時您需要指出聲明哪些實例變量

  實例變量的選擇可以通過說明由分析過程生成的中間值和匯總值來確定每個中間值和匯總值都可以有一個相應的實例變量將變量的值作為對象屬性

  我采用這樣的分析來確定為清單 中的 SimpleLinearRegression 類聲明哪些變量可以對 MultipleRegression ANOVA 或 TimeSeries 過程執行類似的分析

  清單 SimpleLinearRegression 類的實例變量
 
<?php  
// Copyright Paul Meagher  
// Distributed under GPL    
class SimpleLinearRegression {  
  var $n;  
  var $X = array(); 
  var $Y = array();   
  var $ConfInt;   
  var $Alpha; 
  var $XMean; 
  var $YMean; 
  var $SumXX; 
  var $SumXY; 
  var $SumYY;   
  var $Slope; 
  var $YInt;   
  var $PredictedY   = array(); 
  var $Error        = array(); 
  var $SquaredError = array(); 
  var $TotalError;   
  var $SumError; 
  var $SumSquaredError;   
  var $ErrorVariance; 
  var $StdErr; 
  var $SlopeStdErr;   
  var $SlopeVal;   // T value of Slope  
  var $YIntStdErr;     
  var $YIntTVal;   // T value for Y Intercept 
  var $R; 
  var $RSquared;     
  var $DF;         // Degrees of Freedom 
  var $SlopeProb;  // Probability of Slope Estimate 
  var $YIntProb;   // Probability of Y Intercept Estimate 
  var $AlphaTVal;  // T Value for given alpha setting 
  var $ConfIntOfSlope;         
   
  var $RPath  = "/usr/local/bin/R";  // Your path here 
   
  var $format = "%f"; // Used for formatting output  
   

?> 
 
構造函數

  SimpleLinearRegression 類的構造函數方法接受一個 X和一個 Y向量每個向量都有相同數量的值您還可以為您預計的 Y值設置一個缺省為 % 的置信區間(confidence interval)

  構造函數方法從驗證數據形式是否適合於處理開始一旦輸入向量通過了“大小相等”和“值大於 ”測試就執行算法的核心部分

  執行這項任務涉及到通過一系列 getter 方法計算統計過程的中間值和匯總值將每個方法調用的返回值賦給該類的一個實例變量用這種方法存儲計算結果確保了前後鏈接的計算中的調用例程可以使用中間值和匯總值還可以通過調用該類的輸出方法來顯示這些結果如清單 所描述的那樣

  清單 調用類輸出方法

  
<?php  
// Copyright Paul Meagher  
// Distributed under GPL    
function SimpleLinearRegression($X $Y $ConfidenceInterval="") { 
  $numX = count($X); 
  $numY = count($Y); 
  if ($numX != $numY) { 
    die("Error: Size of X and Y vectors must be the same"); 
  }  
  if ($numX <= ) {  
    die("Error: Size of input array must be at least "); 
  } 
   
  $this>n               = $numX; 
  $this>X               = $X; 
  $this>Y               = $Y;   
   
  $this>ConfInt         = $ConfidenceInterval;  
  $this>Alpha           = ( + ($this>ConfInt / ) ) /
  $this>XMean           = $this>getMean($this>X); 
  $this>YMean           = $this>getMean($this>Y); 
  $this>SumXX           = $this>getSumXX(); 
  $this>SumYY           = $this>getSumYY(); 
  $this>SumXY           = $this>getSumXY();     
  $this>Slope           = $this>getSlope(); 
  $this>YInt            = $this>getYInt(); 
  $this>PredictedY      = $this>getPredictedY(); 
  $this>Error           = $this>getError(); 
  $this>SquaredError    = $this>getSquaredError(); 
  $this>SumError        = $this>getSumError(); 
  $this>TotalError      = $this>getTotalError();     
  $this>SumSquaredError = $this>getSumSquaredError(); 
  $this>ErrorVariance   = $this>getErrorVariance(); 
  $this>StdErr          = $this>getStdErr();   
  $this>SlopeStdErr     = $this>getSlopeStdErr();      
  $this>YIntStdErr      = $this>getYIntStdErr();          
  $this>SlopeTVal       = $this>getSlopeTVal();             
  $this>YIntTVal        = $this>getYIntTVal();                 
  $this>R               = $this>getR();    
  $this>RSquared        = $this>getRSquared(); 
  $this>DF              = $this>getDF();           
  $this>SlopeProb       = $this>getStudentProb($this>SlopeTVal $this>DF); 
  $this>YIntProb        = $this>getStudentProb($this>YIntTVal $this>DF); 
  $this>AlphaTVal       = $this>getInverseStudentProb($this>Alpha $this>DF); 
  $this>ConfIntOfSlope  = $this>getConfIntOfSlope();  
  return true; 

?> 
 

  方法名及其序列是通過結合逆向鏈接和參考大學本科學生使用的統計學教科書推導得出的該教科書一步一步地說明了如何計算中間值我需要計算的中間值的名稱帶有“get”前綴從而推導出方法名

  使模型與數據相吻合

  SimpleLinearRegression 過程用於產生與數據相吻合的直線其中直線具有以下標准方程

  y = b + mx

  該方程的 PHP 格式看起來類似於清單

  清單 使模型與數據相吻合的 PHP 方程

  
$PredictedY[$i] = $YIntercept + $Slope * $X[$i] 
 

  SimpleLinearRegression 類使用最小二乘法准則推導出 Y 軸截距(Y Intercept)和斜率(Slope)參數的估計值這些估計的參數用來構造線性方程(請參閱 清單 該方程對 X和 Y值之間的關系進行建模

  使用推導出的線性方程您就可以得到每個 X值對應的預測 Y值如果線性方程與數據非常吻合那麼 Y的觀測值與預測值趨近於一致

  如何確定是否非常吻合

  SimpleLinearRegression 類生成了相當多的匯總值一個重要的匯總值是 T統計值它可以用來衡量一個線性方程與數據的 吻合程度如果非常吻合那麼 T 統計值往往很大如果 T 統計值很小那麼應當用一個模型替換該線性方程該模型假設 Y值的均值是最佳預測值(也就是說一組值的均值通常是下一個觀測值有用的預測值使之成為缺省模型)

  要測試 T 統計值是否大得足以不把 Y值的均值作為最佳預測值您需要計算獲取 T 統計值的隨機概率如果獲取 T 統計值的概率很低那麼您可以否定均值是最佳預測值這個無效假設與此相對應也就確信簡單線性模型與數據非常吻合

  那麼如何計算 T 統計值的概率呢?

  計算 T 統計值概率

  由於 PHP 缺少計算 T 統計值概率的數學例程因此我決定將此任務交給統計計算包 R(請參閱 參考資料中的 wwwrprojectorg)來獲得必要的值我還想提醒大家注意該包因為

  R 提供了許多想法PHP 開發人員可能會在 PHP 數學庫中模擬這些想法 
有了 R可以確定從 PHP 數學庫獲得的值與那些從成熟的免費可用的開放源碼統計包中獲得的值是否一致 
清單 中的代碼演示了交給 R 來處理以獲取一個值是多麼容易

  清單 交給 R 統計計算包來處理以獲取一個值

  
<?php  
// Copyright Paul Meagher  
// Distributed under GPL    
class SimpleLinearRegression {  
    
  var $RPath  = "/usr/local/bin/R";  // Your path here 
  function getStudentProb($T $df) {     
    $Probability = ;    
    $cmd = "echo dt($T $df) | $this>RPath slave";  
    $result = shell_exec($cmd);     
    list($LineNumber $Probability) = explode(" " trim($result));  
    return $Probability; 
  } 
  function getInverseStudentProb($alpha $df) {   
    $InverseProbability = ;  
    $cmd = "echo qt($alpha $df) | $this>RPath slave";  
    $result = shell_exec($cmd);   
    list($LineNumber $InverseProbability) = explode(" " trim($result));  
    return $InverseProbability; 
  } 

?>

  請注意這裡已經設置了到 R 可執行文件的路徑並在兩個函數中使用了該路徑第一個函數根據學生的 T 分布返回了與 T 統計值相關的概率值而第二個反函數計算了與給定的 alpha 設置相對應的 T 統計值 getStudentProb 方法用來評估線性模型的吻合程度 getInverseStudentProb 方法返回一個中間值它用來計算每個預測的 Y值的置信區間

  由於篇幅有限我不可能逐個詳細說明這個類中的所有函數因此如果您想搞清楚簡單線性回歸分析中所涉及的術語和步驟我鼓勵您參考大學本科學生使用的統計學教科書

  燃耗研究

  要演示如何使用該類我可以使用來自公共事業中燃耗(burnout)研究中的數據Michael Leiter 和 Kimberly Ann Meechan 研究了稱為 消耗指數(Exhaustion Index)的燃耗度量單位和稱之為 集中度(Concentration)的獨立變量之間的關系集中度是指人們的社交接觸中來自其工作環境的那部分比例

  要研究他們樣本中個人的消耗指數值與集中度值之間的關系請將這些值裝入適當命名的數組中並用這些數組值對該類進行實例化對類進行實例化後顯示該類所生成的某些匯總值以評估線性模型與數據的吻合程度

  清單 顯示了裝入數據和顯示匯總值的腳本

  清單 用於裝入數據並顯示匯總值的腳本

  
<?php  
// BurnoutStudyphp 
// Copyright Paul Meagher  
// Distributed under GPL    
include "SimpleLinearRegressionphp";  
// Load data from burnout study  
$Concentration   = array(  
                           
                           
                         );   
                           
$ExhaustionIndex = array(  
                           
                           
                         );   
                           
$slr = new SimpleLinearRegression($Concentration $ExhaustionIndex);   
$YInt      = sprintf($slr>format $slr>YInt); 
$Slope     = sprintf($slr>format $slr>Slope);     
$SlopeTVal = sprintf($slr>format $slr>SlopeTVal);     
$SlopeProb = sprintf("%f" $slr>SlopeProb);     
?> 
<table border= cellpadding=
  <tr> 
    <th align=right>Equation:</th> 
    <td></td> 
  </tr> 
  <tr> 
    <th align=right>T:</th> 
    <td></td> 
  </tr> 
  <tr> 
    <th align=right>Prob > T:</th> 
    <td><td> 
  </tr> 
</table> 
 

  通過 Web 浏覽器運行該腳本產生以下輸出

  Equation: Exhaustion = + ( * Concentration)  
T:   
Prob > T: 

  這張表的最後一行指出獲取這樣大 T值的 隨機概率非常低可以得出這樣的結論與僅僅使用消耗值的均值相比簡單線性模型的預測能力更好

  知道了某個人的工作場所聯系的集中度就可以用來預測他們可能正在消耗的燃耗程度這個方程告訴我們集中度值每增加 個單位社會服務領域中一個人的消耗值就會增加 個單位這進一步證明了要減少潛在的燃耗社會服務領域中的個人應當考慮在其工作場所之外結交朋友

  這只是粗略地描述了這些結果可能表示的含義為全面研究這個數據集的含義您可能想更詳細地研究這個數據以確信這是正確的解釋在下一篇文章中我將討論應當執行其它哪些分析

  您學到了什麼?

  其一要開發意義重大的基於 PHP 的數學包您不必是一名火箭科學家堅持標准的面向對象技術以及明確地采用逆向鏈接問題解決方法就可以相對方便地使用 PHP 實現某些較為基本的統計過程

  從教學的觀點出發我認為如果只是因為要求您在較高和較低的抽象層次思考統計測試或例程那麼這個練習是非常有用的換句話說補充您的統計測試或過程學習的一個好辦法就是將這個過程作為算法實現

  要實現統計測試通常需要超出所給定的信息范圍並創造性地解決和發現問題對於發現對某個學科認識的不足而言它也是一個好辦法

  不利的一面您發現 PHP 對於取樣分布缺乏內在手段而這是實現大多數統計測試所必需的您需要交給 R 來處理以獲取這些值但是我擔心您會沒時間或沒興趣安裝 R某些常見概率函數的本機 PHP 實現可以解決這個問題

  另一個問題是該類生成許多中間值和匯總值但是匯總輸出實際上沒有利用這一點我提供了一些難處理的輸出但是這既不夠充分也沒進行很好的組織以致您無法充分地解釋分析結果實際上我完全不知道如何可以將輸出方法集成到該類中這需要得到解決

  最後要弄明白數據不僅僅是察看匯總值就可以了您還需要明白各個數據點是如何分布的最好的辦法之一是將您的數據繪制成圖表再次聲明我對這方面不太了解但是如果要用這個類來分析實際數據的話就需要解決這個問題


From:http://tw.wingwit.com/Article/program/PHP/201311/20872.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.