// Copyright 2003, 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 = "%01.2f"; // Used for formatting output
}
?>
构造函数
SimpleLinearRegression 类的构造函数方法接受一个 X和一个 Y向量,每个向量都有相同数量的值。您还可以为您预计的 Y值设置一个缺省为 95% 的置信区间(confidence interval)。
构造函数方法从验证数据形式是否适合于处理开始。一旦输入向量通过了“大小相等”和“值大于 1”测试,就执行算法的核心部分。
执行这项任务涉及到通过一系列 getter 方法计算统计过程的中间值和汇总值。将每个方法调用的返回值赋给该类的一个实例变量。用这种方法存储计算结果确保了前后链接的计算中的调用例程可以使用中间值和汇总值。还可以通过调用该类的输出方法来显示这些结果,如清单 2 所描述的那样。
清单 2. 调用类输出方法
// 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;
}
?>
方法名及其序列是通过结合逆向链接和参考大学本科学生使用的统计学教科书推导得出的,该教科书一步一步地说明了如何计算中间值。我需要计算的中间值的名称带有“get”前缀,从而推导出方法名。
使模型与数据相吻合
SimpleLinearRegression 过程用于产生与数据相吻合的直线,其中直线具有以下标准方程:
y = b + mx
该方程的 PHP 格式看起来类似于清单 3:
清单 3. 使模型与数据相吻合的 PHP 方程
$PredictedY[$i] = $YIntercept + $Slope * $X[$i]
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)来获得必要的值。我还想提醒大家注意该包,因为:
- R 提供了许多想法,PHP 开发人员可能会在 PHP 数学库中模拟这些想法。
- 有了 R,可以确定从 PHP 数学库获得的值与那些从成熟的免费可用的开放源码统计包中获得的值是否一致。
清单 4 中的代码演示了交给 R 来处理以获取一个值是多么容易。
清单 4. 交给 R 统计计算包来处理以获取一个值
// 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;
}
}
?>
请注意,这里已经设置了到 R 可执行文件的路径,并在两个函数中使用了该路径。第一个函数根据学生的 T 分布返回了与 T 统计值相关的概率值,而第二个反函数计算了与给定的 alpha 设置相对应的 T 统计值。 getStudentProb 方法用来评估线性模型的吻合程度; getInverseStudentProb 方法返回一个中间值,它用来计算每个预测的 Y值的置信区间。
由于篇幅有限,我不可能逐个详细说明这个类中的所有函数,因此如果您想搞清楚简单线性回归分析中所涉及的术语和步骤,我鼓励您参考大学本科学生使用的统计学教科书。
燃耗研究
要演示如何使用该类,我可以使用来自公共事业中燃耗(burnout)研究中的数据。Michael Leiter 和 Kimberly Ann Meechan 研究了称为 消耗指数(Exhaustion Index)的燃耗度量单位和称之为 集中度(Concentration)的独立变量之间的关系。集中度是指人们的社交接触中来自其工作环境的那部分比例。
要研究他们样本中个人的消耗指数值与集中度值之间的关系,请将这些值装入适当命名的数组中,并用这些数组值对该类进行实例化。对类进行实例化后,显示该类所生成的某些汇总值以评估线性模型与数据的吻合程度。
清单 5 显示了装入数据和显示汇总值的脚本:
清单 5. 用于装入数据并显示汇总值的脚本
// 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("%01.6f", $slr->SlopeProb);
?>
Equation: |
T: |
Prob > T: |
通过 Web 浏览器运行该脚本,产生以下输出:
Equation:
Exhaustion = -29.50 + (8.87 * Concentration)
T:
6.03
Prob > T:
0.000005
这张表的最后一行指出获取这样大 T值的 随机概率非常低。可以得出这样的结论:与仅仅使用消耗值的均值相比,简单线性模型的预测能力更好。
知道了某个人的工作场所联系的集中度,就可以用来预测他们可能正在消耗的燃耗程度。这个方程告诉我们:集中度值每增加 1 个单位,社会服务领域中一个人的消耗值就会增加 8 个单位。这进一步证明了:要减少潜在的燃耗,社会服务领域中的个人应当考虑在其工作场所之外结交朋友。
这只是粗略地描述了这些结果可能表示的含义。为全面研究这个数据集的含义,您可能想更详细地研究这个数据以确信这是正确的解释。在下一篇文章中我将讨论应当执行其它哪些分析。
您学到了什么?
其一,要开发意义重大的基于 PHP 的数学包,您不必是一名火箭科学家。坚持标准的面向对象技术,以及明确地采用逆向链接问题解决方法,就可以相对方便地使用 PHP 实现某些较为基本的统计过程。
从教学的观点出发,我认为:如果只是因为要求您在较高和较低的抽象层次思考统计测试或例程,那么这个练习是非常有用的。换句话说,补充您的统计测试或过程学习的一个好办法就是将这个过程作为算法实现。
要实现统计测试通常需要超出所给定的信息范围并创造性地解决和发现问题。对于发现对某个学科认识的不足而言,它也是一个好办法。
不利的一面,您发现 PHP 对于取样分布缺乏内在手段,而这是实现大多数统计测试所必需的。您需要交给 R 来处理以获取这些值,但是我担心您会没时间或没兴趣安装 R。某些常见概率函数的本机 PHP 实现可以解决这个问题。
另一个问题是:该类生成许多中间值和汇总值,但是汇总输出实际上没有利用这一点。我提供了一些难处理的输出,但是这既不够充分也没进行很好的组织,以致您无法充分地解释分析结果。实际上,我完全不知道如何可以将输出方法集成到该类中。这需要得到解决。
最后,要弄明白数据,不仅仅是察看汇总值就可以了。您还需要明白各个数据点是如何分布的。最好的办法之一是将您的数据绘制成图表。再次声明,我对这方面不太了解,但是如果要用这个类来分析实际数据的话就需要解决这个问题。
赞
If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)


QQ:154298438
QQ:417480759