Skip to content

Commit

Permalink
Throw proper exception (#259)
Browse files Browse the repository at this point in the history
* Throw proper exception

* Fix coding style
  • Loading branch information
y-uti authored and akondas committed Mar 6, 2018
1 parent a40c50b commit 66ca874
Show file tree
Hide file tree
Showing 18 changed files with 242 additions and 54 deletions.
6 changes: 3 additions & 3 deletions src/Classification/Ensemble/AdaBoost.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

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;
Expand Down Expand Up @@ -93,14 +93,14 @@ public function setBaseClassifier(string $baseClassifier = DecisionStump::class,
}

/**
* @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
Expand Down
6 changes: 3 additions & 3 deletions src/Classification/Ensemble/Bagging.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

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;
Expand Down Expand Up @@ -77,12 +77,12 @@ public function __construct(int $numClassifier = 50)
*
* @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;
Expand Down
6 changes: 3 additions & 3 deletions src/Classification/Linear/Adaline.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Phpml\Classification\Linear;

use Exception;
use Phpml\Exception\InvalidArgumentException;

class Adaline extends Perceptron
{
Expand Down Expand Up @@ -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,
Expand All @@ -43,7 +43,7 @@ public function __construct(
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;
Expand Down
6 changes: 3 additions & 3 deletions src/Classification/Linear/DecisionStump.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

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;
Expand Down Expand Up @@ -104,7 +104,7 @@ public function setNumericalSplitCount(float $count): void
}

/**
* @throws \Exception
* @throws InvalidArgumentException
*/
protected function trainBinary(array $samples, array $targets, array $labels): void
{
Expand All @@ -121,7 +121,7 @@ protected function trainBinary(array $samples, array $targets, array $labels): v
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);
Expand Down
23 changes: 16 additions & 7 deletions src/Classification/Linear/LogisticRegression.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Closure;
use Exception;
use Phpml\Exception\InvalidArgumentException;
use Phpml\Helper\Optimizer\ConjugateGradient;

class LogisticRegression extends Adaline
Expand Down Expand Up @@ -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,
Expand All @@ -72,18 +73,24 @@ public function __construct(
) {
$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;
Expand Down Expand Up @@ -140,7 +147,8 @@ protected function runTraining(array $samples, array $targets): void
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));
}
}

Expand Down Expand Up @@ -232,6 +240,7 @@ protected function getCostFunction(): Closure
return $callback;

default:
// Not reached
throw new Exception(sprintf('Logistic regression has invalid cost function: %s.', $this->costFunction));
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/Classification/Linear/Perceptron.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
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;
Expand Down Expand Up @@ -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) {
Expand Down
14 changes: 9 additions & 5 deletions src/DimensionReduction/KernelPCA.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -97,16 +99,17 @@ public function fit(array $data): array
* Transforms the given sample to a lower dimensional vector by using
* the variables obtained during the last run of <code>fit</code>.
*
* @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);
Expand Down Expand Up @@ -199,6 +202,7 @@ protected function getKernel(): Closure
};

default:
// Not reached
throw new Exception(sprintf('KernelPCA initialized with invalid kernel: %d', $this->kernel));
}
}
Expand Down
17 changes: 9 additions & 8 deletions src/DimensionReduction/LDA.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

namespace Phpml\DimensionReduction;

use Exception;
use Phpml\Exception\InvalidArgumentException;
use Phpml\Exception\InvalidOperationException;
use Phpml\Math\Matrix;

class LDA extends EigenTransformerBase
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -94,12 +95,12 @@ public function fit(array $data, array $classes): array
* Transforms the given sample to a lower dimensional vector by using
* the eigenVectors obtained in the last run of <code>fit</code>.
*
* @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])) {
Expand Down
17 changes: 9 additions & 8 deletions src/DimensionReduction/PCA.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

namespace Phpml\DimensionReduction;

use Exception;
use Phpml\Exception\InvalidArgumentException;
use Phpml\Exception\InvalidOperationException;
use Phpml\Math\Statistic\Covariance;
use Phpml\Math\Statistic\Mean;

Expand All @@ -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) {
Expand Down Expand Up @@ -81,12 +82,12 @@ public function fit(array $data): array
* Transforms the given sample to a lower dimensional vector by using
* the eigenVectors obtained in the last run of <code>fit</code>.
*
* @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])) {
Expand Down
Loading

0 comments on commit 66ca874

Please sign in to comment.