From 64703f0adcca6f499b5b31f45c90ecf76e7d2049 Mon Sep 17 00:00:00 2001 From: Andrew DalPino Date: Sat, 22 Aug 2026 11:51:40 -0500 Subject: [PATCH 1/4] Initial commit --- src/AnomalyDetectors/GaussianMLE.php | 9 +++++++-- src/Classifiers/GaussianNB.php | 7 +++++-- src/Clusterers/GaussianMixture.php | 9 +++++++-- src/Helpers/Stats.php | 3 ++- src/Kernels/Distance/Cosine.php | 4 ++-- src/Kernels/Distance/Euclidean.php | 4 +++- src/Kernels/Distance/SafeEuclidean.php | 4 +++- src/Kernels/Distance/SparseCosine.php | 8 ++++---- 8 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/AnomalyDetectors/GaussianMLE.php b/src/AnomalyDetectors/GaussianMLE.php index 560a2963d..e7a791308 100644 --- a/src/AnomalyDetectors/GaussianMLE.php +++ b/src/AnomalyDetectors/GaussianMLE.php @@ -254,13 +254,15 @@ public function partial(Dataset $dataset) : void $oldVariance -= $this->epsilon; + $delta = $n * $oldMean - $n * $mean; + $this->means[$column] = (($this->n * $oldMean) + ($n * $mean)) / $weight; $this->variances[$column] = ($this->n * $oldVariance + ($n * $variance) + ($this->n / ($n * $weight)) - * ($n * $oldMean - $n * $mean) ** 2) + * ($delta * $delta)) / $weight; } @@ -346,7 +348,10 @@ protected function logLikelihood(array $sample) : float $variance = $this->variances[$column]; $pdf = 0.5 * log(TWO_PI * $variance); - $pdf += 0.5 * (($value - $mean) ** 2) / $variance; + + $delta = $value - $mean; + + $pdf += 0.5 * ($delta * $delta) / $variance; $likelihood += $pdf; } diff --git a/src/Classifiers/GaussianNB.php b/src/Classifiers/GaussianNB.php index 201987e50..ac801697a 100644 --- a/src/Classifiers/GaussianNB.php +++ b/src/Classifiers/GaussianNB.php @@ -273,6 +273,8 @@ public function partial(Dataset $dataset) : void [$mean, $variance] = Stats::meanVar($values); + $delta = $n * $oldMean - $n * $mean; + $means[] = (($n * $mean) + ($oldWeight * $oldMean)) / $weight; @@ -280,7 +282,7 @@ public function partial(Dataset $dataset) : void $variances[] = ($oldWeight * $oldVariance + ($n * $variance) + ($oldWeight / ($n * $weight)) - * ($n * $oldMean - $n * $mean) ** 2) + * ($delta * $delta)) / $weight; } } else { @@ -418,7 +420,8 @@ protected function jointLogLikelihood(array $sample) : array $variance = $variances[$column]; $pdf = -0.5 * log(TWO_PI * $variance); - $pdf -= 0.5 * (($value - $mean) ** 2) / $variance; + $delta = $value - $mean; + $pdf -= 0.5 * ($delta * $delta) / $variance; $likelihood += $pdf; } diff --git a/src/Clusterers/GaussianMixture.php b/src/Clusterers/GaussianMixture.php index 1c6e8d0f0..642b0dcf3 100644 --- a/src/Clusterers/GaussianMixture.php +++ b/src/Clusterers/GaussianMixture.php @@ -355,7 +355,9 @@ public function train(Dataset $dataset) : void $mean = $sigma / $total; foreach ($column as $i => $value) { - $ssd += $affinities[$i] * ($value - $mean) ** 2; + $delta = $value - $mean; + + $ssd += $affinities[$i] * $delta * $delta; } $variance = $ssd / $total; @@ -505,7 +507,10 @@ protected function jointLogLikelihood(array $sample) : array $variance = $variances[$column]; $pdf = -0.5 * log(TWO_PI * $variance); - $pdf -= 0.5 * (($feature - $mean) ** 2) / $variance; + + $delta = $feature - $mean; + + $pdf -= 0.5 * ($delta * $delta) / $variance; $likelihood += $pdf; } diff --git a/src/Helpers/Stats.php b/src/Helpers/Stats.php index ff63f2807..3716d9848 100644 --- a/src/Helpers/Stats.php +++ b/src/Helpers/Stats.php @@ -173,7 +173,8 @@ public static function variance(array $values, ?float $mean = null) : float $ssd = 0.0; foreach ($values as $value) { - $ssd += ($value - $mean) ** 2; + $delta = $value - $mean; + $ssd += $delta * $delta; } return $ssd / count($values); diff --git a/src/Kernels/Distance/Cosine.php b/src/Kernels/Distance/Cosine.php index 0635a20ce..09c54145c 100644 --- a/src/Kernels/Distance/Cosine.php +++ b/src/Kernels/Distance/Cosine.php @@ -54,8 +54,8 @@ public function compute(array $a, array $b) : float $sigma += $valueA * $valueB; - $ssA += $valueA ** 2; - $ssB += $valueB ** 2; + $ssA += $valueA * $valueA; + $ssB += $valueB * $valueB; } if ($ssA === 0.0 and $ssB === 0.0) { diff --git a/src/Kernels/Distance/Euclidean.php b/src/Kernels/Distance/Euclidean.php index 5f27dc84b..c8023aa93 100644 --- a/src/Kernels/Distance/Euclidean.php +++ b/src/Kernels/Distance/Euclidean.php @@ -44,7 +44,9 @@ public function compute(array $a, array $b) : float $distance = 0.0; foreach ($a as $i => $value) { - $distance += ($value - $b[$i]) ** 2; + $delta = $value - $b[$i]; + + $distance += $delta * $delta; } return sqrt($distance); diff --git a/src/Kernels/Distance/SafeEuclidean.php b/src/Kernels/Distance/SafeEuclidean.php index b8bc9d009..aa8e90802 100644 --- a/src/Kernels/Distance/SafeEuclidean.php +++ b/src/Kernels/Distance/SafeEuclidean.php @@ -68,7 +68,9 @@ public function compute(array $a, array $b) : float continue; } - $distance += ($valueA - $valueB) ** 2; + $delta = $valueA - $valueB; + + $distance += $delta * $delta; } $n = count($a); diff --git a/src/Kernels/Distance/SparseCosine.php b/src/Kernels/Distance/SparseCosine.php index 52e547c04..9575d7d1c 100644 --- a/src/Kernels/Distance/SparseCosine.php +++ b/src/Kernels/Distance/SparseCosine.php @@ -48,15 +48,15 @@ public function compute(array $a, array $b) : float if ($valueA != 0 and $valueB != 0) { $sigma += $valueA * $valueB; - $ssA += $valueA ** 2; - $ssB += $valueB ** 2; + $ssA += $valueA * $valueA; + $ssB += $valueB * $valueB; } else { if ($valueA != 0) { - $ssA += $valueA ** 2; + $ssA += $valueA * $valueA; } if ($valueB != 0) { - $ssB += $valueB ** 2; + $ssB += $valueB * $valueB; } } } From ef08ac99ee36e3bee6b274673d14df194e4b0eb9 Mon Sep 17 00:00:00 2001 From: Andrew DalPino Date: Sat, 22 Aug 2026 11:58:53 -0500 Subject: [PATCH 2/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/Clusterers/GaussianMixture.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Clusterers/GaussianMixture.php b/src/Clusterers/GaussianMixture.php index 642b0dcf3..3dd51840e 100644 --- a/src/Clusterers/GaussianMixture.php +++ b/src/Clusterers/GaussianMixture.php @@ -357,7 +357,7 @@ public function train(Dataset $dataset) : void foreach ($column as $i => $value) { $delta = $value - $mean; - $ssd += $affinities[$i] * $delta * $delta; +$ssd += $affinities[$i] * ($delta * $delta); } $variance = $ssd / $total; From 94c4810e257ad64a66aa368d9342cf786557481b Mon Sep 17 00:00:00 2001 From: Andrew DalPino Date: Sat, 22 Aug 2026 12:06:08 -0500 Subject: [PATCH 3/4] Fix coding style --- src/Clusterers/GaussianMixture.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Clusterers/GaussianMixture.php b/src/Clusterers/GaussianMixture.php index 3dd51840e..7ce152caa 100644 --- a/src/Clusterers/GaussianMixture.php +++ b/src/Clusterers/GaussianMixture.php @@ -357,7 +357,7 @@ public function train(Dataset $dataset) : void foreach ($column as $i => $value) { $delta = $value - $mean; -$ssd += $affinities[$i] * ($delta * $delta); + $ssd += $affinities[$i] * ($delta * $delta); } $variance = $ssd / $total; From 9a2aae618df19657507252d081e0c48de538cbbc Mon Sep 17 00:00:00 2001 From: Andrew DalPino Date: Sun, 23 Aug 2026 11:31:23 -0500 Subject: [PATCH 4/4] Factor mean delta --- src/AnomalyDetectors/GaussianMLE.php | 2 +- src/Classifiers/GaussianNB.php | 2 +- src/Transformers/ZScaleStandardizer.php | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/AnomalyDetectors/GaussianMLE.php b/src/AnomalyDetectors/GaussianMLE.php index e7a791308..97155fb39 100644 --- a/src/AnomalyDetectors/GaussianMLE.php +++ b/src/AnomalyDetectors/GaussianMLE.php @@ -254,7 +254,7 @@ public function partial(Dataset $dataset) : void $oldVariance -= $this->epsilon; - $delta = $n * $oldMean - $n * $mean; + $delta = $n * ($oldMean - $mean); $this->means[$column] = (($this->n * $oldMean) + ($n * $mean)) / $weight; diff --git a/src/Classifiers/GaussianNB.php b/src/Classifiers/GaussianNB.php index ac801697a..ebda4ca0c 100644 --- a/src/Classifiers/GaussianNB.php +++ b/src/Classifiers/GaussianNB.php @@ -273,7 +273,7 @@ public function partial(Dataset $dataset) : void [$mean, $variance] = Stats::meanVar($values); - $delta = $n * $oldMean - $n * $mean; + $delta = $n * ($oldMean - $mean); $means[] = (($n * $mean) + ($oldWeight * $oldMean)) diff --git a/src/Transformers/ZScaleStandardizer.php b/src/Transformers/ZScaleStandardizer.php index 39886a8be..c48552939 100644 --- a/src/Transformers/ZScaleStandardizer.php +++ b/src/Transformers/ZScaleStandardizer.php @@ -173,13 +173,15 @@ public function update(Dataset $dataset) : void [$mean, $variance] = Stats::meanVar($values); + $delta = $n * ($oldMean - $mean); + $this->means[$column] = (($this->n * $oldMean) + ($n * $mean)) / $weight; $this->variances[$column] = ($this->n * $oldVariance + ($n * $variance) + ($this->n / ($n * $weight)) - * ($n * $oldMean - $n * $mean) ** 2) + * ($delta * $delta)) / $weight; }