diff --git a/src/Classification/Ensemble/AdaBoost.php b/src/Classification/Ensemble/AdaBoost.php
index b314c81..c7b5e75 100644
--- a/src/Classification/Ensemble/AdaBoost.php
+++ b/src/Classification/Ensemble/AdaBoost.php
@@ -4,10 +4,10 @@ declare(strict_types=1);
namespace Phpml\Classification\Ensemble;
-use Exception;
use Phpml\Classification\Classifier;
use Phpml\Classification\Linear\DecisionStump;
use Phpml\Classification\WeightedClassifier;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\Helper\Predictable;
use Phpml\Helper\Trainable;
use Phpml\Math\Statistic\Mean;
@@ -93,14 +93,14 @@ class AdaBoost implements Classifier
}
/**
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
public function train(array $samples, array $targets): void
{
// Initialize usual variables
$this->labels = array_keys(array_count_values($targets));
if (count($this->labels) != 2) {
- throw new Exception('AdaBoost is a binary classifier and can classify between two classes only');
+ throw new InvalidArgumentException('AdaBoost is a binary classifier and can classify between two classes only');
}
// Set all target values to either -1 or 1
diff --git a/src/Classification/Ensemble/Bagging.php b/src/Classification/Ensemble/Bagging.php
index a1d51c2..02e958b 100644
--- a/src/Classification/Ensemble/Bagging.php
+++ b/src/Classification/Ensemble/Bagging.php
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace Phpml\Classification\Ensemble;
-use Exception;
use Phpml\Classification\Classifier;
use Phpml\Classification\DecisionTree;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\Helper\Predictable;
use Phpml\Helper\Trainable;
use ReflectionClass;
@@ -77,12 +77,12 @@ class Bagging implements Classifier
*
* @return $this
*
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
public function setSubsetRatio(float $ratio)
{
if ($ratio < 0.1 || $ratio > 1.0) {
- throw new Exception('Subset ratio should be between 0.1 and 1.0');
+ throw new InvalidArgumentException('Subset ratio should be between 0.1 and 1.0');
}
$this->subsetRatio = $ratio;
diff --git a/src/Classification/Linear/Adaline.php b/src/Classification/Linear/Adaline.php
index 3b6309d..a133732 100644
--- a/src/Classification/Linear/Adaline.php
+++ b/src/Classification/Linear/Adaline.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Phpml\Classification\Linear;
-use Exception;
+use Phpml\Exception\InvalidArgumentException;
class Adaline extends Perceptron
{
@@ -34,7 +34,7 @@ class Adaline extends Perceptron
* If normalizeInputs is set to true, then every input given to the algorithm will be standardized
* by use of standard deviation and mean calculation
*
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
public function __construct(
float $learningRate = 0.001,
@@ -43,7 +43,7 @@ class Adaline extends Perceptron
int $trainingType = self::BATCH_TRAINING
) {
if (!in_array($trainingType, [self::BATCH_TRAINING, self::ONLINE_TRAINING], true)) {
- throw new Exception('Adaline can only be trained with batch and online/stochastic gradient descent algorithm');
+ throw new InvalidArgumentException('Adaline can only be trained with batch and online/stochastic gradient descent algorithm');
}
$this->trainingType = $trainingType;
diff --git a/src/Classification/Linear/DecisionStump.php b/src/Classification/Linear/DecisionStump.php
index 1903712..ef6a458 100644
--- a/src/Classification/Linear/DecisionStump.php
+++ b/src/Classification/Linear/DecisionStump.php
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace Phpml\Classification\Linear;
-use Exception;
use Phpml\Classification\DecisionTree;
use Phpml\Classification\WeightedClassifier;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\Helper\OneVsRest;
use Phpml\Helper\Predictable;
use Phpml\Math\Comparison;
@@ -104,7 +104,7 @@ class DecisionStump extends WeightedClassifier
}
/**
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
protected function trainBinary(array $samples, array $targets, array $labels): void
{
@@ -121,7 +121,7 @@ class DecisionStump extends WeightedClassifier
if (!empty($this->weights)) {
$numWeights = count($this->weights);
if ($numWeights != count($samples)) {
- throw new Exception('Number of sample weights does not match with number of samples');
+ throw new InvalidArgumentException('Number of sample weights does not match with number of samples');
}
} else {
$this->weights = array_fill(0, count($samples), 1);
diff --git a/src/Classification/Linear/LogisticRegression.php b/src/Classification/Linear/LogisticRegression.php
index 13f4b8a..0414d59 100644
--- a/src/Classification/Linear/LogisticRegression.php
+++ b/src/Classification/Linear/LogisticRegression.php
@@ -6,6 +6,7 @@ namespace Phpml\Classification\Linear;
use Closure;
use Exception;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\Helper\Optimizer\ConjugateGradient;
class LogisticRegression extends Adaline
@@ -61,7 +62,7 @@ class LogisticRegression extends Adaline
*
* Penalty (Regularization term) can be 'L2' or empty string to cancel penalty term
*
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
public function __construct(
int $maxIterations = 500,
@@ -72,18 +73,24 @@ class LogisticRegression extends Adaline
) {
$trainingTypes = range(self::BATCH_TRAINING, self::CONJUGATE_GRAD_TRAINING);
if (!in_array($trainingType, $trainingTypes, true)) {
- throw new Exception('Logistic regression can only be trained with '.
+ throw new InvalidArgumentException(
+ 'Logistic regression can only be trained with '.
'batch (gradient descent), online (stochastic gradient descent) '.
- 'or conjugate batch (conjugate gradients) algorithms');
+ 'or conjugate batch (conjugate gradients) algorithms'
+ );
}
if (!in_array($cost, ['log', 'sse'], true)) {
- throw new Exception("Logistic regression cost function can be one of the following: \n".
- "'log' for log-likelihood and 'sse' for sum of squared errors");
+ throw new InvalidArgumentException(
+ "Logistic regression cost function can be one of the following: \n".
+ "'log' for log-likelihood and 'sse' for sum of squared errors"
+ );
}
if ($penalty != '' && strtoupper($penalty) !== 'L2') {
- throw new Exception("Logistic regression supports only 'L2' regularization");
+ throw new InvalidArgumentException(
+ "Logistic regression supports only 'L2' regularization"
+ );
}
$this->learningRate = 0.001;
@@ -140,7 +147,8 @@ class LogisticRegression extends Adaline
return;
default:
- throw new Exception('Logistic regression has invalid training type: %s.', $this->trainingType);
+ // Not reached
+ throw new Exception(sprintf('Logistic regression has invalid training type: %d.', $this->trainingType));
}
}
@@ -232,6 +240,7 @@ class LogisticRegression extends Adaline
return $callback;
default:
+ // Not reached
throw new Exception(sprintf('Logistic regression has invalid cost function: %s.', $this->costFunction));
}
}
diff --git a/src/Classification/Linear/Perceptron.php b/src/Classification/Linear/Perceptron.php
index 5fffc01..038b4c8 100644
--- a/src/Classification/Linear/Perceptron.php
+++ b/src/Classification/Linear/Perceptron.php
@@ -5,8 +5,8 @@ declare(strict_types=1);
namespace Phpml\Classification\Linear;
use Closure;
-use Exception;
use Phpml\Classification\Classifier;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\Helper\OneVsRest;
use Phpml\Helper\Optimizer\GD;
use Phpml\Helper\Optimizer\StochasticGD;
@@ -70,16 +70,16 @@ class Perceptron implements Classifier, IncrementalEstimator
* @param float $learningRate Value between 0.0(exclusive) and 1.0(inclusive)
* @param int $maxIterations Must be at least 1
*
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
public function __construct(float $learningRate = 0.001, int $maxIterations = 1000, bool $normalizeInputs = true)
{
if ($learningRate <= 0.0 || $learningRate > 1.0) {
- throw new Exception('Learning rate should be a float value between 0.0(exclusive) and 1.0(inclusive)');
+ throw new InvalidArgumentException('Learning rate should be a float value between 0.0(exclusive) and 1.0(inclusive)');
}
if ($maxIterations <= 0) {
- throw new Exception('Maximum number of iterations must be an integer greater than 0');
+ throw new InvalidArgumentException('Maximum number of iterations must be an integer greater than 0');
}
if ($normalizeInputs) {
diff --git a/src/DimensionReduction/KernelPCA.php b/src/DimensionReduction/KernelPCA.php
index b962b3d..29deb4c 100644
--- a/src/DimensionReduction/KernelPCA.php
+++ b/src/DimensionReduction/KernelPCA.php
@@ -6,6 +6,8 @@ namespace Phpml\DimensionReduction;
use Closure;
use Exception;
+use Phpml\Exception\InvalidArgumentException;
+use Phpml\Exception\InvalidOperationException;
use Phpml\Math\Distance\Euclidean;
use Phpml\Math\Distance\Manhattan;
use Phpml\Math\Matrix;
@@ -53,13 +55,13 @@ class KernelPCA extends PCA
* @param int $numFeatures Number of columns to be returned
* @param float $gamma Gamma parameter is used with RBF and Sigmoid kernels
*
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
public function __construct(int $kernel = self::KERNEL_RBF, ?float $totalVariance = null, ?int $numFeatures = null, ?float $gamma = null)
{
$availableKernels = [self::KERNEL_RBF, self::KERNEL_SIGMOID, self::KERNEL_LAPLACIAN, self::KERNEL_LINEAR];
if (!in_array($kernel, $availableKernels, true)) {
- throw new Exception('KernelPCA can be initialized with the following kernels only: Linear, RBF, Sigmoid and Laplacian');
+ throw new InvalidArgumentException('KernelPCA can be initialized with the following kernels only: Linear, RBF, Sigmoid and Laplacian');
}
parent::__construct($totalVariance, $numFeatures);
@@ -97,16 +99,17 @@ class KernelPCA extends PCA
* Transforms the given sample to a lower dimensional vector by using
* the variables obtained during the last run of fit
.
*
- * @throws \Exception
+ * @throws InvalidArgumentException
+ * @throws InvalidOperationException
*/
public function transform(array $sample): array
{
if (!$this->fit) {
- throw new Exception('KernelPCA has not been fitted with respect to original dataset, please run KernelPCA::fit() first');
+ throw new InvalidOperationException('KernelPCA has not been fitted with respect to original dataset, please run KernelPCA::fit() first');
}
if (is_array($sample[0])) {
- throw new Exception('KernelPCA::transform() accepts only one-dimensional arrays');
+ throw new InvalidArgumentException('KernelPCA::transform() accepts only one-dimensional arrays');
}
$pairs = $this->getDistancePairs($sample);
@@ -199,6 +202,7 @@ class KernelPCA extends PCA
};
default:
+ // Not reached
throw new Exception(sprintf('KernelPCA initialized with invalid kernel: %d', $this->kernel));
}
}
diff --git a/src/DimensionReduction/LDA.php b/src/DimensionReduction/LDA.php
index d188205..68ab0cd 100644
--- a/src/DimensionReduction/LDA.php
+++ b/src/DimensionReduction/LDA.php
@@ -4,7 +4,8 @@ declare(strict_types=1);
namespace Phpml\DimensionReduction;
-use Exception;
+use Phpml\Exception\InvalidArgumentException;
+use Phpml\Exception\InvalidOperationException;
use Phpml\Math\Matrix;
class LDA extends EigenTransformerBase
@@ -46,20 +47,20 @@ class LDA extends EigenTransformerBase
* @param float|null $totalVariance Total explained variance to be preserved
* @param int|null $numFeatures Number of features to be preserved
*
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
public function __construct(?float $totalVariance = null, ?int $numFeatures = null)
{
if ($totalVariance !== null && ($totalVariance < 0.1 || $totalVariance > 0.99)) {
- throw new Exception('Total variance can be a value between 0.1 and 0.99');
+ throw new InvalidArgumentException('Total variance can be a value between 0.1 and 0.99');
}
if ($numFeatures !== null && $numFeatures <= 0) {
- throw new Exception('Number of features to be preserved should be greater than 0');
+ throw new InvalidArgumentException('Number of features to be preserved should be greater than 0');
}
- if ($totalVariance !== null && $numFeatures !== null) {
- throw new Exception('Either totalVariance or numFeatures should be specified in order to run the algorithm');
+ if (($totalVariance !== null) === ($numFeatures !== null)) {
+ throw new InvalidArgumentException('Either totalVariance or numFeatures should be specified in order to run the algorithm');
}
if ($numFeatures !== null) {
@@ -94,12 +95,12 @@ class LDA extends EigenTransformerBase
* Transforms the given sample to a lower dimensional vector by using
* the eigenVectors obtained in the last run of fit
.
*
- * @throws \Exception
+ * @throws InvalidOperationException
*/
public function transform(array $sample): array
{
if (!$this->fit) {
- throw new Exception('LDA has not been fitted with respect to original dataset, please run LDA::fit() first');
+ throw new InvalidOperationException('LDA has not been fitted with respect to original dataset, please run LDA::fit() first');
}
if (!is_array($sample[0])) {
diff --git a/src/DimensionReduction/PCA.php b/src/DimensionReduction/PCA.php
index 18879bb..a3d8a4d 100644
--- a/src/DimensionReduction/PCA.php
+++ b/src/DimensionReduction/PCA.php
@@ -4,7 +4,8 @@ declare(strict_types=1);
namespace Phpml\DimensionReduction;
-use Exception;
+use Phpml\Exception\InvalidArgumentException;
+use Phpml\Exception\InvalidOperationException;
use Phpml\Math\Statistic\Covariance;
use Phpml\Math\Statistic\Mean;
@@ -31,20 +32,20 @@ class PCA extends EigenTransformerBase
* @param float $totalVariance Total explained variance to be preserved
* @param int $numFeatures Number of features to be preserved
*
- * @throws \Exception
+ * @throws InvalidArgumentException
*/
public function __construct(?float $totalVariance = null, ?int $numFeatures = null)
{
if ($totalVariance !== null && ($totalVariance < 0.1 || $totalVariance > 0.99)) {
- throw new Exception('Total variance can be a value between 0.1 and 0.99');
+ throw new InvalidArgumentException('Total variance can be a value between 0.1 and 0.99');
}
if ($numFeatures !== null && $numFeatures <= 0) {
- throw new Exception('Number of features to be preserved should be greater than 0');
+ throw new InvalidArgumentException('Number of features to be preserved should be greater than 0');
}
- if ($totalVariance !== null && $numFeatures !== null) {
- throw new Exception('Either totalVariance or numFeatures should be specified in order to run the algorithm');
+ if (($totalVariance !== null) === ($numFeatures !== null)) {
+ throw new InvalidArgumentException('Either totalVariance or numFeatures should be specified in order to run the algorithm');
}
if ($numFeatures !== null) {
@@ -81,12 +82,12 @@ class PCA extends EigenTransformerBase
* Transforms the given sample to a lower dimensional vector by using
* the eigenVectors obtained in the last run of fit
.
*
- * @throws \Exception
+ * @throws InvalidOperationException
*/
public function transform(array $sample): array
{
if (!$this->fit) {
- throw new Exception('PCA has not been fitted with respect to original dataset, please run PCA::fit() first');
+ throw new InvalidOperationException('PCA has not been fitted with respect to original dataset, please run PCA::fit() first');
}
if (!is_array($sample[0])) {
diff --git a/tests/Classification/Ensemble/AdaBoostTest.php b/tests/Classification/Ensemble/AdaBoostTest.php
index 7677c31..095cde0 100644
--- a/tests/Classification/Ensemble/AdaBoostTest.php
+++ b/tests/Classification/Ensemble/AdaBoostTest.php
@@ -5,12 +5,32 @@ declare(strict_types=1);
namespace Phpml\Tests\Classification\Ensemble;
use Phpml\Classification\Ensemble\AdaBoost;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\ModelManager;
use PHPUnit\Framework\TestCase;
class AdaBoostTest extends TestCase
{
- public function testPredictSingleSample()
+ public function testTrainThrowWhenMultiClassTargetGiven(): void
+ {
+ $samples = [
+ [0, 0],
+ [0.5, 0.5],
+ [1, 1],
+ ];
+ $targets = [
+ 0,
+ 1,
+ 2,
+ ];
+
+ $classifier = new AdaBoost();
+
+ $this->expectException(InvalidArgumentException::class);
+ $classifier->train($samples, $targets);
+ }
+
+ public function testPredictSingleSample(): void
{
// AND problem
$samples = [[0.1, 0.3], [1, 0], [0, 1], [1, 1], [0.9, 0.8], [1.1, 1.1]];
@@ -38,8 +58,6 @@ class AdaBoostTest extends TestCase
$this->assertEquals(0, $classifier->predict([0.1, 0.1]));
$this->assertEquals(1, $classifier->predict([0, 0.999]));
$this->assertEquals(0, $classifier->predict([1.1, 0.8]));
-
- return $classifier;
}
public function testSaveAndRestore(): void
diff --git a/tests/Classification/Ensemble/BaggingTest.php b/tests/Classification/Ensemble/BaggingTest.php
index 69c4d01..5b2e47b 100644
--- a/tests/Classification/Ensemble/BaggingTest.php
+++ b/tests/Classification/Ensemble/BaggingTest.php
@@ -7,6 +7,7 @@ namespace Phpml\Tests\Classification\Ensemble;
use Phpml\Classification\DecisionTree;
use Phpml\Classification\Ensemble\Bagging;
use Phpml\Classification\NaiveBayes;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\ModelManager;
use PHPUnit\Framework\TestCase;
@@ -34,7 +35,15 @@ class BaggingTest extends TestCase
['scorching', 0, 0, 'false', 'Dont_play'],
];
- public function testPredictSingleSample()
+ public function testSetSubsetRatioThrowWhenRatioOutOfBounds(): void
+ {
+ $classifier = $this->getClassifier();
+
+ $this->expectException(InvalidArgumentException::class);
+ $classifier->setSubsetRatio(0);
+ }
+
+ public function testPredictSingleSample(): void
{
[$data, $targets] = $this->getData($this->data);
$classifier = $this->getClassifier();
@@ -48,8 +57,6 @@ class BaggingTest extends TestCase
$classifier->train($data, $targets);
$this->assertEquals('Dont_play', $classifier->predict(['scorching', 95, 90, 'true']));
$this->assertEquals('Play', $classifier->predict(['overcast', 60, 60, 'false']));
-
- return $classifier;
}
public function testSaveAndRestore(): void
diff --git a/tests/Classification/Linear/AdalineTest.php b/tests/Classification/Linear/AdalineTest.php
index c8ca752..62224e8 100644
--- a/tests/Classification/Linear/AdalineTest.php
+++ b/tests/Classification/Linear/AdalineTest.php
@@ -5,11 +5,23 @@ declare(strict_types=1);
namespace Phpml\Tests\Classification\Linear;
use Phpml\Classification\Linear\Adaline;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\ModelManager;
use PHPUnit\Framework\TestCase;
class AdalineTest extends TestCase
{
+ public function testAdalineThrowWhenInvalidTrainingType(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $classifier = new Adaline(
+ 0.001,
+ 1000,
+ true,
+ 0
+ );
+ }
+
public function testPredictSingleSample(): void
{
// AND problem
diff --git a/tests/Classification/Linear/DecisionStumpTest.php b/tests/Classification/Linear/DecisionStumpTest.php
index 93c8595..1295ac5 100644
--- a/tests/Classification/Linear/DecisionStumpTest.php
+++ b/tests/Classification/Linear/DecisionStumpTest.php
@@ -5,11 +5,24 @@ declare(strict_types=1);
namespace Phpml\Tests\Classification\Linear;
use Phpml\Classification\Linear\DecisionStump;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\ModelManager;
use PHPUnit\Framework\TestCase;
class DecisionStumpTest extends TestCase
{
+ public function testTrainThrowWhenSample(): void
+ {
+ $samples = [[0, 0], [1, 0], [0, 1], [1, 1]];
+ $targets = [0, 0, 1, 1];
+
+ $classifier = new DecisionStump();
+ $classifier->setSampleWeights([0.1, 0.1, 0.1]);
+
+ $this->expectException(InvalidArgumentException::class);
+ $classifier->train($samples, $targets);
+ }
+
public function testPredictSingleSample()
{
// Samples should be separable with a line perpendicular
diff --git a/tests/Classification/Linear/LogisticRegressionTest.php b/tests/Classification/Linear/LogisticRegressionTest.php
index ed9b878..37b5182 100644
--- a/tests/Classification/Linear/LogisticRegressionTest.php
+++ b/tests/Classification/Linear/LogisticRegressionTest.php
@@ -5,16 +5,16 @@ declare(strict_types=1);
namespace Phpml\Tests\Classification\Linear;
use Phpml\Classification\Linear\LogisticRegression;
+use Phpml\Exception\InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use ReflectionMethod;
use ReflectionProperty;
-use Throwable;
class LogisticRegressionTest extends TestCase
{
public function testConstructorThrowWhenInvalidTrainingType(): void
{
- $this->expectException(Throwable::class);
+ $this->expectException(InvalidArgumentException::class);
$classifier = new LogisticRegression(
500,
@@ -27,7 +27,7 @@ class LogisticRegressionTest extends TestCase
public function testConstructorThrowWhenInvalidCost(): void
{
- $this->expectException(Throwable::class);
+ $this->expectException(InvalidArgumentException::class);
$classifier = new LogisticRegression(
500,
@@ -40,7 +40,7 @@ class LogisticRegressionTest extends TestCase
public function testConstructorThrowWhenInvalidPenalty(): void
{
- $this->expectException(Throwable::class);
+ $this->expectException(InvalidArgumentException::class);
$classifier = new LogisticRegression(
500,
diff --git a/tests/Classification/Linear/PerceptronTest.php b/tests/Classification/Linear/PerceptronTest.php
index 35af855..731eac1 100644
--- a/tests/Classification/Linear/PerceptronTest.php
+++ b/tests/Classification/Linear/PerceptronTest.php
@@ -5,11 +5,24 @@ declare(strict_types=1);
namespace Phpml\Tests\Classification\Linear;
use Phpml\Classification\Linear\Perceptron;
+use Phpml\Exception\InvalidArgumentException;
use Phpml\ModelManager;
use PHPUnit\Framework\TestCase;
class PerceptronTest extends TestCase
{
+ public function testPerceptronThrowWhenLearningRateOutOfRange(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $classifier = new Perceptron(0, 5000);
+ }
+
+ public function testPerceptronThrowWhenMaxIterationsOutOfRange(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $classifier = new Perceptron(0.001, 0);
+ }
+
public function testPredictSingleSample(): void
{
// AND problem
diff --git a/tests/DimensionReduction/KernelPCATest.php b/tests/DimensionReduction/KernelPCATest.php
index 05a4138..dfd8bb9 100644
--- a/tests/DimensionReduction/KernelPCATest.php
+++ b/tests/DimensionReduction/KernelPCATest.php
@@ -5,6 +5,8 @@ declare(strict_types=1);
namespace Phpml\Tests\DimensionReduction;
use Phpml\DimensionReduction\KernelPCA;
+use Phpml\Exception\InvalidArgumentException;
+use Phpml\Exception\InvalidOperationException;
use PHPUnit\Framework\TestCase;
class KernelPCATest extends TestCase
@@ -48,4 +50,34 @@ class KernelPCATest extends TestCase
$newTransformed2 = $kpca->transform($newData);
$this->assertEquals(abs($newTransformed[0]), abs($newTransformed2[0]), '', $epsilon);
}
+
+ public function testKernelPCAThrowWhenKernelInvalid(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $kpca = new KernelPCA(0, null, 1, 15);
+ }
+
+ public function testTransformThrowWhenNotFitted(): void
+ {
+ $samples = [1, 0];
+
+ $kpca = new KernelPCA(KernelPCA::KERNEL_RBF, null, 1, 15);
+
+ $this->expectException(InvalidOperationException::class);
+ $kpca->transform($samples);
+ }
+
+ public function testTransformThrowWhenMultiDimensionalArrayGiven(): void
+ {
+ $samples = [
+ [1, 0],
+ [1, 1],
+ ];
+
+ $kpca = new KernelPCA(KernelPCA::KERNEL_RBF, null, 1, 15);
+ $kpca->fit($samples);
+
+ $this->expectException(InvalidArgumentException::class);
+ $kpca->transform($samples);
+ }
}
diff --git a/tests/DimensionReduction/LDATest.php b/tests/DimensionReduction/LDATest.php
index 2803a4b..641c226 100644
--- a/tests/DimensionReduction/LDATest.php
+++ b/tests/DimensionReduction/LDATest.php
@@ -6,6 +6,8 @@ namespace Phpml\Tests\DimensionReduction;
use Phpml\Dataset\Demo\IrisDataset;
use Phpml\DimensionReduction\LDA;
+use Phpml\Exception\InvalidArgumentException;
+use Phpml\Exception\InvalidOperationException;
use PHPUnit\Framework\TestCase;
class LDATest extends TestCase
@@ -62,4 +64,41 @@ class LDATest extends TestCase
array_map($check, $newRow, $newRow2);
}
}
+
+ public function testLDAThrowWhenTotalVarianceOutOfRange(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $pca = new LDA(0, null);
+ }
+
+ public function testLDAThrowWhenNumFeaturesOutOfRange(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $pca = new LDA(null, 0);
+ }
+
+ public function testLDAThrowWhenParameterNotSpecified(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $pca = new LDA();
+ }
+
+ public function testLDAThrowWhenBothParameterSpecified(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $pca = new LDA(0.9, 1);
+ }
+
+ public function testTransformThrowWhenNotFitted(): void
+ {
+ $samples = [
+ [1, 0],
+ [1, 1],
+ ];
+
+ $pca = new LDA(0.9);
+
+ $this->expectException(InvalidOperationException::class);
+ $pca->transform($samples);
+ }
}
diff --git a/tests/DimensionReduction/PCATest.php b/tests/DimensionReduction/PCATest.php
index 337b253..5fca211 100644
--- a/tests/DimensionReduction/PCATest.php
+++ b/tests/DimensionReduction/PCATest.php
@@ -5,6 +5,8 @@ declare(strict_types=1);
namespace Phpml\Tests\DimensionReduction;
use Phpml\DimensionReduction\PCA;
+use Phpml\Exception\InvalidArgumentException;
+use Phpml\Exception\InvalidOperationException;
use PHPUnit\Framework\TestCase;
class PCATest extends TestCase
@@ -54,4 +56,41 @@ class PCATest extends TestCase
}, $newRow, $newRow2);
}
}
+
+ public function testPCAThrowWhenTotalVarianceOutOfRange(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $pca = new PCA(0, null);
+ }
+
+ public function testPCAThrowWhenNumFeaturesOutOfRange(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $pca = new PCA(null, 0);
+ }
+
+ public function testPCAThrowWhenParameterNotSpecified(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $pca = new PCA();
+ }
+
+ public function testPCAThrowWhenBothParameterSpecified(): void
+ {
+ $this->expectException(InvalidArgumentException::class);
+ $pca = new PCA(0.9, 1);
+ }
+
+ public function testTransformThrowWhenNotFitted(): void
+ {
+ $samples = [
+ [1, 0],
+ [1, 1],
+ ];
+
+ $pca = new PCA(0.9);
+
+ $this->expectException(InvalidOperationException::class);
+ $pca->transform($samples);
+ }
}