首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 數學庫開發指南:以線性回歸為例

     編輯:PHP 綜合知識

背景與動機

PHP 社區缺乏成熟數學/統計庫,主因:既有工具(R、S System、Python SciPy)已極完善,透過 exec() 調用即可。但開發原生 PHP 數學庫具教學價值,能深化對算法理解,且避免進程切換開銷,適合輕量級內嵌計算場景。

設計六大原則

  1. 每個分析模型一個類:如 SimpleLinearRegression、MultipleRegression、ChiSquared
  2. 逆向鏈接開發:從期望輸出(報表、統計量)反推所需中間計算,再反推輸入數據結構
  3. 大量 Getter 方法:封裝中間結果(如 getSlope(), getIntercept(), getRSquared(), getStdError())
  4. 存儲中間結果:實例屬性緩存計算值,避免重複計算,供下游方法複用
  5. 豐富 API 選項:提供原始數值、格式化字串、JSON、陣列多種輸出
  6. 務實不求完美:優先實現核心算法正確,邊界情況、數值穩定性迭代優化

SimpleLinearRegression 類骨架

<?php
class SimpleLinearRegression {
    // 輸入數據
    private $x = array();
    private $y = array();
    private $n = 0;

    // 中間結果緩存
    private $sumX = null;
    private $sumY = null;
    private $sumXY = null;
    private $sumX2 = null;
    private $sumY2 = null;

    // 核心統計量
    private $slope = null;
    private $intercept = null;
    private $rSquared = null;
    private $stdError = null;

    public function __construct(array $x, array $y) {
        if (count($x) !== count($y)) throw new InvalidArgumentException('X/Y 長度必須相等');
        $this->x = $x;
        $this->y = $y;
        $this->n = count($x);
    }

    // 惰性計算中間和
    private function computeSums() {
        if ($this->sumX !== null) return;
        $sumX = $sumY = $sumXY = $sumX2 = $sumY2 = 0;
        for ($i = 0; $i < $this->n; $i++) {
            $sumX  += $this->x[$i];
            $sumY  += $this->y[$i];
            $sumXY += $this->x[$i] * $this->y[$i];
            $sumX2 += $this->x[$i] ** 2;
            $sumY2 += $this->y[$i] ** 2;
        }
        $this->sumX = $sumX; $this->sumY = $sumY; $this->sumXY = $sumXY;
        $this->sumX2 = $sumX2; $this->sumY2 = $sumY2;
    }

    private function computeCoefficients() {
        if ($this->slope !== null) return;
        $this->computeSums();
        $denom = $this->n * $this->sumX2 - $this->sumX ** 2;
        if ($denom == 0) throw new RuntimeException('X 變量無變異,無法擬合');
        $this->slope     = ($this->n * $this->sumXY - $this->sumX * $this->sumY) / $denom;
        $this->intercept = ($this->sumY - $this->slope * $this->sumX) / $this->n;
    }

    public function getSlope() { $this->computeCoefficients(); return $this->slope; }
    public function getIntercept() { $this->computeCoefficients(); return $this->intercept; }
    public function predict($x) { return $this->getSlope() * $x + $this->getIntercept(); }

    public function getRSquared() {
        if ($this->rSquared !== null) return $this->rSquared;
        $this->computeCoefficients();
        $this->computeSums();
        $ssTot = $this->sumY2 - $this->sumY ** 2 / $this->n;
        $ssRes = 0;
        for ($i = 0; $i < $this->n; $i++) {
            $yHat = $this->predict($this->x[$i]);
            $ssRes += ($this->y[$i] - $yHat) ** 2;
        }
        $this->rSquared = 1 - $ssRes / $ssTot;
        return $this->rSquared;
    }

    public function getStandardError() {
        if ($this->stdError !== null) return $this->stdError;
        $this->getRSquared(); // 確保 ssRes 計算
        $this->stdError = sqrt($ssRes / ($this->n - 2));
        return $this->stdError;
    }

    public function toArray() {
        return [
            'slope' => $this->getSlope(),
            'intercept' => $this->getIntercept(),
            'r_squared' => $this->getRSquared(),
            'std_error' => $this->getStandardError(),
            'n' => $this->n
        ];
    }

    public function __toString() {
        $a = $this->toArray();
        return sprintf(
            "Simple Linear Regression (n=%d)\nY = %.4f X + %.4f\nR² = %.4f\nStdErr = %.4f",
            $a['n'], $a['slope'], $a['intercept'], $a['r_squared'], $a['std_error']
        );
    }
}
?>

使用示例

$x = [1,2,3,4,5];
$y = [2,4,5,4,5];
$model = new SimpleLinearRegression($x, $y);
echo $model;               // 友好輸出
print_r($model->toArray()); // 結構化數據
echo "X=6 預測 Y = " . $model->predict(6);

擴展方向

  • 多元線性回歸(矩陣運算,建議引入 MathPHP 或自建簡易矩陣類)
  • 假設檢定:t-test, F-test, ANOVA
  • 時間序列:移動平均、指數平滑、ARIMA
  • 分佈函數:常態、T、F、卡方分佈的 CDF/PDF/反函數
  • 數值穩定性:QR 分解、SVD 替代正規方程求解

結語

開發 PHP 數學庫非重造輪子,而是為「可嵌入、無依賴、教學友好」場景提供選擇。遵循「單一模型單一類、逆向設計、緩存中間量、豐富 Getter」原則,可構建清晰、可維護、可擴展的數學組件庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved