exec_shell
调用,那么为何还要麻烦用 PHP 实现相同的统计计算功能呢?有关 S System、它的 ACM 奖或 R 的更多信息,请参阅相关参考资料。 SimpleLinearRegression
,它演示了一个可以用来开发 PHP 数学库的通用方法。让我们从讨论一些通用的原则开始,这些原则指导我开发这个 SimpleLinearRegression
类。 SimpleLinearRegression
类的开发。 MultipleRegression
、 TimeSeries
或 ChiSquared
)所希望生成的标准输出值。从解决问题的角度出发,这意味着您可以使用逆向链接来开发数学类的方法。 SimpleLinearRegression
类中的成员函数和实例变量制定命名方案时,我发现:如果我使用较长的名称(类似于 getSumSquaredError
这样的名称,而不是 getYY2
)来描述成员函数和实例变量,那么就更容易了解函数的操作内容和变量所代表的意义。 SimpleLinearRegression
类声明哪些变量。可以对 MultipleRegression
、 ANOVA
或 TimeSeries
过程执行类似的分析。 <code class="section"> .2f"; // Used for formatting output } ?> </code>
SimpleLinearRegression
类的构造函数方法接受一个 X和一个 Y向量,每个向量都有相同数量的值。您还可以为您预计的 Y值设置一个缺省为 95% 的置信区间(confidence interval)。 <code class="section"> <?php // Copyright 2003, Paul Meagher // Distributed under GPL function SimpleLinearRegression($X, $Y, $ConfidenceInterval="95") { $numX = count($X); $numY = count($Y); if ($numX != $numY) { die("Error: Size of X and Y vectors must be the same."); } if ($numX <= 1) { die("Error: Size of input array must be at least 2."); } $this->n = $numX; $this->X = $X; $this->Y = $Y; $this->ConfInt = $ConfidenceInterval; $this->Alpha = (1 ($this->ConfInt / 100) ) / 2; $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; } ?> </code>
SimpleLinearRegression
过程用于产生与数据相吻合的直线,其中直线具有以下标准方程: <code class="section"> $PredictedY[$i] = $YIntercept $Slope * $X[$i] </code>
SimpleLinearRegression
类使用最小二乘法准则推导出 Y 轴截距(Y Intercept)和斜率(Slope)参数的估计值。这些估计的参数用来构造线性方程(请参阅 清单 3),该方程对 X和 Y值之间的关系进行建模。
使用推导出的线性方程,您就可以得到每个 X值对应的预测 Y值。如果线性方程与数据非常吻合,那么 Y的观测值与预测值趋近于一致。
如何确定是否非常吻合 SimpleLinearRegression
类生成了相当多的汇总值。一个重要的汇总值是 T统计值,它可以用来衡量一个线性方程与数据的 吻合程度。如果非常吻合,那么 T 统计值往往很大。如果 T 统计值很小,那么应当用一个模型替换该线性方程,该模型假设 Y值的均值是最佳预测值(也就是说,一组值的均值通常是下一个观测值有用的预测值,使之成为缺省模型)。
要测试 T 统计值是否大得足以不把 Y值的均值作为最佳预测值,您需要计算获取 T 统计值的随机概率。如果获取 T 统计值的概率很低,那么您可以否定均值是最佳预测值这个无效假设,与此相对应,也就确信简单线性模型与数据非常吻合。
那么,如何计算 T 统计值的概率呢?
计算 T 统计值概率
由于 PHP 缺少计算 T 统计值概率的数学例程,因此我决定将此任务交给统计计算包 R(请参阅 参考资料中的 www.r-project.org)来获得必要的值。我还想提醒大家注意该包,因为:
清单 4 中的代码演示了交给 R 来处理以获取一个值是多么容易。
清单 4. 交给 R 统计计算包来处理以获取一个值
<code class="section"> <?php // Copyright 2003, Paul Meagher // Distributed under GPL class SimpleLinearRegression { var $RPath = "/usr/local/bin/R"; // Your path here function getStudentProb($T, $df) { $Probability = 0.0; $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 = 0.0; $cmd = "echo 'qt($alpha, $df)' | $this->RPath --slave"; $result = shell_exec($cmd); list($LineNumber, $InverseProbability) = explode(" ", trim($result)); return $InverseProbability; } } ?></code>
getStudentProb
方法用来评估线性模型的吻合程度; getInverseStudentProb
方法返回一个中间值,它用来计算每个预测的 Y值的置信区间。 <code class="section"> <?php // BurnoutStudy.php // Copyright 2003, Paul Meagher // Distributed under GPL include "SimpleLinearRegression.php"; // Load data from burnout study $Concentration = array(20,60,38,88,79,87, 68,12,35,70,80,92, 77,86,83,79,75,81, 75,77,77,77,17,85,96); $ExhaustionIndex = array(100,525,300,980,310,900, 410,296,120,501,920,810, 506,493,892,527,600,855, 709,791,718,684,141,400,970); $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(".6f", $slr->SlopeProb); ?> <table border="1" cellpadding="5"> <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> <td> </td> </tr> </table> </code>
Equation: | Exhaustion = -29.50 (8.87 * Concentration) |
T: | 6.03 |
Prob > T: | 0.000005 |