Update easy coding standard to ^5.1 (#317)
This commit is contained in:
parent
9c9705a32c
commit
0beb407b16
|
@ -28,8 +28,8 @@
|
|||
"phpstan/phpstan-shim": "^0.9",
|
||||
"phpstan/phpstan-strict-rules": "^0.9.0",
|
||||
"phpunit/phpunit": "^7.0.0",
|
||||
"symplify/coding-standard": "^4.4",
|
||||
"symplify/easy-coding-standard": "^4.4"
|
||||
"symplify/coding-standard": "^5.1",
|
||||
"symplify/easy-coding-standard": "^5.1"
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,8 @@ use Phpml\Helper\Trainable;
|
|||
|
||||
class Apriori implements Associator
|
||||
{
|
||||
use Trainable, Predictable;
|
||||
use Trainable;
|
||||
use Predictable;
|
||||
|
||||
public const ARRAY_KEY_ANTECEDENT = 'antecedent';
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ use Phpml\Math\Statistic\Mean;
|
|||
|
||||
class DecisionTree implements Classifier
|
||||
{
|
||||
use Trainable, Predictable;
|
||||
use Trainable;
|
||||
use Predictable;
|
||||
|
||||
public const CONTINUOUS = 1;
|
||||
|
||||
|
@ -31,7 +32,7 @@ class DecisionTree implements Classifier
|
|||
/**
|
||||
* @var DecisionTreeLeaf
|
||||
*/
|
||||
protected $tree = null;
|
||||
protected $tree;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
|
@ -219,10 +220,9 @@ class DecisionTree implements Classifier
|
|||
// Normalize & sort the importances
|
||||
$total = array_sum($this->featureImportances);
|
||||
if ($total > 0) {
|
||||
foreach ($this->featureImportances as &$importance) {
|
||||
array_walk($this->featureImportances, function (&$importance) use ($total): void {
|
||||
$importance /= $total;
|
||||
}
|
||||
|
||||
});
|
||||
arsort($this->featureImportances);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@ use ReflectionClass;
|
|||
|
||||
class AdaBoost implements Classifier
|
||||
{
|
||||
use Predictable, Trainable;
|
||||
use Predictable;
|
||||
use Trainable;
|
||||
|
||||
/**
|
||||
* Actual labels given in the targets array
|
||||
|
|
|
@ -13,7 +13,8 @@ use ReflectionClass;
|
|||
|
||||
class Bagging implements Classifier
|
||||
{
|
||||
use Trainable, Predictable;
|
||||
use Trainable;
|
||||
use Predictable;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
|
|
|
@ -16,9 +16,9 @@ class RandomForest extends Bagging
|
|||
protected $featureSubsetRatio = 'log';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var array|null
|
||||
*/
|
||||
protected $columnNames = null;
|
||||
protected $columnNames;
|
||||
|
||||
/**
|
||||
* Initializes RandomForest with the given number of trees. More trees
|
||||
|
@ -53,7 +53,7 @@ class RandomForest extends Bagging
|
|||
throw new InvalidArgumentException('When a float is given, feature subset ratio should be between 0.1 and 1.0');
|
||||
}
|
||||
|
||||
if (is_string($ratio) && $ratio != 'sqrt' && $ratio != 'log') {
|
||||
if (is_string($ratio) && $ratio !== 'sqrt' && $ratio !== 'log') {
|
||||
throw new InvalidArgumentException("When a string is given, feature subset ratio can only be 'sqrt' or 'log'");
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ class RandomForest extends Bagging
|
|||
*/
|
||||
public function setClassifer(string $classifier, array $classifierOptions = [])
|
||||
{
|
||||
if ($classifier != DecisionTree::class) {
|
||||
if ($classifier !== DecisionTree::class) {
|
||||
throw new InvalidArgumentException('RandomForest can only use DecisionTree as base classifier');
|
||||
}
|
||||
|
||||
|
@ -100,10 +100,9 @@ class RandomForest extends Bagging
|
|||
|
||||
// Normalize & sort the importance values
|
||||
$total = array_sum($sum);
|
||||
foreach ($sum as &$importance) {
|
||||
array_walk($sum, function (&$importance) use ($total): void {
|
||||
$importance /= $total;
|
||||
}
|
||||
|
||||
});
|
||||
arsort($sum);
|
||||
|
||||
return $sum;
|
||||
|
@ -131,7 +130,7 @@ class RandomForest extends Bagging
|
|||
{
|
||||
if (is_float($this->featureSubsetRatio)) {
|
||||
$featureCount = (int) ($this->featureSubsetRatio * $this->featureCount);
|
||||
} elseif ($this->featureSubsetRatio == 'sqrt') {
|
||||
} elseif ($this->featureSubsetRatio === 'sqrt') {
|
||||
$featureCount = (int) sqrt($this->featureCount) + 1;
|
||||
} else {
|
||||
$featureCount = (int) log($this->featureCount, 2) + 1;
|
||||
|
|
|
@ -11,7 +11,8 @@ use Phpml\Math\Distance\Euclidean;
|
|||
|
||||
class KNearestNeighbors implements Classifier
|
||||
{
|
||||
use Trainable, Predictable;
|
||||
use Trainable;
|
||||
use Predictable;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
|
@ -47,7 +48,7 @@ class KNearestNeighbors implements Classifier
|
|||
|
||||
$predictions = array_combine(array_values($this->targets), array_fill(0, count($this->targets), 0));
|
||||
|
||||
foreach ($distances as $index => $distance) {
|
||||
foreach (array_keys($distances) as $index) {
|
||||
++$predictions[$this->targets[$index]];
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@ use Phpml\Math\Comparison;
|
|||
|
||||
class DecisionStump extends WeightedClassifier
|
||||
{
|
||||
use Predictable, OneVsRest;
|
||||
use Predictable;
|
||||
use OneVsRest;
|
||||
|
||||
public const AUTO_SELECT = -1;
|
||||
|
||||
|
|
|
@ -87,10 +87,8 @@ class LogisticRegression extends Adaline
|
|||
);
|
||||
}
|
||||
|
||||
if ($penalty != '' && strtoupper($penalty) !== 'L2') {
|
||||
throw new InvalidArgumentException(
|
||||
"Logistic regression supports only 'L2' regularization"
|
||||
);
|
||||
if ($penalty !== '' && strtoupper($penalty) !== 'L2') {
|
||||
throw new InvalidArgumentException('Logistic regression supports only \'L2\' regularization');
|
||||
}
|
||||
|
||||
$this->learningRate = 0.001;
|
||||
|
@ -174,7 +172,7 @@ class LogisticRegression extends Adaline
|
|||
protected function getCostFunction(): Closure
|
||||
{
|
||||
$penalty = 0;
|
||||
if ($this->penalty == 'L2') {
|
||||
if ($this->penalty === 'L2') {
|
||||
$penalty = $this->lambda;
|
||||
}
|
||||
|
||||
|
@ -190,7 +188,7 @@ class LogisticRegression extends Adaline
|
|||
* The gradient of the cost function to be used with gradient descent:
|
||||
* ∇J(x) = -(y - h(x)) = (h(x) - y)
|
||||
*/
|
||||
$callback = function ($weights, $sample, $y) use ($penalty) {
|
||||
return function ($weights, $sample, $y) use ($penalty) {
|
||||
$this->weights = $weights;
|
||||
$hX = $this->output($sample);
|
||||
|
||||
|
@ -211,9 +209,6 @@ class LogisticRegression extends Adaline
|
|||
|
||||
return [$error, $gradient, $penalty];
|
||||
};
|
||||
|
||||
return $callback;
|
||||
|
||||
case 'sse':
|
||||
/*
|
||||
* Sum of squared errors or least squared errors cost function:
|
||||
|
@ -225,7 +220,7 @@ class LogisticRegression extends Adaline
|
|||
* The gradient of the cost function:
|
||||
* ∇J(x) = -(h(x) - y) . h(x) . (1 - h(x))
|
||||
*/
|
||||
$callback = function ($weights, $sample, $y) use ($penalty) {
|
||||
return function ($weights, $sample, $y) use ($penalty) {
|
||||
$this->weights = $weights;
|
||||
$hX = $this->output($sample);
|
||||
|
||||
|
@ -236,9 +231,6 @@ class LogisticRegression extends Adaline
|
|||
|
||||
return [$error, $gradient, $penalty];
|
||||
};
|
||||
|
||||
return $callback;
|
||||
|
||||
default:
|
||||
// Not reached
|
||||
throw new Exception(sprintf('Logistic regression has invalid cost function: %s.', $this->costFunction));
|
||||
|
|
|
@ -17,7 +17,8 @@ use Phpml\Preprocessing\Normalizer;
|
|||
|
||||
class Perceptron implements Classifier, IncrementalEstimator
|
||||
{
|
||||
use Predictable, OneVsRest;
|
||||
use Predictable;
|
||||
use OneVsRest;
|
||||
|
||||
/**
|
||||
* @var Optimizer|GD|StochasticGD|null
|
||||
|
|
|
@ -11,7 +11,8 @@ use Phpml\Math\Statistic\StandardDeviation;
|
|||
|
||||
class NaiveBayes implements Classifier
|
||||
{
|
||||
use Trainable, Predictable;
|
||||
use Trainable;
|
||||
use Predictable;
|
||||
|
||||
public const CONTINUOS = 1;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class ArrayDataset implements Dataset
|
|||
*/
|
||||
public function __construct(array $samples, array $targets)
|
||||
{
|
||||
if (count($samples) != count($targets)) {
|
||||
if (count($samples) !== count($targets)) {
|
||||
throw new InvalidArgumentException('Size of given arrays does not match');
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ class SvmDataset extends ArrayDataset
|
|||
private static function parseFeatureColumn(string $column): array
|
||||
{
|
||||
$feature = explode(':', $column, 2);
|
||||
if (count($feature) != 2) {
|
||||
if (count($feature) !== 2) {
|
||||
throw new DatasetException(sprintf('Invalid value "%s".', $column));
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ class PCA extends EigenTransformerBase
|
|||
}
|
||||
|
||||
// Normalize data
|
||||
foreach ($data as $i => $row) {
|
||||
foreach (array_keys($data) as $i) {
|
||||
for ($k = 0; $k < $n; ++$k) {
|
||||
$data[$i][$k] -= $this->means[$k];
|
||||
}
|
||||
|
|
|
@ -48,9 +48,9 @@ class TokenCountVectorizer implements Transformer
|
|||
|
||||
public function transform(array &$samples): void
|
||||
{
|
||||
foreach ($samples as &$sample) {
|
||||
array_walk($samples, function (string &$sample): void {
|
||||
$this->transformSample($sample);
|
||||
}
|
||||
});
|
||||
|
||||
$this->checkDocumentFrequency($samples);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class TokenCountVectorizer implements Transformer
|
|||
|
||||
private function buildVocabulary(array &$samples): void
|
||||
{
|
||||
foreach ($samples as $index => $sample) {
|
||||
foreach ($samples as $sample) {
|
||||
$tokens = $this->tokenizer->tokenize($sample);
|
||||
foreach ($tokens as $token) {
|
||||
$this->addTokenToVocabulary($token);
|
||||
|
|
|
@ -43,7 +43,7 @@ final class UnivariateLinearRegression implements ScoringFunction
|
|||
}
|
||||
|
||||
$correlations = [];
|
||||
foreach ($samples[0] as $index => $feature) {
|
||||
foreach (array_keys($samples[0]) as $index) {
|
||||
$featureColumn = array_column($samples, $index);
|
||||
$correlations[$index] =
|
||||
(Matrix::dot($targets, $featureColumn)[0] / (new Matrix($featureColumn, false))->transpose()->frobeniusNorm())
|
||||
|
@ -57,15 +57,15 @@ final class UnivariateLinearRegression implements ScoringFunction
|
|||
}, $correlations);
|
||||
}
|
||||
|
||||
private function centerTargets(&$targets): void
|
||||
private function centerTargets(array &$targets): void
|
||||
{
|
||||
$mean = Mean::arithmetic($targets);
|
||||
foreach ($targets as &$target) {
|
||||
array_walk($targets, function (&$target) use ($mean): void {
|
||||
$target -= $mean;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function centerSamples(&$samples): void
|
||||
private function centerSamples(array &$samples): void
|
||||
{
|
||||
$means = [];
|
||||
foreach ($samples[0] as $index => $feature) {
|
||||
|
|
|
@ -179,7 +179,7 @@ class EigenvalueDecomposition
|
|||
continue;
|
||||
}
|
||||
|
||||
$o = ($this->e[$i] > 0) ? $i + 1 : $i - 1;
|
||||
$o = $this->e[$i] > 0 ? $i + 1 : $i - 1;
|
||||
$D[$i][$o] = $this->e[$i];
|
||||
}
|
||||
|
||||
|
@ -222,7 +222,7 @@ class EigenvalueDecomposition
|
|||
}
|
||||
|
||||
$this->e[$i] = $scale * $g;
|
||||
$h = $h - $f * $g;
|
||||
$h -= $f * $g;
|
||||
$this->d[$i_] = $f - $g;
|
||||
|
||||
for ($j = 0; $j < $i; ++$j) {
|
||||
|
@ -395,7 +395,7 @@ class EigenvalueDecomposition
|
|||
} while (abs($this->e[$l]) > $eps * $tst1);
|
||||
}
|
||||
|
||||
$this->d[$l] = $this->d[$l] + $f;
|
||||
$this->d[$l] += $f;
|
||||
$this->e[$l] = 0.0;
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ class EigenvalueDecomposition
|
|||
// Scale column.
|
||||
$scale = 0.0;
|
||||
for ($i = $m; $i <= $high; ++$i) {
|
||||
$scale = $scale + abs($this->H[$i][$m - 1]);
|
||||
$scale += abs($this->H[$i][$m - 1]);
|
||||
}
|
||||
|
||||
if ($scale != 0.0) {
|
||||
|
@ -477,7 +477,7 @@ class EigenvalueDecomposition
|
|||
$f += $this->ort[$j] * $this->H[$i][$j];
|
||||
}
|
||||
|
||||
$f = $f / $h;
|
||||
$f /= $h;
|
||||
for ($j = $m; $j <= $high; ++$j) {
|
||||
$this->H[$i][$j] -= $f * $this->ort[$j];
|
||||
}
|
||||
|
@ -568,7 +568,7 @@ class EigenvalueDecomposition
|
|||
}
|
||||
|
||||
for ($j = max($i - 1, 0); $j < $nn; ++$j) {
|
||||
$norm = $norm + abs($this->H[$i][$j]);
|
||||
$norm += abs($this->H[$i][$j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,7 +593,7 @@ class EigenvalueDecomposition
|
|||
// Check for convergence
|
||||
// One root found
|
||||
if ($l == $n) {
|
||||
$this->H[$n][$n] = $this->H[$n][$n] + $exshift;
|
||||
$this->H[$n][$n] += $exshift;
|
||||
$this->d[$n] = $this->H[$n][$n];
|
||||
$this->e[$n] = 0.0;
|
||||
--$n;
|
||||
|
@ -604,8 +604,8 @@ class EigenvalueDecomposition
|
|||
$p = ($this->H[$n - 1][$n - 1] - $this->H[$n][$n]) / 2.0;
|
||||
$q = $p * $p + $w;
|
||||
$z = sqrt(abs($q));
|
||||
$this->H[$n][$n] = $this->H[$n][$n] + $exshift;
|
||||
$this->H[$n - 1][$n - 1] = $this->H[$n - 1][$n - 1] + $exshift;
|
||||
$this->H[$n][$n] += $exshift;
|
||||
$this->H[$n - 1][$n - 1] += $exshift;
|
||||
$x = $this->H[$n][$n];
|
||||
// Real pair
|
||||
if ($q >= 0) {
|
||||
|
@ -628,8 +628,8 @@ class EigenvalueDecomposition
|
|||
$p = $x / $s;
|
||||
$q = $z / $s;
|
||||
$r = sqrt($p * $p + $q * $q);
|
||||
$p = $p / $r;
|
||||
$q = $q / $r;
|
||||
$p /= $r;
|
||||
$q /= $r;
|
||||
// Row modification
|
||||
for ($j = $n - 1; $j < $nn; ++$j) {
|
||||
$z = $this->H[$n - 1][$j];
|
||||
|
@ -659,7 +659,7 @@ class EigenvalueDecomposition
|
|||
$this->e[$n] = -$z;
|
||||
}
|
||||
|
||||
$n = $n - 2;
|
||||
$n -= 2;
|
||||
$iter = 0;
|
||||
// No convergence yet
|
||||
} else {
|
||||
|
@ -687,7 +687,7 @@ class EigenvalueDecomposition
|
|||
// MATLAB's new ad hoc shift
|
||||
if ($iter == 30) {
|
||||
$s = ($y - $x) / 2.0;
|
||||
$s = $s * $s + $w;
|
||||
$s *= $s + $w;
|
||||
if ($s > 0) {
|
||||
$s = sqrt($s);
|
||||
if ($y < $x) {
|
||||
|
@ -705,7 +705,7 @@ class EigenvalueDecomposition
|
|||
}
|
||||
|
||||
// Could check iteration count here.
|
||||
$iter = $iter + 1;
|
||||
++$iter;
|
||||
// Look for two consecutive small sub-diagonal elements
|
||||
$m = $n - 2;
|
||||
while ($m >= $l) {
|
||||
|
@ -716,9 +716,9 @@ class EigenvalueDecomposition
|
|||
$q = $this->H[$m + 1][$m + 1] - $z - $r - $s;
|
||||
$r = $this->H[$m + 2][$m + 1];
|
||||
$s = abs($p) + abs($q) + abs($r);
|
||||
$p = $p / $s;
|
||||
$q = $q / $s;
|
||||
$r = $r / $s;
|
||||
$p /= $s;
|
||||
$q /= $s;
|
||||
$r /= $s;
|
||||
if ($m == $l) {
|
||||
break;
|
||||
}
|
||||
|
@ -747,9 +747,9 @@ class EigenvalueDecomposition
|
|||
$r = ($notlast ? $this->H[$k + 2][$k - 1] : 0.0);
|
||||
$x = abs($p) + abs($q) + abs($r);
|
||||
if ($x != 0.0) {
|
||||
$p = $p / $x;
|
||||
$q = $q / $x;
|
||||
$r = $r / $x;
|
||||
$p /= $x;
|
||||
$q /= $x;
|
||||
$r /= $x;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,46 +769,46 @@ class EigenvalueDecomposition
|
|||
$this->H[$k][$k - 1] = -$this->H[$k][$k - 1];
|
||||
}
|
||||
|
||||
$p = $p + $s;
|
||||
$p += $s;
|
||||
$x = $p / $s;
|
||||
$y = $q / $s;
|
||||
$z = $r / $s;
|
||||
$q = $q / $p;
|
||||
$r = $r / $p;
|
||||
$q /= $p;
|
||||
$r /= $p;
|
||||
// Row modification
|
||||
for ($j = $k; $j < $nn; ++$j) {
|
||||
$p = $this->H[$k][$j] + $q * $this->H[$k + 1][$j];
|
||||
if ($notlast) {
|
||||
$p = $p + $r * $this->H[$k + 2][$j];
|
||||
$this->H[$k + 2][$j] = $this->H[$k + 2][$j] - $p * $z;
|
||||
$p += $r * $this->H[$k + 2][$j];
|
||||
$this->H[$k + 2][$j] -= $p * $z;
|
||||
}
|
||||
|
||||
$this->H[$k][$j] = $this->H[$k][$j] - $p * $x;
|
||||
$this->H[$k + 1][$j] = $this->H[$k + 1][$j] - $p * $y;
|
||||
$this->H[$k][$j] -= $p * $x;
|
||||
$this->H[$k + 1][$j] -= $p * $y;
|
||||
}
|
||||
|
||||
// Column modification
|
||||
for ($i = 0; $i <= min($n, $k + 3); ++$i) {
|
||||
$p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k + 1];
|
||||
if ($notlast) {
|
||||
$p = $p + $z * $this->H[$i][$k + 2];
|
||||
$this->H[$i][$k + 2] = $this->H[$i][$k + 2] - $p * $r;
|
||||
$p += $z * $this->H[$i][$k + 2];
|
||||
$this->H[$i][$k + 2] -= $p * $r;
|
||||
}
|
||||
|
||||
$this->H[$i][$k] = $this->H[$i][$k] - $p;
|
||||
$this->H[$i][$k + 1] = $this->H[$i][$k + 1] - $p * $q;
|
||||
$this->H[$i][$k] -= $p;
|
||||
$this->H[$i][$k + 1] -= $p * $q;
|
||||
}
|
||||
|
||||
// Accumulate transformations
|
||||
for ($i = $low; $i <= $high; ++$i) {
|
||||
$p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k + 1];
|
||||
if ($notlast) {
|
||||
$p = $p + $z * $this->V[$i][$k + 2];
|
||||
$this->V[$i][$k + 2] = $this->V[$i][$k + 2] - $p * $r;
|
||||
$p += $z * $this->V[$i][$k + 2];
|
||||
$this->V[$i][$k + 2] -= $p * $r;
|
||||
}
|
||||
|
||||
$this->V[$i][$k] = $this->V[$i][$k] - $p;
|
||||
$this->V[$i][$k + 1] = $this->V[$i][$k + 1] - $p * $q;
|
||||
$this->V[$i][$k] -= $p;
|
||||
$this->V[$i][$k + 1] -= $p * $q;
|
||||
}
|
||||
} // ($s != 0)
|
||||
} // k loop
|
||||
|
@ -831,7 +831,7 @@ class EigenvalueDecomposition
|
|||
$w = $this->H[$i][$i] - $p;
|
||||
$r = 0.0;
|
||||
for ($j = $l; $j <= $n; ++$j) {
|
||||
$r = $r + $this->H[$i][$j] * $this->H[$j][$n];
|
||||
$r += $this->H[$i][$j] * $this->H[$j][$n];
|
||||
}
|
||||
|
||||
if ($this->e[$i] < 0.0) {
|
||||
|
@ -864,7 +864,7 @@ class EigenvalueDecomposition
|
|||
$t = abs($this->H[$i][$n]);
|
||||
if (($eps * $t) * $t > 1) {
|
||||
for ($j = $i; $j <= $n; ++$j) {
|
||||
$this->H[$j][$n] = $this->H[$j][$n] / $t;
|
||||
$this->H[$j][$n] /= $t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -890,8 +890,8 @@ class EigenvalueDecomposition
|
|||
$ra = 0.0;
|
||||
$sa = 0.0;
|
||||
for ($j = $l; $j <= $n; ++$j) {
|
||||
$ra = $ra + $this->H[$i][$j] * $this->H[$j][$n - 1];
|
||||
$sa = $sa + $this->H[$i][$j] * $this->H[$j][$n];
|
||||
$ra += $this->H[$i][$j] * $this->H[$j][$n - 1];
|
||||
$sa += $this->H[$i][$j] * $this->H[$j][$n];
|
||||
}
|
||||
|
||||
$w = $this->H[$i][$i] - $p;
|
||||
|
@ -932,8 +932,8 @@ class EigenvalueDecomposition
|
|||
$t = max(abs($this->H[$i][$n - 1]), abs($this->H[$i][$n]));
|
||||
if (($eps * $t) * $t > 1) {
|
||||
for ($j = $i; $j <= $n; ++$j) {
|
||||
$this->H[$j][$n - 1] = $this->H[$j][$n - 1] / $t;
|
||||
$this->H[$j][$n] = $this->H[$j][$n] / $t;
|
||||
$this->H[$j][$n - 1] /= $t;
|
||||
$this->H[$j][$n] /= $t;
|
||||
}
|
||||
}
|
||||
} // end else
|
||||
|
@ -955,7 +955,7 @@ class EigenvalueDecomposition
|
|||
for ($i = $low; $i <= $high; ++$i) {
|
||||
$z = 0.0;
|
||||
for ($k = $low; $k <= min($j, $high); ++$k) {
|
||||
$z = $z + $this->V[$i][$k] * $this->H[$k][$j];
|
||||
$z += $this->V[$i][$k] * $this->H[$k][$j];
|
||||
}
|
||||
|
||||
$this->V[$i][$j] = $z;
|
||||
|
|
|
@ -133,7 +133,7 @@ class LUDecomposition
|
|||
$k = $this->piv[$p];
|
||||
$this->piv[$p] = $this->piv[$j];
|
||||
$this->piv[$j] = $k;
|
||||
$this->pivsign = $this->pivsign * -1;
|
||||
$this->pivsign *= -1;
|
||||
}
|
||||
|
||||
// Compute multipliers.
|
||||
|
|
|
@ -261,7 +261,7 @@ class Matrix
|
|||
$squareSum = 0;
|
||||
for ($i = 0; $i < $this->rows; ++$i) {
|
||||
for ($j = 0; $j < $this->columns; ++$j) {
|
||||
$squareSum += ($this->matrix[$i][$j]) ** 2;
|
||||
$squareSum += $this->matrix[$i][$j] ** 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ final class ANOVA
|
|||
{
|
||||
foreach ($sums as &$row) {
|
||||
foreach ($row as &$sum) {
|
||||
$sum = $sum ** 2;
|
||||
$sum **= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class Normalizer implements Preprocessor
|
|||
return;
|
||||
}
|
||||
|
||||
if ($this->norm == self::NORM_STD) {
|
||||
if ($this->norm === self::NORM_STD) {
|
||||
$features = range(0, count($samples[0]) - 1);
|
||||
foreach ($features as $i) {
|
||||
$values = array_column($samples, $i);
|
||||
|
@ -93,9 +93,9 @@ class Normalizer implements Preprocessor
|
|||
$count = count($sample);
|
||||
$sample = array_fill(0, $count, 1.0 / $count);
|
||||
} else {
|
||||
foreach ($sample as &$feature) {
|
||||
array_walk($sample, function (&$feature) use ($norm1): void {
|
||||
$feature /= $norm1;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,15 +111,15 @@ class Normalizer implements Preprocessor
|
|||
if ($norm2 == 0) {
|
||||
$sample = array_fill(0, count($sample), 1);
|
||||
} else {
|
||||
foreach ($sample as &$feature) {
|
||||
array_walk($sample, function (&$feature) use ($norm2): void {
|
||||
$feature /= $norm2;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private function normalizeSTD(array &$sample): void
|
||||
{
|
||||
foreach ($sample as $i => $val) {
|
||||
foreach (array_keys($sample) as $i) {
|
||||
if ($this->std[$i] != 0) {
|
||||
$sample[$i] = ($sample[$i] - $this->mean[$i]) / $this->std[$i];
|
||||
} else {
|
||||
|
|
|
@ -66,14 +66,13 @@ class KNearestNeighborsTest extends TestCase
|
|||
$trainLabels = ['a', 'a', 'a', 'b', 'b', 'b'];
|
||||
|
||||
$testSamples = [[3, 2], [5, 1], [4, 3], [4, -5], [2, 3], [1, 2], [1, 5], [3, 10]];
|
||||
$testLabels = ['b', 'b', 'b', 'b', 'a', 'a', 'a', 'a'];
|
||||
|
||||
// Using non-default constructor parameters to check that their values are restored.
|
||||
$classifier = new KNearestNeighbors(3, new Chebyshev());
|
||||
$classifier->train($trainSamples, $trainLabels);
|
||||
$predicted = $classifier->predict($testSamples);
|
||||
|
||||
$filename = 'knearest-neighbors-test-'.random_int(100, 999).'-'.uniqid();
|
||||
$filename = 'knearest-neighbors-test-'.random_int(100, 999).'-'.uniqid('', false);
|
||||
$filepath = tempnam(sys_get_temp_dir(), $filename);
|
||||
$modelManager = new ModelManager();
|
||||
$modelManager->saveToFile($classifier, $filepath);
|
||||
|
|
|
@ -14,7 +14,9 @@ class AdalineTest extends TestCase
|
|||
public function testAdalineThrowWhenInvalidTrainingType(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$classifier = new Adaline(
|
||||
$this->expectExceptionMessage('Adaline can only be trained with batch and online/stochastic gradient descent algorithm');
|
||||
|
||||
new Adaline(
|
||||
0.001,
|
||||
1000,
|
||||
true,
|
||||
|
@ -86,7 +88,7 @@ class AdalineTest extends TestCase
|
|||
$testSamples = [[0, 1], [1, 1], [0.2, 0.1]];
|
||||
$predicted = $classifier->predict($testSamples);
|
||||
|
||||
$filename = 'adaline-test-'.random_int(100, 999).'-'.uniqid();
|
||||
$filename = 'adaline-test-'.random_int(100, 999).'-'.uniqid('', false);
|
||||
$filepath = tempnam(sys_get_temp_dir(), $filename);
|
||||
$modelManager = new ModelManager();
|
||||
$modelManager->saveToFile($classifier, $filepath);
|
||||
|
|
|
@ -15,8 +15,11 @@ class LogisticRegressionTest extends TestCase
|
|||
public function testConstructorThrowWhenInvalidTrainingType(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Logistic regression can only be trained with '.
|
||||
'batch (gradient descent), online (stochastic gradient descent) '.
|
||||
'or conjugate batch (conjugate gradients) algorithms');
|
||||
|
||||
$classifier = new LogisticRegression(
|
||||
new LogisticRegression(
|
||||
500,
|
||||
true,
|
||||
-1,
|
||||
|
@ -28,8 +31,10 @@ class LogisticRegressionTest extends TestCase
|
|||
public function testConstructorThrowWhenInvalidCost(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage("Logistic regression cost function can be one of the following: \n".
|
||||
"'log' for log-likelihood and 'sse' for sum of squared errors");
|
||||
|
||||
$classifier = new LogisticRegression(
|
||||
new LogisticRegression(
|
||||
500,
|
||||
true,
|
||||
LogisticRegression::CONJUGATE_GRAD_TRAINING,
|
||||
|
@ -41,8 +46,9 @@ class LogisticRegressionTest extends TestCase
|
|||
public function testConstructorThrowWhenInvalidPenalty(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Logistic regression supports only \'L2\' regularization');
|
||||
|
||||
$classifier = new LogisticRegression(
|
||||
new LogisticRegression(
|
||||
500,
|
||||
true,
|
||||
LogisticRegression::CONJUGATE_GRAD_TRAINING,
|
||||
|
|
|
@ -14,13 +14,15 @@ class PerceptronTest extends TestCase
|
|||
public function testPerceptronThrowWhenLearningRateOutOfRange(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$classifier = new Perceptron(0, 5000);
|
||||
$this->expectExceptionMessage('Learning rate should be a float value between 0.0(exclusive) and 1.0(inclusive)');
|
||||
new Perceptron(0, 5000);
|
||||
}
|
||||
|
||||
public function testPerceptronThrowWhenMaxIterationsOutOfRange(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$classifier = new Perceptron(0.001, 0);
|
||||
$this->expectExceptionMessage('Maximum number of iterations must be an integer greater than 0');
|
||||
new Perceptron(0.001, 0);
|
||||
}
|
||||
|
||||
public function testPredictSingleSample(): void
|
||||
|
@ -90,7 +92,7 @@ class PerceptronTest extends TestCase
|
|||
$testSamples = [[0, 1], [1, 1], [0.2, 0.1]];
|
||||
$predicted = $classifier->predict($testSamples);
|
||||
|
||||
$filename = 'perceptron-test-'.random_int(100, 999).'-'.uniqid();
|
||||
$filename = 'perceptron-test-'.random_int(100, 999).'-'.uniqid('', false);
|
||||
$filepath = tempnam(sys_get_temp_dir(), $filename);
|
||||
$modelManager = new ModelManager();
|
||||
$modelManager->saveToFile($classifier, $filepath);
|
||||
|
|
|
@ -53,13 +53,12 @@ class NaiveBayesTest extends TestCase
|
|||
$trainLabels = ['a', 'b', 'c'];
|
||||
|
||||
$testSamples = [[3, 1, 1], [5, 1, 1], [4, 3, 8]];
|
||||
$testLabels = ['a', 'a', 'c'];
|
||||
|
||||
$classifier = new NaiveBayes();
|
||||
$classifier->train($trainSamples, $trainLabels);
|
||||
$predicted = $classifier->predict($testSamples);
|
||||
|
||||
$filename = 'naive-bayes-test-'.random_int(100, 999).'-'.uniqid();
|
||||
$filename = 'naive-bayes-test-'.random_int(100, 999).'-'.uniqid('', false);
|
||||
$filepath = tempnam(sys_get_temp_dir(), $filename);
|
||||
$modelManager = new ModelManager();
|
||||
$modelManager->saveToFile($classifier, $filepath);
|
||||
|
@ -112,13 +111,12 @@ class NaiveBayesTest extends TestCase
|
|||
$trainLabels = ['1996', '1997', '1998'];
|
||||
|
||||
$testSamples = [[3, 1, 1], [5, 1, 1], [4, 3, 8]];
|
||||
$testLabels = ['1996', '1996', '1998'];
|
||||
|
||||
$classifier = new NaiveBayes();
|
||||
$classifier->train($trainSamples, $trainLabels);
|
||||
$predicted = $classifier->predict($testSamples);
|
||||
|
||||
$filename = 'naive-bayes-test-'.random_int(100, 999).'-'.uniqid();
|
||||
$filename = 'naive-bayes-test-'.random_int(100, 999).'-'.uniqid('', false);
|
||||
$filepath = tempnam(sys_get_temp_dir(), $filename);
|
||||
$modelManager = new ModelManager();
|
||||
$modelManager->saveToFile($classifier, $filepath);
|
||||
|
|
|
@ -136,77 +136,77 @@ class SvmDatasetTest extends TestCase
|
|||
public function testSvmDatasetMissingFile(): void
|
||||
{
|
||||
$this->expectException(FileException::class);
|
||||
$this->expectExceptionMessage('File "err_file_not_exists.svm" missing.');
|
||||
|
||||
$filePath = self::getFilePath('err_file_not_exists.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_file_not_exists.svm'));
|
||||
}
|
||||
|
||||
public function testSvmDatasetEmptyLine(): void
|
||||
{
|
||||
$this->expectException(DatasetException::class);
|
||||
$this->expectExceptionMessage('Invalid target "".');
|
||||
|
||||
$filePath = self::getFilePath('err_empty_line.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_empty_line.svm'));
|
||||
}
|
||||
|
||||
public function testSvmDatasetNoLabels(): void
|
||||
{
|
||||
$this->expectException(DatasetException::class);
|
||||
$this->expectExceptionMessage('Invalid target "1:2.3".');
|
||||
|
||||
$filePath = self::getFilePath('err_no_labels.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_no_labels.svm'));
|
||||
}
|
||||
|
||||
public function testSvmDatasetStringLabels(): void
|
||||
{
|
||||
$this->expectException(DatasetException::class);
|
||||
$this->expectExceptionMessage('Invalid target "A".');
|
||||
|
||||
$filePath = self::getFilePath('err_string_labels.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_string_labels.svm'));
|
||||
}
|
||||
|
||||
public function testSvmDatasetInvalidSpaces(): void
|
||||
{
|
||||
$this->expectException(DatasetException::class);
|
||||
$this->expectExceptionMessage('Invalid target "".');
|
||||
|
||||
$filePath = self::getFilePath('err_invalid_spaces.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_invalid_spaces.svm'));
|
||||
}
|
||||
|
||||
public function testSvmDatasetStringIndex(): void
|
||||
{
|
||||
$this->expectException(DatasetException::class);
|
||||
$this->expectExceptionMessage('Invalid index "x".');
|
||||
|
||||
$filePath = self::getFilePath('err_string_index.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_string_index.svm'));
|
||||
}
|
||||
|
||||
public function testSvmDatasetIndexZero(): void
|
||||
{
|
||||
$this->expectException(DatasetException::class);
|
||||
$this->expectExceptionMessage('Invalid index "0".');
|
||||
|
||||
$filePath = self::getFilePath('err_index_zero.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_index_zero.svm'));
|
||||
}
|
||||
|
||||
public function testSvmDatasetInvalidValue(): void
|
||||
{
|
||||
$this->expectException(DatasetException::class);
|
||||
$this->expectExceptionMessage('Invalid value "xyz".');
|
||||
|
||||
$filePath = self::getFilePath('err_invalid_value.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_invalid_value.svm'));
|
||||
}
|
||||
|
||||
public function testSvmDatasetInvalidFeature(): void
|
||||
{
|
||||
$this->expectException(DatasetException::class);
|
||||
$this->expectExceptionMessage('Invalid value "12345".');
|
||||
|
||||
$filePath = self::getFilePath('err_invalid_feature.svm');
|
||||
$dataset = new SvmDataset($filePath);
|
||||
new SvmDataset(self::getFilePath('err_invalid_feature.svm'));
|
||||
}
|
||||
|
||||
private static function getFilePath(string $baseName): string
|
||||
{
|
||||
return dirname(__FILE__).'/Resources/svm/'.$baseName;
|
||||
return __DIR__.'/Resources/svm/'.$baseName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,16 +54,18 @@ class KernelPCATest extends TestCase
|
|||
public function testKernelPCAThrowWhenKernelInvalid(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$kpca = new KernelPCA(0, null, 1, 15);
|
||||
$this->expectExceptionMessage('KernelPCA can be initialized with the following kernels only: Linear, RBF, Sigmoid and Laplacian');
|
||||
new KernelPCA(0, null, 1, 15.);
|
||||
}
|
||||
|
||||
public function testTransformThrowWhenNotFitted(): void
|
||||
{
|
||||
$samples = [1, 0];
|
||||
|
||||
$kpca = new KernelPCA(KernelPCA::KERNEL_RBF, null, 1, 15);
|
||||
$kpca = new KernelPCA(KernelPCA::KERNEL_RBF, null, 1, 15.);
|
||||
|
||||
$this->expectException(InvalidOperationException::class);
|
||||
$this->expectExceptionMessage('KernelPCA has not been fitted with respect to original dataset, please run KernelPCA::fit() first');
|
||||
$kpca->transform($samples);
|
||||
}
|
||||
|
||||
|
@ -74,10 +76,11 @@ class KernelPCATest extends TestCase
|
|||
[1, 1],
|
||||
];
|
||||
|
||||
$kpca = new KernelPCA(KernelPCA::KERNEL_RBF, null, 1, 15);
|
||||
$kpca = new KernelPCA(KernelPCA::KERNEL_RBF, null, 1, 15.);
|
||||
$kpca->fit($samples);
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('KernelPCA::transform() accepts only one-dimensional arrays');
|
||||
$kpca->transform($samples);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,25 +68,29 @@ class LDATest extends TestCase
|
|||
public function testLDAThrowWhenTotalVarianceOutOfRange(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$pca = new LDA(0, null);
|
||||
$this->expectExceptionMessage('Total variance can be a value between 0.1 and 0.99');
|
||||
new LDA(0., null);
|
||||
}
|
||||
|
||||
public function testLDAThrowWhenNumFeaturesOutOfRange(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$pca = new LDA(null, 0);
|
||||
$this->expectExceptionMessage('Number of features to be preserved should be greater than 0');
|
||||
new LDA(null, 0);
|
||||
}
|
||||
|
||||
public function testLDAThrowWhenParameterNotSpecified(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$pca = new LDA();
|
||||
$this->expectExceptionMessage('Either totalVariance or numFeatures should be specified in order to run the algorithm');
|
||||
new LDA();
|
||||
}
|
||||
|
||||
public function testLDAThrowWhenBothParameterSpecified(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$pca = new LDA(0.9, 1);
|
||||
$this->expectExceptionMessage('Either totalVariance or numFeatures should be specified in order to run the algorithm');
|
||||
new LDA(0.9, 1);
|
||||
}
|
||||
|
||||
public function testTransformThrowWhenNotFitted(): void
|
||||
|
@ -99,6 +103,7 @@ class LDATest extends TestCase
|
|||
$pca = new LDA(0.9);
|
||||
|
||||
$this->expectException(InvalidOperationException::class);
|
||||
$this->expectExceptionMessage('LDA has not been fitted with respect to original dataset, please run LDA::fit() first');
|
||||
$pca->transform($samples);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,25 +60,29 @@ class PCATest extends TestCase
|
|||
public function testPCAThrowWhenTotalVarianceOutOfRange(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$pca = new PCA(0, null);
|
||||
$this->expectExceptionMessage('Total variance can be a value between 0.1 and 0.99');
|
||||
new PCA(0., null);
|
||||
}
|
||||
|
||||
public function testPCAThrowWhenNumFeaturesOutOfRange(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$pca = new PCA(null, 0);
|
||||
$this->expectExceptionMessage('Number of features to be preserved should be greater than 0');
|
||||
new PCA(null, 0);
|
||||
}
|
||||
|
||||
public function testPCAThrowWhenParameterNotSpecified(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$pca = new PCA();
|
||||
$this->expectExceptionMessage('Either totalVariance or numFeatures should be specified in order to run the algorithm');
|
||||
new PCA();
|
||||
}
|
||||
|
||||
public function testPCAThrowWhenBothParameterSpecified(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$pca = new PCA(0.9, 1);
|
||||
$this->expectExceptionMessage('Either totalVariance or numFeatures should be specified in order to run the algorithm');
|
||||
new PCA(0.9, 1);
|
||||
}
|
||||
|
||||
public function testTransformThrowWhenNotFitted(): void
|
||||
|
@ -91,6 +95,7 @@ class PCATest extends TestCase
|
|||
$pca = new PCA(0.9);
|
||||
|
||||
$this->expectException(InvalidOperationException::class);
|
||||
$this->expectExceptionMessage('PCA has not been fitted with respect to original dataset, please run PCA::fit() first');
|
||||
$pca->transform($samples);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ class ClassificationReportTest extends TestCase
|
|||
$predicted = ['cat', 'cat', 'bird', 'bird', 'ant'];
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$report = new ClassificationReport($labels, $predicted, 0);
|
||||
new ClassificationReport($labels, $predicted, 0);
|
||||
}
|
||||
|
||||
public function testClassificationReportMicroAverage(): void
|
||||
|
|
|
@ -197,7 +197,7 @@ SV
|
|||
$svm = new SupportVectorMachine(Type::C_SVC, Kernel::LINEAR, 100.0);
|
||||
$svm->train($samples, $labels);
|
||||
|
||||
$predictions = $svm->predictProbability([
|
||||
$svm->predictProbability([
|
||||
[3, 2],
|
||||
[2, 3],
|
||||
[4, -5],
|
||||
|
|
Loading…
Reference in New Issue