简介
与其它开放源码语言(比如 Perl 和 Python)相比,PHP 社区缺少强有力的工作来开发数学库。造成这种状况的一个原因可能是由于已经存在大量成熟的数学工具,这可能阻碍了社区自行开发 PHP 工具的工作。例如,我曾研究过一个功能强大的工具 S System,它拥有一组令人印象深刻的统计库,专门被设计成用来分析数据集,并且在 1998 年由于其语言设计而获得了 ACM 奖。如果 S 或者其开放源码同类 R 仅仅是一个 exec_shell 调用,那么为何还要麻烦用 PHP 实现相同的统计计算功能呢?有关 S System、它的 ACM 奖或 R 的更多信息,请参阅参考资料。
难道这不是在浪费开发人员的精力吗?如果开发 PHP 数学库的动机是出自节省开发人员的精力以及使用最好的工具来完成工作,那么 PHP 现在的课题是很有意义的。
另一方面,出于教学动机可能会鼓励对 PHP 数学库的开发。对于大约 10% 的人来说,数学是个值得探索的有趣课题。对于那些同时还熟练应用 PHP 的人来说,PHP 数学库的开发可以增强数学学习过程,换句话说,不要只阅读有关 T 测试的章节,还要实现一个能计算相应的中间值并用标准格式显示它们的类。
通过指导和训练,我希望证明开发 PHP 数学库并不是一项很难的任务,它可能代表一项有趣的技术和学习难题。在本文中,我将提供一个 PHP 数学库示例,名为 SimpleLinearRegression,它演示了一个可以用来开发 PHP 数学库的通用方法。让我们从讨论一些通用的原则开始,这些原则指导我开发这个 SimpleLinearRegression 类。
指导原则
我使用了六个通用原则来指导 SimpleLinearRegression 类的开发。
每个分析模型建立一个类。
使用逆向链接来开发类。
预计有大量的 getter。
存储中间结果。
为详细的 API 制定首选项。
尽善尽美并非目标。
让我们更详细地逐条研究这些指导方针。
每个分析模型建立一个类
每种主要的分析测试或过程应当有一个名称与测试或过程名相同的 PHP 类,这个类包含了输入函数、计算中间值和汇总值的函数和输出函数(将中间值和汇总值用文本或图形格式全部显示在屏幕上)。
使用逆向链接来开发类
在数学编程中,编码的目标通常是分析过程(比如 MultipleRegression、TimeSeries 或 ChiSquared)所希望生成的标准输出值。从解决问题的角度出发,这意味着您可以使用逆向链接来开发数学类的方法。
例如,汇总输出屏幕显示了一个或多个汇总统计结果。这些汇总统计结果依赖于中间统计结果的计算,这些中间统计结果又可能会涉及到更深一层的中间统计结果,以此类推。这个基于逆向链接的开发方法导出了下一个原则。
预计有大量的 getter
数学类的大部分类开发工作都涉及到计算中间值和汇总值。实际上,这意味着,如果您的类包含许多计算中间值和汇总值的 getter 方法,您不应当感到惊讶。
存储中间结果
将中间计算结果存储在结果对象内,这样您就可以将中间结果用作后续计算的输入。在 S 语言设计中实施了这一原则。在当前环境下,通过选择实例变量来表示计算得到的中间值和汇总结果,从而实施了该原则。
为详细的 API 制定首选项
SimpleLinearRegression クラスのメンバー関数とインスタンス変数の命名スキームを開発するときに、メンバー関数とインスタンス変数を記述するために長い名前 (getYY2 の代わりに getSumSquaredError など) を使用すると、より簡単であることがわかりました。関数の演算内容と変数の意味を理解する。
私は短縮名を完全に放棄したわけではありません。ただし、名前の短縮形を使用する場合は、名前の意味を完全に説明するコメントを提供するように努めなければなりません。私の見解は次のとおりです。高度に省略された命名スキームは数学的プログラミングでは一般的ですが、特定の数学的ルーチンを理解し、正しいことを証明することが必要以上に困難になります。
完璧は目標ではありません
このコーディング演習の目標は、必ずしも PHP 用に高度に最適化された厳密な数学エンジンを開発することではありません。初期段階では、有意義な分析テストの実装方法を学び、この分野の困難な問題を解決することに重点を置く必要があります。
インスタンス変数: 統計テストまたはプロセスをモデル化する場合、どのインスタンス変数が宣言されているかを示す必要があります。
インスタンス変数の選択は、分析プロセスによって生成された中間値と要約値を考慮して決定できます。各中間値と要約値は、変数の値をオブジェクト プロパティとして持つ、対応するインスタンス変数を持つことができます。
この分析を使用して、リスト 1 の SimpleLinearRegression クラスに対して宣言する変数を決定しました。同様の分析は、MultipleRegression、ANOVA、または TimeSeries プロシージャでも実行できます。
<ccid_code><?php // 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 } ?> </ccid_code> ログイン後にコピー |
クラスのコンストラクター メソッドは、X ベクトルと Y ベクトルを受け入れます。同じ数の値。予想される Y 値のデフォルトの 95% 信頼区間を設定することもできます。 コンストラクター メソッドは、データ形式が処理に適しているかどうかを検証することから始まります。入力ベクトルが「等しいサイズ」テストと「1 より大きい値」テストに合格すると、アルゴリズムのコア部分が実行されます。 このタスクの実行には、一連のゲッター メソッドによる統計プロセスの中間値と要約値の計算が含まれます。各メソッド呼び出しの戻り値をクラスのインスタンス変数に代入します。この方法で計算結果を保存すると、連鎖計算の呼び出しルーチンで中間値と要約値を確実に利用できるようになります。リスト 2 で説明されているように、クラスの出力メソッドを呼び出してこれらの結果を表示することもできます。
<ccid_code><?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; } ?></ccid_code> ログイン後にコピー |