support = self::getLabelIndexedArray($actualLabels, $predictedLabels); foreach ($actualLabels as $index => $actual) { $predicted = $predictedLabels[$index]; ++$this->support[$actual]; if ($actual === $predicted) { ++$truePositive[$actual]; } else { ++$falsePositive[$predicted]; ++$falseNegative[$actual]; } } $this->computeMetrics($truePositive, $falsePositive, $falseNegative); $this->computeAverage(); } public function getPrecision(): array { return $this->precision; } public function getRecall(): array { return $this->recall; } public function getF1score(): array { return $this->f1score; } public function getSupport(): array { return $this->support; } public function getAverage(): array { return $this->average; } private function computeMetrics(array $truePositive, array $falsePositive, array $falseNegative): void { foreach ($truePositive as $label => $tp) { $this->precision[$label] = $this->computePrecision($tp, $falsePositive[$label]); $this->recall[$label] = $this->computeRecall($tp, $falseNegative[$label]); $this->f1score[$label] = $this->computeF1Score((float) $this->precision[$label], (float) $this->recall[$label]); } } private function computeAverage(): void { foreach (['precision', 'recall', 'f1score'] as $metric) { $values = array_filter($this->{$metric}); if (empty($values)) { $this->average[$metric] = 0.0; continue; } $this->average[$metric] = array_sum($values) / count($values); } } /** * @return float|string */ private function computePrecision(int $truePositive, int $falsePositive) { $divider = $truePositive + $falsePositive; if ($divider == 0) { return 0.0; } return $truePositive / $divider; } /** * @return float|string */ private function computeRecall(int $truePositive, int $falseNegative) { $divider = $truePositive + $falseNegative; if ($divider == 0) { return 0.0; } return $truePositive / $divider; } private function computeF1Score(float $precision, float $recall): float { $divider = $precision + $recall; if ($divider == 0) { return 0.0; } return 2.0 * (($precision * $recall) / $divider); } private static function getLabelIndexedArray(array $actualLabels, array $predictedLabels): array { $labels = array_values(array_unique(array_merge($actualLabels, $predictedLabels))); sort($labels); $labels = array_combine($labels, array_fill(0, count($labels), 0)); return $labels; } }