mirror of
https://github.com/Llewellynvdm/php-ml.git
synced 2024-11-21 20:45:10 +00:00
[coding standard] fix imports order and drop unused docs typehints (#145)
* fix imports order * drop unused docs typehints, make use of return types where possible
This commit is contained in:
parent
a0772658bf
commit
f4650c696c
@ -94,7 +94,7 @@ class CustomDistance implements Distance
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function distance(array $a, array $b): float
|
||||
public function distance(array $a, array $b) : float
|
||||
{
|
||||
$distance = [];
|
||||
$count = count($a);
|
||||
|
@ -49,9 +49,6 @@ class Apriori implements Associator
|
||||
|
||||
/**
|
||||
* Apriori constructor.
|
||||
*
|
||||
* @param float $support
|
||||
* @param float $confidence
|
||||
*/
|
||||
public function __construct(float $support = 0.0, float $confidence = 0.0)
|
||||
{
|
||||
@ -261,8 +258,6 @@ class Apriori implements Associator
|
||||
*
|
||||
* @param mixed[] $set
|
||||
* @param mixed[] $subset
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
private function confidence(array $set, array $subset) : float
|
||||
{
|
||||
@ -276,8 +271,6 @@ class Apriori implements Associator
|
||||
* @see \Phpml\Association\Apriori::samples
|
||||
*
|
||||
* @param mixed[] $sample
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
private function support(array $sample) : float
|
||||
{
|
||||
@ -290,8 +283,6 @@ class Apriori implements Associator
|
||||
* @see \Phpml\Association\Apriori::samples
|
||||
*
|
||||
* @param mixed[] $sample
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function frequency(array $sample) : int
|
||||
{
|
||||
@ -307,8 +298,6 @@ class Apriori implements Associator
|
||||
*
|
||||
* @param mixed[][] $system
|
||||
* @param mixed[] $set
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function contains(array $system, array $set) : bool
|
||||
{
|
||||
@ -322,8 +311,6 @@ class Apriori implements Associator
|
||||
*
|
||||
* @param mixed[] $set
|
||||
* @param mixed[] $subset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function subset(array $set, array $subset) : bool
|
||||
{
|
||||
@ -335,8 +322,6 @@ class Apriori implements Associator
|
||||
*
|
||||
* @param mixed[] $set1
|
||||
* @param mixed[] $set2
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function equals(array $set1, array $set2) : bool
|
||||
{
|
||||
|
@ -4,11 +4,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Classification;
|
||||
|
||||
use Phpml\Classification\DecisionTree\DecisionTreeLeaf;
|
||||
use Phpml\Exception\InvalidArgumentException;
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\Helper\Trainable;
|
||||
use Phpml\Math\Statistic\Mean;
|
||||
use Phpml\Classification\DecisionTree\DecisionTreeLeaf;
|
||||
|
||||
class DecisionTree implements Classifier
|
||||
{
|
||||
@ -63,14 +63,10 @@ class DecisionTree implements Classifier
|
||||
private $featureImportances = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $columnNames = null;
|
||||
|
||||
/**
|
||||
* @param int $maxDepth
|
||||
*/
|
||||
public function __construct(int $maxDepth = 10)
|
||||
{
|
||||
$this->maxDepth = $maxDepth;
|
||||
@ -129,8 +125,6 @@ class DecisionTree implements Classifier
|
||||
/**
|
||||
* @param array $records
|
||||
* @param int $depth
|
||||
*
|
||||
* @return DecisionTreeLeaf
|
||||
*/
|
||||
protected function getSplitLeaf(array $records, int $depth = 0) : DecisionTreeLeaf
|
||||
{
|
||||
@ -190,11 +184,6 @@ class DecisionTree implements Classifier
|
||||
return $split;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $records
|
||||
*
|
||||
* @return DecisionTreeLeaf
|
||||
*/
|
||||
protected function getBestSplit(array $records) : DecisionTreeLeaf
|
||||
{
|
||||
$targets = array_intersect_key($this->targets, array_flip($records));
|
||||
@ -277,10 +266,6 @@ class DecisionTree implements Classifier
|
||||
|
||||
/**
|
||||
* @param mixed $baseValue
|
||||
* @param array $colValues
|
||||
* @param array $targets
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getGiniIndex($baseValue, array $colValues, array $targets) : float
|
||||
{
|
||||
@ -342,8 +327,6 @@ class DecisionTree implements Classifier
|
||||
|
||||
/**
|
||||
* @param array $columnValues
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isCategoricalColumn(array $columnValues) : bool
|
||||
{
|
||||
@ -376,8 +359,6 @@ class DecisionTree implements Classifier
|
||||
* otherwise the given value will be used as a maximum for number of columns
|
||||
* randomly selected for each split operation.
|
||||
*
|
||||
* @param int $numFeatures
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
@ -395,8 +376,6 @@ class DecisionTree implements Classifier
|
||||
|
||||
/**
|
||||
* Used to set predefined features to consider while deciding which column to use for a split
|
||||
*
|
||||
* @param array $selectedFeatures
|
||||
*/
|
||||
protected function setSelectedFeatures(array $selectedFeatures)
|
||||
{
|
||||
@ -407,8 +386,6 @@ class DecisionTree implements Classifier
|
||||
* A string array to represent columns. Useful when HTML output or
|
||||
* column importances are desired to be inspected.
|
||||
*
|
||||
* @param array $names
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
@ -424,10 +401,7 @@ class DecisionTree implements Classifier
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHtml()
|
||||
public function getHtml() : string
|
||||
{
|
||||
return $this->tree->getHTML($this->columnNames);
|
||||
}
|
||||
@ -436,10 +410,8 @@ class DecisionTree implements Classifier
|
||||
* This will return an array including an importance value for
|
||||
* each column in the given dataset. The importance values are
|
||||
* normalized and their total makes 1.<br/>
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFeatureImportances()
|
||||
public function getFeatureImportances() : array
|
||||
{
|
||||
if ($this->featureImportances !== null) {
|
||||
return $this->featureImportances;
|
||||
@ -473,11 +445,6 @@ class DecisionTree implements Classifier
|
||||
/**
|
||||
* Collects and returns an array of internal nodes that use the given
|
||||
* column as a split criterion
|
||||
*
|
||||
* @param int $column
|
||||
* @param DecisionTreeLeaf $node
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getSplitNodesByColumn(int $column, DecisionTreeLeaf $node) : array
|
||||
{
|
||||
@ -506,8 +473,6 @@ class DecisionTree implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function predictSample(array $sample)
|
||||
|
@ -71,31 +71,22 @@ class DecisionTreeLeaf
|
||||
*/
|
||||
public $level = 0;
|
||||
|
||||
/**
|
||||
* @param array $record
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function evaluate($record)
|
||||
public function evaluate(array $record) : bool
|
||||
{
|
||||
$recordField = $record[$this->columnIndex];
|
||||
|
||||
if ($this->isContinuous) {
|
||||
return Comparison::compare((string) $recordField, $this->numericValue, $this->operator);
|
||||
}
|
||||
|
||||
|
||||
return $recordField == $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Mean Decrease Impurity (MDI) in the node.
|
||||
* For terminal nodes, this value is equal to 0
|
||||
*
|
||||
* @param int $parentRecordCount
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getNodeImpurityDecrease(int $parentRecordCount)
|
||||
public function getNodeImpurityDecrease(int $parentRecordCount) : float
|
||||
{
|
||||
if ($this->isTerminal) {
|
||||
return 0.0;
|
||||
@ -119,12 +110,8 @@ class DecisionTreeLeaf
|
||||
|
||||
/**
|
||||
* Returns HTML representation of the node including children nodes
|
||||
*
|
||||
* @param $columnNames
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHTML($columnNames = null)
|
||||
public function getHTML($columnNames = null) : string
|
||||
{
|
||||
if ($this->isTerminal) {
|
||||
$value = "<b>$this->classValue</b>";
|
||||
@ -170,10 +157,8 @@ class DecisionTreeLeaf
|
||||
|
||||
/**
|
||||
* HTML representation of the tree without column names
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString() : string
|
||||
{
|
||||
return $this->getHTML();
|
||||
}
|
||||
|
@ -4,13 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Classification\Ensemble;
|
||||
|
||||
use Phpml\Classification\Classifier;
|
||||
use Phpml\Classification\Linear\DecisionStump;
|
||||
use Phpml\Classification\WeightedClassifier;
|
||||
use Phpml\Math\Statistic\Mean;
|
||||
use Phpml\Math\Statistic\StandardDeviation;
|
||||
use Phpml\Classification\Classifier;
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\Helper\Trainable;
|
||||
use Phpml\Math\Statistic\Mean;
|
||||
use Phpml\Math\Statistic\StandardDeviation;
|
||||
|
||||
class AdaBoost implements Classifier
|
||||
{
|
||||
@ -75,8 +75,6 @@ class AdaBoost implements Classifier
|
||||
* ADAptive BOOSTing (AdaBoost) is an ensemble algorithm to
|
||||
* improve classification performance of 'weak' classifiers such as
|
||||
* DecisionStump (default base classifier of AdaBoost).
|
||||
*
|
||||
* @param int $maxIterations
|
||||
*/
|
||||
public function __construct(int $maxIterations = 50)
|
||||
{
|
||||
@ -85,9 +83,6 @@ class AdaBoost implements Classifier
|
||||
|
||||
/**
|
||||
* Sets the base classifier that will be used for boosting (default = DecisionStump)
|
||||
*
|
||||
* @param string $baseClassifier
|
||||
* @param array $classifierOptions
|
||||
*/
|
||||
public function setBaseClassifier(string $baseClassifier = DecisionStump::class, array $classifierOptions = [])
|
||||
{
|
||||
@ -96,9 +91,6 @@ class AdaBoost implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function train(array $samples, array $targets)
|
||||
@ -143,10 +135,8 @@ class AdaBoost implements Classifier
|
||||
/**
|
||||
* Returns the classifier with the lowest error rate with the
|
||||
* consideration of current sample weights
|
||||
*
|
||||
* @return Classifier
|
||||
*/
|
||||
protected function getBestClassifier()
|
||||
protected function getBestClassifier() : Classifier
|
||||
{
|
||||
$ref = new \ReflectionClass($this->baseClassifier);
|
||||
if ($this->classifierOptions) {
|
||||
@ -169,10 +159,8 @@ class AdaBoost implements Classifier
|
||||
/**
|
||||
* Resamples the dataset in accordance with the weights and
|
||||
* returns the new dataset
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function resample()
|
||||
protected function resample() : array
|
||||
{
|
||||
$weights = $this->weights;
|
||||
$std = StandardDeviation::population($weights);
|
||||
@ -198,12 +186,8 @@ class AdaBoost implements Classifier
|
||||
|
||||
/**
|
||||
* Evaluates the classifier and returns the classification error rate
|
||||
*
|
||||
* @param Classifier $classifier
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function evaluateClassifier(Classifier $classifier)
|
||||
protected function evaluateClassifier(Classifier $classifier) : float
|
||||
{
|
||||
$total = (float) array_sum($this->weights);
|
||||
$wrong = 0;
|
||||
@ -219,12 +203,8 @@ class AdaBoost implements Classifier
|
||||
|
||||
/**
|
||||
* Calculates alpha of a classifier
|
||||
*
|
||||
* @param float $errorRate
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function calculateAlpha(float $errorRate)
|
||||
protected function calculateAlpha(float $errorRate) : float
|
||||
{
|
||||
if ($errorRate == 0) {
|
||||
$errorRate = 1e-10;
|
||||
@ -235,9 +215,6 @@ class AdaBoost implements Classifier
|
||||
|
||||
/**
|
||||
* Updates the sample weights
|
||||
*
|
||||
* @param Classifier $classifier
|
||||
* @param float $alpha
|
||||
*/
|
||||
protected function updateWeights(Classifier $classifier, float $alpha)
|
||||
{
|
||||
@ -256,8 +233,6 @@ class AdaBoost implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function predictSample(array $sample)
|
||||
|
@ -4,10 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Classification\Ensemble;
|
||||
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\Helper\Trainable;
|
||||
use Phpml\Classification\Classifier;
|
||||
use Phpml\Classification\DecisionTree;
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\Helper\Trainable;
|
||||
|
||||
class Bagging implements Classifier
|
||||
{
|
||||
@ -62,8 +62,6 @@ class Bagging implements Classifier
|
||||
* Creates an ensemble classifier with given number of base classifiers
|
||||
* Default number of base classifiers is 50.
|
||||
* The more number of base classifiers, the better performance but at the cost of procesing time
|
||||
*
|
||||
* @param int $numClassifier
|
||||
*/
|
||||
public function __construct(int $numClassifier = 50)
|
||||
{
|
||||
@ -75,8 +73,6 @@ class Bagging implements Classifier
|
||||
* e.g., random samples drawn from the original dataset with replacement (allow repeats),
|
||||
* to train each base classifier.
|
||||
*
|
||||
* @param float $ratio
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Exception
|
||||
@ -100,9 +96,6 @@ class Bagging implements Classifier
|
||||
* given in the order they are in the constructor of the classifier and parameter
|
||||
* names are neglected.
|
||||
*
|
||||
* @param string $classifier
|
||||
* @param array $classifierOptions
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setClassifer(string $classifier, array $classifierOptions = [])
|
||||
@ -113,10 +106,6 @@ class Bagging implements Classifier
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
public function train(array $samples, array $targets)
|
||||
{
|
||||
$this->samples = array_merge($this->samples, $samples);
|
||||
@ -134,12 +123,7 @@ class Bagging implements Classifier
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getRandomSubset(int $index)
|
||||
protected function getRandomSubset(int $index) : array
|
||||
{
|
||||
$samples = [];
|
||||
$targets = [];
|
||||
@ -154,10 +138,7 @@ class Bagging implements Classifier
|
||||
return [$samples, $targets];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function initClassifiers()
|
||||
protected function initClassifiers() : array
|
||||
{
|
||||
$classifiers = [];
|
||||
for ($i = 0; $i < $this->numClassifier; ++$i) {
|
||||
@ -185,8 +166,6 @@ class Bagging implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function predictSample(array $sample)
|
||||
|
@ -22,8 +22,6 @@ class RandomForest extends Bagging
|
||||
* Initializes RandomForest with the given number of trees. More trees
|
||||
* may increase the prediction performance while it will also substantially
|
||||
* increase the processing time and the required memory
|
||||
*
|
||||
* @param int $numClassifier
|
||||
*/
|
||||
public function __construct(int $numClassifier = 50)
|
||||
{
|
||||
@ -65,9 +63,6 @@ class RandomForest extends Bagging
|
||||
/**
|
||||
* RandomForest algorithm is usable *only* with DecisionTree
|
||||
*
|
||||
* @param string $classifier
|
||||
* @param array $classifierOptions
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Exception
|
||||
@ -85,10 +80,8 @@ class RandomForest extends Bagging
|
||||
* This will return an array including an importance value for
|
||||
* each column in the given dataset. Importance values for a column
|
||||
* is the average importance of that column in all trees in the forest
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFeatureImportances()
|
||||
public function getFeatureImportances() : array
|
||||
{
|
||||
// Traverse each tree and sum importance of the columns
|
||||
$sum = [];
|
||||
@ -120,8 +113,6 @@ class RandomForest extends Bagging
|
||||
* A string array to represent the columns is given. They are useful
|
||||
* when trying to print some information about the trees such as feature importances
|
||||
*
|
||||
* @param array $names
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnNames(array $names)
|
||||
|
@ -24,7 +24,6 @@ class KNearestNeighbors implements Classifier
|
||||
private $distanceMetric;
|
||||
|
||||
/**
|
||||
* @param int $k
|
||||
* @param Distance|null $distanceMetric (if null then Euclidean distance as default)
|
||||
*/
|
||||
public function __construct(int $k = 3, Distance $distanceMetric = null)
|
||||
@ -40,8 +39,6 @@ class KNearestNeighbors implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function predictSample(array $sample)
|
||||
@ -61,13 +58,9 @@ class KNearestNeighbors implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Phpml\Exception\InvalidArgumentException
|
||||
*/
|
||||
private function kNeighborsDistances(array $sample)
|
||||
private function kNeighborsDistances(array $sample) : array
|
||||
{
|
||||
$distances = [];
|
||||
|
||||
|
@ -32,11 +32,6 @@ 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
|
||||
*
|
||||
* @param float $learningRate
|
||||
* @param int $maxIterations
|
||||
* @param bool $normalizeInputs
|
||||
* @param int $trainingType
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(
|
||||
@ -57,8 +52,6 @@ class Adaline extends Perceptron
|
||||
/**
|
||||
* Adapts the weights with respect to given samples and targets
|
||||
* by use of gradient descent learning rule
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
protected function runTraining(array $samples, array $targets)
|
||||
|
@ -4,10 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Classification\Linear;
|
||||
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\Helper\OneVsRest;
|
||||
use Phpml\Classification\WeightedClassifier;
|
||||
use Phpml\Classification\DecisionTree;
|
||||
use Phpml\Classification\WeightedClassifier;
|
||||
use Phpml\Helper\OneVsRest;
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\Math\Comparison;
|
||||
|
||||
class DecisionStump extends WeightedClassifier
|
||||
@ -77,8 +77,6 @@ class DecisionStump extends WeightedClassifier
|
||||
* If columnIndex is given, then the stump tries to produce a decision node
|
||||
* on this column, otherwise in cases given the value of -1, the stump itself
|
||||
* decides which column to take for the decision (Default DecisionTree behaviour)
|
||||
*
|
||||
* @param int $columnIndex
|
||||
*/
|
||||
public function __construct(int $columnIndex = self::AUTO_SELECT)
|
||||
{
|
||||
@ -86,10 +84,6 @@ class DecisionStump extends WeightedClassifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param array $labels
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function trainBinary(array $samples, array $targets, array $labels)
|
||||
@ -151,8 +145,6 @@ class DecisionStump extends WeightedClassifier
|
||||
* values in the column. Given <i>$count</i> value determines how many split
|
||||
* points to be probed. The more split counts, the better performance but
|
||||
* worse processing time (Default value is 10.0)
|
||||
*
|
||||
* @param float $count
|
||||
*/
|
||||
public function setNumericalSplitCount(float $count)
|
||||
{
|
||||
@ -161,14 +153,8 @@ class DecisionStump extends WeightedClassifier
|
||||
|
||||
/**
|
||||
* Determines best split point for the given column
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param int $col
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getBestNumericalSplit(array $samples, array $targets, int $col)
|
||||
protected function getBestNumericalSplit(array $samples, array $targets, int $col) : array
|
||||
{
|
||||
$values = array_column($samples, $col);
|
||||
// Trying all possible points may be accomplished in two general ways:
|
||||
@ -207,13 +193,6 @@ class DecisionStump extends WeightedClassifier
|
||||
return $split;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param int $col
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getBestNominalSplit(array $samples, array $targets, int $col) : array
|
||||
{
|
||||
$values = array_column($samples, $col);
|
||||
@ -240,13 +219,6 @@ class DecisionStump extends WeightedClassifier
|
||||
/**
|
||||
* Calculates the ratio of wrong predictions based on the new threshold
|
||||
* value given as the parameter
|
||||
*
|
||||
* @param array $targets
|
||||
* @param float $threshold
|
||||
* @param string $operator
|
||||
* @param array $values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function calculateErrorRate(array $targets, float $threshold, string $operator, array $values) : array
|
||||
{
|
||||
@ -293,10 +265,7 @@ class DecisionStump extends WeightedClassifier
|
||||
* Probability of a sample is calculated as the proportion of the label
|
||||
* within the labels of the training samples in the decision node
|
||||
*
|
||||
* @param array $sample
|
||||
* @param mixed $label
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function predictProbability(array $sample, $label) : float
|
||||
{
|
||||
@ -309,8 +278,6 @@ class DecisionStump extends WeightedClassifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function predictSampleBinary(array $sample)
|
||||
@ -322,17 +289,11 @@ class DecisionStump extends WeightedClassifier
|
||||
return $this->binaryLabels[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function resetBinary()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString() : string
|
||||
{
|
||||
return "IF $this->column $this->operator $this->value ".
|
||||
'THEN '.$this->binaryLabels[0].' '.
|
||||
|
@ -59,12 +59,6 @@ class LogisticRegression extends Adaline
|
||||
*
|
||||
* Penalty (Regularization term) can be 'L2' or empty string to cancel penalty term
|
||||
*
|
||||
* @param int $maxIterations
|
||||
* @param bool $normalizeInputs
|
||||
* @param int $trainingType
|
||||
* @param string $cost
|
||||
* @param string $penalty
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(
|
||||
@ -102,8 +96,6 @@ class LogisticRegression extends Adaline
|
||||
/**
|
||||
* Sets the learning rate if gradient descent algorithm is
|
||||
* selected for training
|
||||
*
|
||||
* @param float $learningRate
|
||||
*/
|
||||
public function setLearningRate(float $learningRate)
|
||||
{
|
||||
@ -113,8 +105,6 @@ class LogisticRegression extends Adaline
|
||||
/**
|
||||
* Lambda (λ) parameter of regularization term. If 0 is given,
|
||||
* then the regularization term is cancelled
|
||||
*
|
||||
* @param float $lambda
|
||||
*/
|
||||
public function setLambda(float $lambda)
|
||||
{
|
||||
@ -125,9 +115,6 @@ class LogisticRegression extends Adaline
|
||||
* Adapts the weights with respect to given samples and targets
|
||||
* by use of selected solver
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function runTraining(array $samples, array $targets)
|
||||
@ -154,7 +141,6 @@ class LogisticRegression extends Adaline
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param \Closure $gradientFunc
|
||||
*/
|
||||
protected function runConjugateGradient(array $samples, array $targets, \Closure $gradientFunc)
|
||||
{
|
||||
@ -170,11 +156,9 @@ class LogisticRegression extends Adaline
|
||||
/**
|
||||
* Returns the appropriate callback function for the selected cost function
|
||||
*
|
||||
* @return \Closure
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getCostFunction()
|
||||
protected function getCostFunction() : \Closure
|
||||
{
|
||||
$penalty = 0;
|
||||
if ($this->penalty == 'L2') {
|
||||
@ -244,8 +228,6 @@ class LogisticRegression extends Adaline
|
||||
/**
|
||||
* Returns the output of the network, a float value between 0.0 and 1.0
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function output(array $sample)
|
||||
@ -257,12 +239,8 @@ class LogisticRegression extends Adaline
|
||||
|
||||
/**
|
||||
* Returns the class value (either -1 or 1) for the given input
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function outputClass(array $sample)
|
||||
protected function outputClass(array $sample) : int
|
||||
{
|
||||
$output = $this->output($sample);
|
||||
|
||||
@ -278,20 +256,17 @@ class LogisticRegression extends Adaline
|
||||
*
|
||||
* The probability is simply taken as the distance of the sample
|
||||
* to the decision plane.
|
||||
*
|
||||
* @param array $sample
|
||||
|
||||
* @param mixed $label
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function predictProbability(array $sample, $label)
|
||||
protected function predictProbability(array $sample, $label) : float
|
||||
{
|
||||
$predicted = $this->predictSampleBinary($sample);
|
||||
|
||||
if ((string) $predicted == (string) $label) {
|
||||
$sample = $this->checkNormalizedSample($sample);
|
||||
|
||||
return abs($this->output($sample) - 0.5);
|
||||
return (float) abs($this->output($sample) - 0.5);
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
|
@ -4,13 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Classification\Linear;
|
||||
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\Helper\OneVsRest;
|
||||
use Phpml\Helper\Optimizer\StochasticGD;
|
||||
use Phpml\Helper\Optimizer\GD;
|
||||
use Phpml\Classification\Classifier;
|
||||
use Phpml\Preprocessing\Normalizer;
|
||||
use Phpml\Helper\OneVsRest;
|
||||
use Phpml\Helper\Optimizer\GD;
|
||||
use Phpml\Helper\Optimizer\StochasticGD;
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\IncrementalEstimator;
|
||||
use Phpml\Preprocessing\Normalizer;
|
||||
|
||||
class Perceptron implements Classifier, IncrementalEstimator
|
||||
{
|
||||
@ -67,7 +67,6 @@ 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
|
||||
* @param bool $normalizeInputs
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
@ -89,21 +88,11 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
$this->maxIterations = $maxIterations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param array $labels
|
||||
*/
|
||||
public function partialTrain(array $samples, array $targets, array $labels = [])
|
||||
{
|
||||
$this->trainByLabel($samples, $targets, $labels);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param array $labels
|
||||
*/
|
||||
public function trainBinary(array $samples, array $targets, array $labels)
|
||||
{
|
||||
if ($this->normalizer) {
|
||||
@ -139,8 +128,6 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
* If "false" is given, the optimization procedure will always be executed
|
||||
* for $maxIterations times
|
||||
*
|
||||
* @param bool $enable
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setEarlyStop(bool $enable = true)
|
||||
@ -152,10 +139,8 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
|
||||
/**
|
||||
* Returns the cost values obtained during the training.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCostValues()
|
||||
public function getCostValues() : array
|
||||
{
|
||||
return $this->costValues;
|
||||
}
|
||||
@ -163,9 +148,6 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
/**
|
||||
* Trains the perceptron model with Stochastic Gradient Descent optimization
|
||||
* to get the correct set of weights
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
protected function runTraining(array $samples, array $targets)
|
||||
{
|
||||
@ -186,11 +168,6 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
/**
|
||||
* Executes a Gradient Descent algorithm for
|
||||
* the given cost function
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param \Closure $gradientFunc
|
||||
* @param bool $isBatch
|
||||
*/
|
||||
protected function runGradientDescent(array $samples, array $targets, \Closure $gradientFunc, bool $isBatch = false)
|
||||
{
|
||||
@ -211,12 +188,8 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
/**
|
||||
* Checks if the sample should be normalized and if so, returns the
|
||||
* normalized sample
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function checkNormalizedSample(array $sample)
|
||||
protected function checkNormalizedSample(array $sample) : array
|
||||
{
|
||||
if ($this->normalizer) {
|
||||
$samples = [$sample];
|
||||
@ -230,8 +203,6 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
/**
|
||||
* Calculates net output of the network as a float value for the given input
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function output(array $sample)
|
||||
@ -250,12 +221,8 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
|
||||
/**
|
||||
* Returns the class value (either -1 or 1) for the given input
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function outputClass(array $sample)
|
||||
protected function outputClass(array $sample) : int
|
||||
{
|
||||
return $this->output($sample) > 0 ? 1 : -1;
|
||||
}
|
||||
@ -266,27 +233,22 @@ class Perceptron implements Classifier, IncrementalEstimator
|
||||
* The probability is simply taken as the distance of the sample
|
||||
* to the decision plane.
|
||||
*
|
||||
* @param array $sample
|
||||
* @param mixed $label
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function predictProbability(array $sample, $label)
|
||||
protected function predictProbability(array $sample, $label) : float
|
||||
{
|
||||
$predicted = $this->predictSampleBinary($sample);
|
||||
|
||||
if ((string) $predicted == (string) $label) {
|
||||
$sample = $this->checkNormalizedSample($sample);
|
||||
|
||||
return abs($this->output($sample));
|
||||
return (float) abs($this->output($sample));
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function predictSampleBinary(array $sample)
|
||||
|
@ -13,10 +13,8 @@ class MLPClassifier extends MultilayerPerceptron implements Classifier
|
||||
* @param mixed $target
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTargetClass($target): int
|
||||
public function getTargetClass($target) : int
|
||||
{
|
||||
if (!in_array($target, $this->classes)) {
|
||||
throw InvalidArgumentException::invalidTarget($target);
|
||||
@ -26,8 +24,6 @@ class MLPClassifier extends MultilayerPerceptron implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function predictSample(array $sample)
|
||||
@ -47,7 +43,6 @@ class MLPClassifier extends MultilayerPerceptron implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
* @param mixed $target
|
||||
*/
|
||||
protected function trainSample(array $sample, $target)
|
||||
|
@ -57,10 +57,6 @@ class NaiveBayes implements Classifier
|
||||
*/
|
||||
private $labels = [];
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
public function train(array $samples, array $targets)
|
||||
{
|
||||
$this->samples = array_merge($this->samples, $samples);
|
||||
@ -80,11 +76,8 @@ class NaiveBayes implements Classifier
|
||||
/**
|
||||
* Calculates vital statistics for each label & feature. Stores these
|
||||
* values in private array in order to avoid repeated calculation
|
||||
*
|
||||
* @param string $label
|
||||
* @param array $samples
|
||||
*/
|
||||
private function calculateStatistics($label, $samples)
|
||||
private function calculateStatistics(string $label, array $samples)
|
||||
{
|
||||
$this->std[$label] = array_fill(0, $this->featureCount, 0);
|
||||
$this->mean[$label] = array_fill(0, $this->featureCount, 0);
|
||||
@ -114,14 +107,8 @@ class NaiveBayes implements Classifier
|
||||
|
||||
/**
|
||||
* Calculates the probability P(label|sample_n)
|
||||
*
|
||||
* @param array $sample
|
||||
* @param int $feature
|
||||
* @param string $label
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
private function sampleProbability($sample, $feature, $label)
|
||||
private function sampleProbability(array $sample, int $feature, string $label) : float
|
||||
{
|
||||
$value = $sample[$feature];
|
||||
if ($this->dataType[$label][$feature] == self::NOMINAL) {
|
||||
@ -149,12 +136,8 @@ class NaiveBayes implements Classifier
|
||||
|
||||
/**
|
||||
* Return samples belonging to specific label
|
||||
*
|
||||
* @param string $label
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSamplesByLabel($label)
|
||||
private function getSamplesByLabel(string $label) : array
|
||||
{
|
||||
$samples = [];
|
||||
for ($i = 0; $i < $this->sampleCount; ++$i) {
|
||||
@ -167,8 +150,6 @@ class NaiveBayes implements Classifier
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function predictSample(array $sample)
|
||||
|
@ -10,17 +10,6 @@ use Phpml\SupportVectorMachine\Type;
|
||||
|
||||
class SVC extends SupportVectorMachine implements Classifier
|
||||
{
|
||||
/**
|
||||
* @param int $kernel
|
||||
* @param float $cost
|
||||
* @param int $degree
|
||||
* @param float|null $gamma
|
||||
* @param float $coef0
|
||||
* @param float $tolerance
|
||||
* @param int $cacheSize
|
||||
* @param bool $shrinking
|
||||
* @param bool $probabilityEstimates
|
||||
*/
|
||||
public function __construct(
|
||||
int $kernel = Kernel::LINEAR,
|
||||
float $cost = 1.0,
|
||||
|
@ -6,10 +6,5 @@ namespace Phpml\Clustering;
|
||||
|
||||
interface Clusterer
|
||||
{
|
||||
/**
|
||||
* @param array $samples
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function cluster(array $samples);
|
||||
public function cluster(array $samples) : array;
|
||||
}
|
||||
|
@ -24,12 +24,7 @@ class DBSCAN implements Clusterer
|
||||
*/
|
||||
private $distanceMetric;
|
||||
|
||||
/**
|
||||
* @param float $epsilon
|
||||
* @param int $minSamples
|
||||
* @param Distance $distanceMetric
|
||||
*/
|
||||
public function __construct($epsilon = 0.5, $minSamples = 3, Distance $distanceMetric = null)
|
||||
public function __construct(float $epsilon = 0.5, int $minSamples = 3, Distance $distanceMetric = null)
|
||||
{
|
||||
if (null === $distanceMetric) {
|
||||
$distanceMetric = new Euclidean();
|
||||
@ -40,12 +35,7 @@ class DBSCAN implements Clusterer
|
||||
$this->distanceMetric = $distanceMetric;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function cluster(array $samples)
|
||||
public function cluster(array $samples) : array
|
||||
{
|
||||
$clusters = [];
|
||||
$visited = [];
|
||||
@ -65,13 +55,7 @@ class DBSCAN implements Clusterer
|
||||
return $clusters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $localSample
|
||||
* @param array $samples
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSamplesInRegion($localSample, $samples)
|
||||
private function getSamplesInRegion(array $localSample, array $samples) : array
|
||||
{
|
||||
$region = [];
|
||||
|
||||
@ -84,13 +68,7 @@ class DBSCAN implements Clusterer
|
||||
return $region;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $visited
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function expandCluster($samples, &$visited)
|
||||
private function expandCluster(array $samples, array &$visited) : array
|
||||
{
|
||||
$cluster = [];
|
||||
|
||||
|
@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Clustering;
|
||||
|
||||
use Phpml\Clustering\KMeans\Point;
|
||||
use Phpml\Clustering\KMeans\Cluster;
|
||||
use Phpml\Clustering\KMeans\Point;
|
||||
use Phpml\Clustering\KMeans\Space;
|
||||
use Phpml\Exception\InvalidArgumentException;
|
||||
use Phpml\Math\Distance\Euclidean;
|
||||
@ -58,11 +58,6 @@ class FuzzyCMeans implements Clusterer
|
||||
private $samples;
|
||||
|
||||
/**
|
||||
* @param int $clustersNumber
|
||||
* @param float $fuzziness
|
||||
* @param float $epsilon
|
||||
* @param int $maxIterations
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(int $clustersNumber, float $fuzziness = 2.0, float $epsilon = 1e-2, int $maxIterations = 100)
|
||||
@ -85,10 +80,6 @@ class FuzzyCMeans implements Clusterer
|
||||
$this->updateClusters();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $rows
|
||||
* @param int $cols
|
||||
*/
|
||||
protected function generateRandomMembership(int $rows, int $cols)
|
||||
{
|
||||
$this->membership = [];
|
||||
@ -155,14 +146,7 @@ class FuzzyCMeans implements Clusterer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $row
|
||||
* @param int $col
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function getDistanceCalc(int $row, int $col)
|
||||
protected function getDistanceCalc(int $row, int $col) : float
|
||||
{
|
||||
$sum = 0.0;
|
||||
$distance = new Euclidean();
|
||||
@ -204,20 +188,15 @@ class FuzzyCMeans implements Clusterer
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMembershipMatrix()
|
||||
public function getMembershipMatrix() : array
|
||||
{
|
||||
return $this->membership;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|Point[] $samples
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function cluster(array $samples)
|
||||
public function cluster(array $samples) : array
|
||||
{
|
||||
// Initialize variables, clusters and membership matrix
|
||||
$this->sampleCount = count($samples);
|
||||
|
@ -22,12 +22,6 @@ class KMeans implements Clusterer
|
||||
*/
|
||||
private $initialization;
|
||||
|
||||
/**
|
||||
* @param int $clustersNumber
|
||||
* @param int $initialization
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(int $clustersNumber, int $initialization = self::INIT_KMEANS_PLUS_PLUS)
|
||||
{
|
||||
if ($clustersNumber <= 0) {
|
||||
@ -38,12 +32,7 @@ class KMeans implements Clusterer
|
||||
$this->initialization = $initialization;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function cluster(array $samples)
|
||||
public function cluster(array $samples) : array
|
||||
{
|
||||
$space = new Space(count($samples[0]));
|
||||
foreach ($samples as $sample) {
|
||||
|
@ -4,10 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Clustering\KMeans;
|
||||
|
||||
use IteratorAggregate;
|
||||
use Countable;
|
||||
use SplObjectStorage;
|
||||
use IteratorAggregate;
|
||||
use LogicException;
|
||||
use SplObjectStorage;
|
||||
|
||||
class Cluster extends Point implements IteratorAggregate, Countable
|
||||
{
|
||||
@ -21,10 +21,6 @@ class Cluster extends Point implements IteratorAggregate, Countable
|
||||
*/
|
||||
protected $points;
|
||||
|
||||
/**
|
||||
* @param Space $space
|
||||
* @param array $coordinates
|
||||
*/
|
||||
public function __construct(Space $space, array $coordinates)
|
||||
{
|
||||
parent::__construct($coordinates);
|
||||
@ -32,10 +28,7 @@ class Cluster extends Point implements IteratorAggregate, Countable
|
||||
$this->points = new SplObjectStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getPoints()
|
||||
public function getPoints() : array
|
||||
{
|
||||
$points = [];
|
||||
foreach ($this->points as $point) {
|
||||
@ -45,10 +38,7 @@ class Cluster extends Point implements IteratorAggregate, Countable
|
||||
return $points;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
public function toArray() : array
|
||||
{
|
||||
return [
|
||||
'centroid' => parent::toArray(),
|
||||
@ -56,14 +46,7 @@ class Cluster extends Point implements IteratorAggregate, Countable
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Point $point
|
||||
*
|
||||
* @return Point
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function attach(Point $point)
|
||||
public function attach(Point $point) : Point
|
||||
{
|
||||
if ($point instanceof self) {
|
||||
throw new LogicException('cannot attach a cluster to another');
|
||||
@ -74,29 +57,18 @@ class Cluster extends Point implements IteratorAggregate, Countable
|
||||
return $point;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Point $point
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function detach(Point $point)
|
||||
public function detach(Point $point) : Point
|
||||
{
|
||||
$this->points->detach($point);
|
||||
|
||||
return $point;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SplObjectStorage $points
|
||||
*/
|
||||
public function attachAll(SplObjectStorage $points)
|
||||
{
|
||||
$this->points->addAll($points);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SplObjectStorage $points
|
||||
*/
|
||||
public function detachAll(SplObjectStorage $points)
|
||||
{
|
||||
$this->points->removeAll($points);
|
||||
@ -136,10 +108,7 @@ class Cluster extends Point implements IteratorAggregate, Countable
|
||||
{
|
||||
return count($this->points);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $newCoordinates
|
||||
*/
|
||||
|
||||
public function setCoordinates(array $newCoordinates)
|
||||
{
|
||||
$this->coordinates = $newCoordinates;
|
||||
|
@ -18,30 +18,21 @@ class Point implements ArrayAccess
|
||||
*/
|
||||
protected $coordinates;
|
||||
|
||||
/**
|
||||
* @param array $coordinates
|
||||
*/
|
||||
public function __construct(array $coordinates)
|
||||
{
|
||||
$this->dimension = count($coordinates);
|
||||
$this->coordinates = $coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
public function toArray() : array
|
||||
{
|
||||
return $this->coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Point $point
|
||||
* @param bool $precise
|
||||
*
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function getDistanceWith(self $point, $precise = true)
|
||||
public function getDistanceWith(self $point, bool $precise = true)
|
||||
{
|
||||
$distance = 0;
|
||||
for ($n = 0; $n < $this->dimension; ++$n) {
|
||||
@ -53,8 +44,6 @@ class Point implements ArrayAccess
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $points
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getClosest(array $points)
|
||||
@ -77,20 +66,15 @@ class Point implements ArrayAccess
|
||||
return $minPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getCoordinates()
|
||||
public function getCoordinates() : array
|
||||
{
|
||||
return $this->coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return isset($this->coordinates[$offset]);
|
||||
}
|
||||
|
@ -4,10 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Clustering\KMeans;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use Phpml\Clustering\KMeans;
|
||||
use SplObjectStorage;
|
||||
use LogicException;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Space extends SplObjectStorage
|
||||
{
|
||||
@ -16,9 +16,6 @@ class Space extends SplObjectStorage
|
||||
*/
|
||||
protected $dimension;
|
||||
|
||||
/**
|
||||
* @param $dimension
|
||||
*/
|
||||
public function __construct($dimension)
|
||||
{
|
||||
if ($dimension < 1) {
|
||||
@ -28,10 +25,7 @@ class Space extends SplObjectStorage
|
||||
$this->dimension = $dimension;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
public function toArray() : array
|
||||
{
|
||||
$points = [];
|
||||
foreach ($this as $point) {
|
||||
@ -41,12 +35,7 @@ class Space extends SplObjectStorage
|
||||
return ['points' => $points];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $coordinates
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function newPoint(array $coordinates)
|
||||
public function newPoint(array $coordinates) : Point
|
||||
{
|
||||
if (count($coordinates) != $this->dimension) {
|
||||
throw new LogicException('('.implode(',', $coordinates).') is not a point of this space');
|
||||
@ -56,7 +45,6 @@ class Space extends SplObjectStorage
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $coordinates
|
||||
* @param null $data
|
||||
*/
|
||||
public function addPoint(array $coordinates, $data = null)
|
||||
@ -77,10 +65,7 @@ class Space extends SplObjectStorage
|
||||
parent::attach($point, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getDimension()
|
||||
public function getDimension() : int
|
||||
{
|
||||
return $this->dimension;
|
||||
}
|
||||
@ -107,13 +92,7 @@ class Space extends SplObjectStorage
|
||||
return [$min, $max];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Point $min
|
||||
* @param Point $max
|
||||
*
|
||||
* @return Point
|
||||
*/
|
||||
public function getRandomPoint(Point $min, Point $max)
|
||||
public function getRandomPoint(Point $min, Point $max) : Point
|
||||
{
|
||||
$point = $this->newPoint(array_fill(0, $this->dimension, null));
|
||||
|
||||
@ -125,12 +104,9 @@ class Space extends SplObjectStorage
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $clustersNumber
|
||||
* @param int $initMethod
|
||||
*
|
||||
* @return array|Cluster[]
|
||||
*/
|
||||
public function cluster(int $clustersNumber, int $initMethod = KMeans::INIT_RANDOM)
|
||||
public function cluster(int $clustersNumber, int $initMethod = KMeans::INIT_RANDOM) : array
|
||||
{
|
||||
$clusters = $this->initializeClusters($clustersNumber, $initMethod);
|
||||
|
||||
@ -141,12 +117,9 @@ class Space extends SplObjectStorage
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $clustersNumber
|
||||
* @param $initMethod
|
||||
*
|
||||
* @return array|Cluster[]
|
||||
*/
|
||||
protected function initializeClusters(int $clustersNumber, int $initMethod)
|
||||
protected function initializeClusters(int $clustersNumber, int $initMethod) : array
|
||||
{
|
||||
switch ($initMethod) {
|
||||
case KMeans::INIT_RANDOM:
|
||||
@ -166,12 +139,7 @@ class Space extends SplObjectStorage
|
||||
return $clusters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $clusters
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function iterate($clusters)
|
||||
protected function iterate($clusters) : bool
|
||||
{
|
||||
$convergence = true;
|
||||
|
||||
@ -209,12 +177,7 @@ class Space extends SplObjectStorage
|
||||
return $convergence;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $clustersNumber
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function initializeRandomClusters(int $clustersNumber)
|
||||
private function initializeRandomClusters(int $clustersNumber) : array
|
||||
{
|
||||
$clusters = [];
|
||||
list($min, $max) = $this->getBoundaries();
|
||||
@ -226,12 +189,7 @@ class Space extends SplObjectStorage
|
||||
return $clusters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $clustersNumber
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function initializeKMPPClusters(int $clustersNumber)
|
||||
protected function initializeKMPPClusters(int $clustersNumber) : array
|
||||
{
|
||||
$clusters = [];
|
||||
$this->rewind();
|
||||
|
@ -8,10 +8,6 @@ use Phpml\Dataset\Dataset;
|
||||
|
||||
class RandomSplit extends Split
|
||||
{
|
||||
/**
|
||||
* @param Dataset $dataset
|
||||
* @param float $testSize
|
||||
*/
|
||||
protected function splitDataset(Dataset $dataset, float $testSize)
|
||||
{
|
||||
$samples = $dataset->getSamples();
|
||||
|
@ -29,13 +29,6 @@ abstract class Split
|
||||
*/
|
||||
protected $testLabels = [];
|
||||
|
||||
/**
|
||||
* @param Dataset $dataset
|
||||
* @param float $testSize
|
||||
* @param int $seed
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(Dataset $dataset, float $testSize = 0.3, int $seed = null)
|
||||
{
|
||||
if (0 >= $testSize || 1 <= $testSize) {
|
||||
@ -48,41 +41,26 @@ abstract class Split
|
||||
|
||||
abstract protected function splitDataset(Dataset $dataset, float $testSize);
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTrainSamples()
|
||||
public function getTrainSamples() : array
|
||||
{
|
||||
return $this->trainSamples;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTestSamples()
|
||||
public function getTestSamples() : array
|
||||
{
|
||||
return $this->testSamples;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTrainLabels()
|
||||
public function getTrainLabels() : array
|
||||
{
|
||||
return $this->trainLabels;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTestLabels()
|
||||
public function getTestLabels() : array
|
||||
{
|
||||
return $this->testLabels;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $seed
|
||||
*/
|
||||
protected function seedGenerator(int $seed = null)
|
||||
{
|
||||
if (null === $seed) {
|
||||
|
@ -9,10 +9,6 @@ use Phpml\Dataset\Dataset;
|
||||
|
||||
class StratifiedRandomSplit extends RandomSplit
|
||||
{
|
||||
/**
|
||||
* @param Dataset $dataset
|
||||
* @param float $testSize
|
||||
*/
|
||||
protected function splitDataset(Dataset $dataset, float $testSize)
|
||||
{
|
||||
$datasets = $this->splitByTarget($dataset);
|
||||
@ -23,11 +19,9 @@ class StratifiedRandomSplit extends RandomSplit
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Dataset $dataset
|
||||
*
|
||||
* @return Dataset[]|array
|
||||
*/
|
||||
private function splitByTarget(Dataset $dataset): array
|
||||
private function splitByTarget(Dataset $dataset) : array
|
||||
{
|
||||
$targets = $dataset->getTargets();
|
||||
$samples = $dataset->getSamples();
|
||||
@ -44,13 +38,7 @@ class StratifiedRandomSplit extends RandomSplit
|
||||
return $datasets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $uniqueTargets
|
||||
* @param array $split
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function createDatasets(array $uniqueTargets, array $split): array
|
||||
private function createDatasets(array $uniqueTargets, array $split) : array
|
||||
{
|
||||
$datasets = [];
|
||||
foreach ($uniqueTargets as $target) {
|
||||
|
@ -37,7 +37,7 @@ class ArrayDataset implements Dataset
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSamples(): array
|
||||
public function getSamples() : array
|
||||
{
|
||||
return $this->samples;
|
||||
}
|
||||
@ -45,7 +45,7 @@ class ArrayDataset implements Dataset
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTargets(): array
|
||||
public function getTargets() : array
|
||||
{
|
||||
return $this->targets;
|
||||
}
|
||||
|
@ -14,12 +14,6 @@ class CsvDataset extends ArrayDataset
|
||||
protected $columnNames;
|
||||
|
||||
/**
|
||||
* @param string $filepath
|
||||
* @param int $features
|
||||
* @param bool $headingRow
|
||||
* @param string $delimiter
|
||||
* @param int $maxLineLength
|
||||
*
|
||||
* @throws FileException
|
||||
*/
|
||||
public function __construct(string $filepath, int $features, bool $headingRow = true, string $delimiter = ',', int $maxLineLength = 0)
|
||||
@ -50,10 +44,7 @@ class CsvDataset extends ArrayDataset
|
||||
parent::__construct($samples, $targets);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnNames()
|
||||
public function getColumnNames() : array
|
||||
{
|
||||
return $this->columnNames;
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ interface Dataset
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSamples(): array;
|
||||
public function getSamples() : array;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTargets(): array;
|
||||
public function getTargets() : array;
|
||||
}
|
||||
|
@ -8,11 +8,6 @@ use Phpml\Exception\DatasetException;
|
||||
|
||||
class FilesDataset extends ArrayDataset
|
||||
{
|
||||
/**
|
||||
* @param string $rootPath
|
||||
*
|
||||
* @throws DatasetException
|
||||
*/
|
||||
public function __construct(string $rootPath)
|
||||
{
|
||||
if (!is_dir($rootPath)) {
|
||||
@ -22,9 +17,6 @@ class FilesDataset extends ArrayDataset
|
||||
$this->scanRootPath($rootPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $rootPath
|
||||
*/
|
||||
private function scanRootPath(string $rootPath)
|
||||
{
|
||||
foreach (glob($rootPath.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR) as $dir) {
|
||||
@ -32,9 +24,6 @@ class FilesDataset extends ArrayDataset
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*/
|
||||
private function scanDir(string $dir)
|
||||
{
|
||||
$target = basename($dir);
|
||||
|
@ -90,7 +90,7 @@ abstract class EigenTransformerBase
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function reduce(array $data)
|
||||
protected function reduce(array $data) : array
|
||||
{
|
||||
$m1 = new Matrix($data);
|
||||
$m2 = new Matrix($this->eigVectors);
|
||||
|
@ -44,14 +44,13 @@ class KernelPCA extends PCA
|
||||
* will initialize the algorithm with an RBF kernel having the gamma parameter as 15,0. <br>
|
||||
* This transformation will return the same number of rows with only <i>2</i> columns.
|
||||
*
|
||||
* @param int $kernel
|
||||
* @param float $totalVariance Total variance to be preserved if numFeatures is not given
|
||||
* @param int $numFeatures Number of columns to be returned
|
||||
* @param float $gamma Gamma parameter is used with RBF and Sigmoid kernels
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct(int $kernel = self::KERNEL_RBF, $totalVariance = null, $numFeatures = null, $gamma = null)
|
||||
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)) {
|
||||
@ -69,12 +68,8 @@ class KernelPCA extends PCA
|
||||
* of this data while preserving $totalVariance or $numFeatures. <br>
|
||||
* $data is an n-by-m matrix and returned array is
|
||||
* n-by-k matrix where k <= m
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fit(array $data)
|
||||
public function fit(array $data) : array
|
||||
{
|
||||
$numRows = count($data);
|
||||
$this->data = $data;
|
||||
@ -96,13 +91,8 @@ class KernelPCA extends PCA
|
||||
/**
|
||||
* Calculates similarity matrix by use of selected kernel function<br>
|
||||
* An n-by-m matrix is given and an n-by-n matrix is returned
|
||||
*
|
||||
* @param array $data
|
||||
* @param int $numRows
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function calculateKernelMatrix(array $data, int $numRows)
|
||||
protected function calculateKernelMatrix(array $data, int $numRows) : array
|
||||
{
|
||||
$kernelFunc = $this->getKernel();
|
||||
|
||||
@ -125,13 +115,8 @@ class KernelPCA extends PCA
|
||||
* conversion:
|
||||
*
|
||||
* K′ = K − N.K − K.N + N.K.N where N is n-by-n matrix filled with 1/n
|
||||
*
|
||||
* @param array $matrix
|
||||
* @param int $n
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function centerMatrix(array $matrix, int $n)
|
||||
protected function centerMatrix(array $matrix, int $n) : array
|
||||
{
|
||||
$N = array_fill(0, $n, array_fill(0, $n, 1.0 / $n));
|
||||
$N = new Matrix($N, false);
|
||||
@ -153,11 +138,9 @@ class KernelPCA extends PCA
|
||||
/**
|
||||
* Returns the callable kernel function
|
||||
*
|
||||
* @return \Closure
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getKernel()
|
||||
protected function getKernel(): \Closure
|
||||
{
|
||||
switch ($this->kernel) {
|
||||
case self::KERNEL_LINEAR:
|
||||
@ -194,12 +177,7 @@ class KernelPCA extends PCA
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDistancePairs(array $sample)
|
||||
protected function getDistancePairs(array $sample) : array
|
||||
{
|
||||
$kernel = $this->getKernel();
|
||||
|
||||
@ -211,12 +189,7 @@ class KernelPCA extends PCA
|
||||
return $pairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $pairs
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function projectSample(array $pairs)
|
||||
protected function projectSample(array $pairs) : array
|
||||
{
|
||||
// Normalize eigenvectors by eig = eigVectors / eigValues
|
||||
$func = function ($eigVal, $eigVect) {
|
||||
@ -235,13 +208,9 @@ class KernelPCA extends PCA
|
||||
* Transforms the given sample to a lower dimensional vector by using
|
||||
* the variables obtained during the last run of <code>fit</code>.
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function transform(array $sample)
|
||||
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');
|
||||
|
@ -47,7 +47,7 @@ class LDA extends EigenTransformerBase
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($totalVariance = null, $numFeatures = null)
|
||||
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');
|
||||
@ -69,11 +69,6 @@ class LDA extends EigenTransformerBase
|
||||
|
||||
/**
|
||||
* Trains the algorithm to transform the given data to a lower dimensional space.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $classes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fit(array $data, array $classes) : array
|
||||
{
|
||||
@ -93,12 +88,8 @@ class LDA extends EigenTransformerBase
|
||||
|
||||
/**
|
||||
* Returns unique labels in the dataset
|
||||
*
|
||||
* @param array $classes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getLabels(array $classes): array
|
||||
protected function getLabels(array $classes) : array
|
||||
{
|
||||
$counts = array_count_values($classes);
|
||||
|
||||
@ -108,11 +99,6 @@ class LDA extends EigenTransformerBase
|
||||
/**
|
||||
* Calculates mean of each column for each class and returns
|
||||
* n by m matrix where n is number of labels and m is number of columns
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $classes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function calculateMeans(array $data, array $classes) : array
|
||||
{
|
||||
@ -159,13 +145,8 @@ class LDA extends EigenTransformerBase
|
||||
* Returns in-class scatter matrix for each class, which
|
||||
* is a n by m matrix where n is number of classes and
|
||||
* m is number of columns
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $classes
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
protected function calculateClassVar($data, $classes)
|
||||
protected function calculateClassVar(array $data, array $classes) : Matrix
|
||||
{
|
||||
// s is an n (number of classes) by m (number of column) matrix
|
||||
$s = array_fill(0, count($data[0]), array_fill(0, count($data[0]), 0));
|
||||
@ -187,10 +168,8 @@ class LDA extends EigenTransformerBase
|
||||
* Returns between-class scatter matrix for each class, which
|
||||
* is an n by m matrix where n is number of classes and
|
||||
* m is number of columns
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
protected function calculateClassCov()
|
||||
protected function calculateClassCov() : Matrix
|
||||
{
|
||||
// s is an n (number of classes) by m (number of column) matrix
|
||||
$s = array_fill(0, count($this->overallMean), array_fill(0, count($this->overallMean), 0));
|
||||
@ -207,13 +186,8 @@ class LDA extends EigenTransformerBase
|
||||
|
||||
/**
|
||||
* Returns the result of the calculation (x - m)T.(x - m)
|
||||
*
|
||||
* @param array $row
|
||||
* @param array $means
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
protected function calculateVar(array $row, array $means)
|
||||
protected function calculateVar(array $row, array $means) : Matrix
|
||||
{
|
||||
$x = new Matrix($row, false);
|
||||
$m = new Matrix($means, false);
|
||||
@ -226,13 +200,9 @@ class LDA extends EigenTransformerBase
|
||||
* Transforms the given sample to a lower dimensional vector by using
|
||||
* the eigenVectors obtained in the last run of <code>fit</code>.
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function transform(array $sample)
|
||||
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');
|
||||
|
@ -32,7 +32,7 @@ class PCA extends EigenTransformerBase
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($totalVariance = null, $numFeatures = null)
|
||||
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');
|
||||
@ -57,12 +57,8 @@ class PCA extends EigenTransformerBase
|
||||
* of this data while preserving $totalVariance or $numFeatures. <br>
|
||||
* $data is an n-by-m matrix and returned array is
|
||||
* n-by-k matrix where k <= m
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fit(array $data)
|
||||
public function fit(array $data) : array
|
||||
{
|
||||
$n = count($data[0]);
|
||||
|
||||
@ -77,10 +73,6 @@ class PCA extends EigenTransformerBase
|
||||
return $this->reduce($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param int $n
|
||||
*/
|
||||
protected function calculateMeans(array $data, int $n)
|
||||
{
|
||||
// Calculate means for each dimension
|
||||
@ -94,13 +86,8 @@ class PCA extends EigenTransformerBase
|
||||
/**
|
||||
* Normalization of the data includes subtracting mean from
|
||||
* each dimension therefore dimensions will be centered to zero
|
||||
*
|
||||
* @param array $data
|
||||
* @param int $n
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function normalize(array $data, int $n)
|
||||
protected function normalize(array $data, int $n) : array
|
||||
{
|
||||
if (empty($this->means)) {
|
||||
$this->calculateMeans($data, $n);
|
||||
@ -120,13 +107,9 @@ class PCA extends EigenTransformerBase
|
||||
* Transforms the given sample to a lower dimensional vector by using
|
||||
* the eigenVectors obtained in the last run of <code>fit</code>.
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function transform(array $sample)
|
||||
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');
|
||||
|
@ -6,12 +6,7 @@ namespace Phpml\Exception;
|
||||
|
||||
class DatasetException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return DatasetException
|
||||
*/
|
||||
public static function missingFolder(string $path)
|
||||
public static function missingFolder(string $path) : DatasetException
|
||||
{
|
||||
return new self(sprintf('Dataset root folder "%s" missing.', $path));
|
||||
}
|
||||
|
@ -6,32 +6,17 @@ namespace Phpml\Exception;
|
||||
|
||||
class FileException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @param string $filepath
|
||||
*
|
||||
* @return FileException
|
||||
*/
|
||||
public static function missingFile(string $filepath)
|
||||
public static function missingFile(string $filepath) : FileException
|
||||
{
|
||||
return new self(sprintf('File "%s" missing.', $filepath));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filepath
|
||||
*
|
||||
* @return FileException
|
||||
*/
|
||||
public static function cantOpenFile(string $filepath)
|
||||
public static function cantOpenFile(string $filepath) : FileException
|
||||
{
|
||||
return new self(sprintf('File "%s" can\'t be open.', $filepath));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filepath
|
||||
*
|
||||
* @return FileException
|
||||
*/
|
||||
public static function cantSaveFile(string $filepath)
|
||||
public static function cantSaveFile(string $filepath) : FileException
|
||||
{
|
||||
return new self(sprintf('File "%s" can\'t be saved.', $filepath));
|
||||
}
|
||||
|
@ -6,164 +6,95 @@ namespace Phpml\Exception;
|
||||
|
||||
class InvalidArgumentException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function arraySizeNotMatch()
|
||||
public static function arraySizeNotMatch() : InvalidArgumentException
|
||||
{
|
||||
return new self('Size of given arrays does not match');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function percentNotInRange($name)
|
||||
public static function percentNotInRange($name) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('%s must be between 0.0 and 1.0', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function arrayCantBeEmpty()
|
||||
public static function arrayCantBeEmpty() : InvalidArgumentException
|
||||
{
|
||||
return new self('The array has zero elements');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $minimumSize
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function arraySizeToSmall($minimumSize = 2)
|
||||
public static function arraySizeToSmall(int $minimumSize = 2) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('The array must have at least %d elements', $minimumSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function matrixDimensionsDidNotMatch()
|
||||
public static function matrixDimensionsDidNotMatch() : InvalidArgumentException
|
||||
{
|
||||
return new self('Matrix dimensions did not match');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function inconsistentMatrixSupplied()
|
||||
public static function inconsistentMatrixSupplied() : InvalidArgumentException
|
||||
{
|
||||
return new self('Inconsistent matrix supplied');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function invalidClustersNumber()
|
||||
public static function invalidClustersNumber() : InvalidArgumentException
|
||||
{
|
||||
return new self('Invalid clusters number');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $target
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function invalidTarget($target)
|
||||
public static function invalidTarget($target) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('Target with value "%s" is not part of the accepted classes', $target));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $language
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function invalidStopWordsLanguage(string $language)
|
||||
public static function invalidStopWordsLanguage(string $language) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('Can\'t find "%s" language for StopWords', $language));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function invalidLayerNodeClass()
|
||||
public static function invalidLayerNodeClass() : InvalidArgumentException
|
||||
{
|
||||
return new self('Layer node class must implement Node interface');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function invalidLayersNumber()
|
||||
public static function invalidLayersNumber() : InvalidArgumentException
|
||||
{
|
||||
return new self('Provide at least 1 hidden layer');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function invalidClassesNumber()
|
||||
public static function invalidClassesNumber() : InvalidArgumentException
|
||||
{
|
||||
return new self('Provide at least 2 different classes');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function inconsistentClasses()
|
||||
public static function inconsistentClasses() : InvalidArgumentException
|
||||
{
|
||||
return new self('The provided classes don\'t match the classes provided in the constructor');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $file
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function fileNotFound(string $file)
|
||||
public static function fileNotFound(string $file) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('File "%s" not found', $file));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $file
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function fileNotExecutable(string $file)
|
||||
public static function fileNotExecutable(string $file) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('File "%s" is not executable', $file));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function pathNotFound(string $path)
|
||||
public static function pathNotFound(string $path) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('The specified path "%s" does not exist', $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function pathNotWritable(string $path)
|
||||
public static function pathNotWritable(string $path) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('The specified path "%s" is not writable', $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $operator
|
||||
*
|
||||
* @return InvalidArgumentException
|
||||
*/
|
||||
public static function invalidOperator(string $operator)
|
||||
public static function invalidOperator(string $operator) : InvalidArgumentException
|
||||
{
|
||||
return new self(sprintf('Invalid operator "%s" provided', $operator));
|
||||
}
|
||||
|
@ -6,26 +6,17 @@ namespace Phpml\Exception;
|
||||
|
||||
class MatrixException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @return MatrixException
|
||||
*/
|
||||
public static function notSquareMatrix()
|
||||
public static function notSquareMatrix() : MatrixException
|
||||
{
|
||||
return new self('Matrix is not square matrix');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MatrixException
|
||||
*/
|
||||
public static function columnOutOfRange()
|
||||
public static function columnOutOfRange() : MatrixException
|
||||
{
|
||||
return new self('Column out of range');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MatrixException
|
||||
*/
|
||||
public static function singularMatrix()
|
||||
public static function singularMatrix() : MatrixException
|
||||
{
|
||||
return new self('Matrix is singular');
|
||||
}
|
||||
|
@ -6,10 +6,7 @@ namespace Phpml\Exception;
|
||||
|
||||
class NormalizerException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @return NormalizerException
|
||||
*/
|
||||
public static function unknownNorm()
|
||||
public static function unknownNorm() : NormalizerException
|
||||
{
|
||||
return new self('Unknown norm supplied.');
|
||||
}
|
||||
|
@ -6,22 +6,12 @@ namespace Phpml\Exception;
|
||||
|
||||
class SerializeException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @param string $filepath
|
||||
*
|
||||
* @return SerializeException
|
||||
*/
|
||||
public static function cantUnserialize(string $filepath)
|
||||
public static function cantUnserialize(string $filepath) : SerializeException
|
||||
{
|
||||
return new self(sprintf('"%s" can not be unserialized.', $filepath));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $classname
|
||||
*
|
||||
* @return SerializeException
|
||||
*/
|
||||
public static function cantSerialize(string $classname)
|
||||
public static function cantSerialize(string $classname) : SerializeException
|
||||
{
|
||||
return new self(sprintf('Class "%s" can not be serialized.', $classname));
|
||||
}
|
||||
|
@ -13,32 +13,17 @@ class StopWords
|
||||
*/
|
||||
protected $stopWords;
|
||||
|
||||
/**
|
||||
* @param array $stopWords
|
||||
*/
|
||||
public function __construct(array $stopWords)
|
||||
{
|
||||
$this->stopWords = array_fill_keys($stopWords, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isStopWord(string $token): bool
|
||||
public function isStopWord(string $token) : bool
|
||||
{
|
||||
return isset($this->stopWords[$token]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $language
|
||||
*
|
||||
* @return StopWords
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function factory($language = 'English'): StopWords
|
||||
public static function factory(string $language = 'English') : StopWords
|
||||
{
|
||||
$className = __NAMESPACE__."\\StopWords\\$language";
|
||||
|
||||
|
@ -34,11 +34,6 @@ class TokenCountVectorizer implements Transformer
|
||||
*/
|
||||
private $frequencies;
|
||||
|
||||
/**
|
||||
* @param Tokenizer $tokenizer
|
||||
* @param StopWords $stopWords
|
||||
* @param float $minDF
|
||||
*/
|
||||
public function __construct(Tokenizer $tokenizer, StopWords $stopWords = null, float $minDF = 0.0)
|
||||
{
|
||||
$this->tokenizer = $tokenizer;
|
||||
@ -49,17 +44,11 @@ class TokenCountVectorizer implements Transformer
|
||||
$this->frequencies = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
*/
|
||||
public function fit(array $samples)
|
||||
{
|
||||
$this->buildVocabulary($samples);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
*/
|
||||
public function transform(array &$samples)
|
||||
{
|
||||
foreach ($samples as &$sample) {
|
||||
@ -69,17 +58,11 @@ class TokenCountVectorizer implements Transformer
|
||||
$this->checkDocumentFrequency($samples);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getVocabulary()
|
||||
public function getVocabulary() : array
|
||||
{
|
||||
return array_flip($this->vocabulary);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
*/
|
||||
private function buildVocabulary(array &$samples)
|
||||
{
|
||||
foreach ($samples as $index => $sample) {
|
||||
@ -90,9 +73,6 @@ class TokenCountVectorizer implements Transformer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sample
|
||||
*/
|
||||
private function transformSample(string &$sample)
|
||||
{
|
||||
$counts = [];
|
||||
@ -122,8 +102,6 @@ class TokenCountVectorizer implements Transformer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*
|
||||
* @return int|bool
|
||||
*/
|
||||
private function getTokenIndex(string $token)
|
||||
@ -135,9 +113,6 @@ class TokenCountVectorizer implements Transformer
|
||||
return $this->vocabulary[$token] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*/
|
||||
private function addTokenToVocabulary(string $token)
|
||||
{
|
||||
if ($this->isStopWord($token)) {
|
||||
@ -149,19 +124,11 @@ class TokenCountVectorizer implements Transformer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isStopWord(string $token): bool
|
||||
{
|
||||
return $this->stopWords && $this->stopWords->isStopWord($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*/
|
||||
private function updateFrequency(string $token)
|
||||
{
|
||||
if (!isset($this->frequencies[$token])) {
|
||||
@ -171,9 +138,6 @@ class TokenCountVectorizer implements Transformer
|
||||
++$this->frequencies[$token];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
*/
|
||||
private function checkDocumentFrequency(array &$samples)
|
||||
{
|
||||
if ($this->minDF > 0) {
|
||||
@ -184,10 +148,6 @@ class TokenCountVectorizer implements Transformer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
* @param array $beyondMinimum
|
||||
*/
|
||||
private function resetBeyondMinimum(array &$sample, array $beyondMinimum)
|
||||
{
|
||||
foreach ($beyondMinimum as $index) {
|
||||
@ -195,12 +155,7 @@ class TokenCountVectorizer implements Transformer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $samplesCount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getBeyondMinimumIndexes(int $samplesCount)
|
||||
private function getBeyondMinimumIndexes(int $samplesCount) : array
|
||||
{
|
||||
$indexes = [];
|
||||
foreach ($this->frequencies as $token => $frequency) {
|
||||
|
@ -27,9 +27,6 @@ trait OneVsRest
|
||||
|
||||
/**
|
||||
* Train a binary classifier in the OvR style
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
public function train(array $samples, array $targets)
|
||||
{
|
||||
@ -39,13 +36,6 @@ trait OneVsRest
|
||||
$this->trainBylabel($samples, $targets);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param array $allLabels All training set labels
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function trainByLabel(array $samples, array $targets, array $allLabels = [])
|
||||
{
|
||||
// Overwrites the current value if it exist. $allLabels must be provided for each partialTrain run.
|
||||
@ -122,12 +112,11 @@ trait OneVsRest
|
||||
* $targets is not passed by reference nor contains objects so this method
|
||||
* changes will not affect the caller $targets array.
|
||||
*
|
||||
* @param array $targets
|
||||
* @param mixed $label
|
||||
*
|
||||
* @return array Binarized targets and target's labels
|
||||
*/
|
||||
private function binarizeTargets($targets, $label)
|
||||
private function binarizeTargets(array $targets, $label) : array
|
||||
{
|
||||
$notLabel = "not_$label";
|
||||
foreach ($targets as $key => $target) {
|
||||
@ -140,8 +129,6 @@ trait OneVsRest
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function predictSample(array $sample)
|
||||
@ -163,10 +150,6 @@ trait OneVsRest
|
||||
|
||||
/**
|
||||
* Each classifier should implement this method instead of train(samples, targets)
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param array $labels
|
||||
*/
|
||||
abstract protected function trainBinary(array $samples, array $targets, array $labels);
|
||||
|
||||
@ -181,9 +164,6 @@ trait OneVsRest
|
||||
* Each classifier that make use of OvR approach should be able to
|
||||
* return a probability for a sample to belong to the given label.
|
||||
*
|
||||
* @param array $sample
|
||||
* @param string $label
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function predictProbability(array $sample, string $label);
|
||||
@ -191,8 +171,6 @@ trait OneVsRest
|
||||
/**
|
||||
* Each classifier should implement this method instead of predictSample()
|
||||
*
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function predictSampleBinary(array $sample);
|
||||
|
@ -20,11 +20,10 @@ class ConjugateGradient extends GD
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param \Closure $gradientCb
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function runOptimization(array $samples, array $targets, \Closure $gradientCb)
|
||||
public function runOptimization(array $samples, array $targets, \Closure $gradientCb) : array
|
||||
{
|
||||
$this->samples = $samples;
|
||||
$this->targets = $targets;
|
||||
@ -65,12 +64,8 @@ class ConjugateGradient extends GD
|
||||
/**
|
||||
* Executes the callback function for the problem and returns
|
||||
* sum of the gradient for all samples & targets.
|
||||
*
|
||||
* @param array $theta
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function gradient(array $theta)
|
||||
protected function gradient(array $theta) : array
|
||||
{
|
||||
list(, $gradient) = parent::gradient($theta);
|
||||
|
||||
@ -79,12 +74,8 @@ class ConjugateGradient extends GD
|
||||
|
||||
/**
|
||||
* Returns the value of f(x) for given solution
|
||||
*
|
||||
* @param array $theta
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function cost(array $theta)
|
||||
protected function cost(array $theta) : float
|
||||
{
|
||||
list($cost) = parent::gradient($theta);
|
||||
|
||||
@ -104,12 +95,8 @@ class ConjugateGradient extends GD
|
||||
* b) Probe a larger alpha (0.01) and calculate cost function
|
||||
* b-1) If cost function decreases, continue enlarging alpha
|
||||
* b-2) If cost function increases, take the midpoint and try again
|
||||
*
|
||||
* @param float $d
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function getAlpha(float $d)
|
||||
protected function getAlpha(float $d) : float
|
||||
{
|
||||
$small = 0.0001 * $d;
|
||||
$large = 0.01 * $d;
|
||||
@ -153,13 +140,8 @@ class ConjugateGradient extends GD
|
||||
* gradient direction.
|
||||
*
|
||||
* θ(k+1) = θ(k) + α.d
|
||||
*
|
||||
* @param float $alpha
|
||||
* @param array $d
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getNewTheta(float $alpha, array $d)
|
||||
protected function getNewTheta(float $alpha, array $d) : array
|
||||
{
|
||||
$theta = $this->theta;
|
||||
|
||||
@ -187,12 +169,8 @@ class ConjugateGradient extends GD
|
||||
*
|
||||
* See:
|
||||
* R. Fletcher and C. M. Reeves, "Function minimization by conjugate gradients", Comput. J. 7 (1964), 149–154.
|
||||
*
|
||||
* @param array $newTheta
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function getBeta(array $newTheta)
|
||||
protected function getBeta(array $newTheta) : float
|
||||
{
|
||||
$dNew = array_sum($this->gradient($newTheta));
|
||||
$dOld = array_sum($this->gradient($this->theta)) + 1e-100;
|
||||
@ -204,14 +182,8 @@ class ConjugateGradient extends GD
|
||||
* Calculates the new conjugate direction
|
||||
*
|
||||
* d(k+1) =–∇f(x(k+1)) + β(k).d(k)
|
||||
*
|
||||
* @param array $theta
|
||||
* @param float $beta
|
||||
* @param array $d
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getNewDirection(array $theta, float $beta, array $d)
|
||||
protected function getNewDirection(array $theta, float $beta, array $d) : array
|
||||
{
|
||||
$grad = $this->gradient($theta);
|
||||
|
||||
@ -227,13 +199,8 @@ class mp
|
||||
{
|
||||
/**
|
||||
* Element-wise <b>multiplication</b> of two vectors of the same size
|
||||
*
|
||||
* @param array $m1
|
||||
* @param array $m2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function mul(array $m1, array $m2)
|
||||
public static function mul(array $m1, array $m2) : array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($m1 as $i => $val) {
|
||||
@ -245,13 +212,8 @@ class mp
|
||||
|
||||
/**
|
||||
* Element-wise <b>division</b> of two vectors of the same size
|
||||
*
|
||||
* @param array $m1
|
||||
* @param array $m2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function div(array $m1, array $m2)
|
||||
public static function div(array $m1, array $m2) : array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($m1 as $i => $val) {
|
||||
@ -263,14 +225,8 @@ class mp
|
||||
|
||||
/**
|
||||
* Element-wise <b>addition</b> of two vectors of the same size
|
||||
*
|
||||
* @param array $m1
|
||||
* @param array $m2
|
||||
* @param int $mag
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function add(array $m1, array $m2, int $mag = 1)
|
||||
public static function add(array $m1, array $m2, int $mag = 1) : array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($m1 as $i => $val) {
|
||||
@ -282,26 +238,16 @@ class mp
|
||||
|
||||
/**
|
||||
* Element-wise <b>subtraction</b> of two vectors of the same size
|
||||
*
|
||||
* @param array $m1
|
||||
* @param array $m2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function sub(array $m1, array $m2)
|
||||
public static function sub(array $m1, array $m2) : array
|
||||
{
|
||||
return self::add($m1, $m2, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Element-wise <b>multiplication</b> of a vector with a scalar
|
||||
*
|
||||
* @param array $m1
|
||||
* @param float $m2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function muls(array $m1, float $m2)
|
||||
public static function muls(array $m1, float $m2) : array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($m1 as $val) {
|
||||
@ -313,13 +259,8 @@ class mp
|
||||
|
||||
/**
|
||||
* Element-wise <b>division</b> of a vector with a scalar
|
||||
*
|
||||
* @param array $m1
|
||||
* @param float $m2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function divs(array $m1, float $m2)
|
||||
public static function divs(array $m1, float $m2) : array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($m1 as $val) {
|
||||
@ -331,14 +272,8 @@ class mp
|
||||
|
||||
/**
|
||||
* Element-wise <b>addition</b> of a vector with a scalar
|
||||
*
|
||||
* @param array $m1
|
||||
* @param float $m2
|
||||
* @param int $mag
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function adds(array $m1, float $m2, int $mag = 1)
|
||||
public static function adds(array $m1, float $m2, int $mag = 1) : array
|
||||
{
|
||||
$res = [];
|
||||
foreach ($m1 as $val) {
|
||||
@ -350,13 +285,8 @@ class mp
|
||||
|
||||
/**
|
||||
* Element-wise <b>subtraction</b> of a vector with a scalar
|
||||
*
|
||||
* @param array $m1
|
||||
* @param float $m2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function subs(array $m1, float $m2)
|
||||
public static function subs(array $m1, float $m2) : array
|
||||
{
|
||||
return self::adds($m1, $m2, -1);
|
||||
}
|
||||
|
@ -17,14 +17,7 @@ class GD extends StochasticGD
|
||||
*/
|
||||
protected $sampleCount = null;
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param \Closure $gradientCb
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function runOptimization(array $samples, array $targets, \Closure $gradientCb)
|
||||
public function runOptimization(array $samples, array $targets, \Closure $gradientCb) : array
|
||||
{
|
||||
$this->samples = $samples;
|
||||
$this->targets = $targets;
|
||||
@ -57,12 +50,8 @@ class GD extends StochasticGD
|
||||
/**
|
||||
* Calculates gradient, cost function and penalty term for each sample
|
||||
* then returns them as an array of values
|
||||
*
|
||||
* @param array $theta
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function gradient(array $theta)
|
||||
protected function gradient(array $theta) : array
|
||||
{
|
||||
$costs = [];
|
||||
$gradient = [];
|
||||
@ -84,10 +73,6 @@ class GD extends StochasticGD
|
||||
return [$costs, $gradient, $totalPenalty];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $updates
|
||||
* @param float $penalty
|
||||
*/
|
||||
protected function updateWeightsWithUpdates(array $updates, float $penalty)
|
||||
{
|
||||
// Updates all weights at once
|
||||
@ -110,8 +95,6 @@ class GD extends StochasticGD
|
||||
|
||||
/**
|
||||
* Clears the optimizer internal vars after the optimization process.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function clear()
|
||||
{
|
||||
|
@ -22,8 +22,6 @@ abstract class Optimizer
|
||||
|
||||
/**
|
||||
* Inits a new instance of Optimizer for the given number of dimensions
|
||||
*
|
||||
* @param int $dimensions
|
||||
*/
|
||||
public function __construct(int $dimensions)
|
||||
{
|
||||
@ -39,8 +37,6 @@ abstract class Optimizer
|
||||
/**
|
||||
* Sets the weights manually
|
||||
*
|
||||
* @param array $theta
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws \Exception
|
||||
@ -59,10 +55,6 @@ abstract class Optimizer
|
||||
/**
|
||||
* Executes the optimization with the given samples & targets
|
||||
* and returns the weights
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param \Closure $gradientCb
|
||||
*/
|
||||
abstract public function runOptimization(array $samples, array $targets, \Closure $gradientCb);
|
||||
}
|
||||
|
@ -76,8 +76,6 @@ class StochasticGD extends Optimizer
|
||||
|
||||
/**
|
||||
* Initializes the SGD optimizer for the given number of dimensions
|
||||
*
|
||||
* @param int $dimensions
|
||||
*/
|
||||
public function __construct(int $dimensions)
|
||||
{
|
||||
@ -94,8 +92,6 @@ class StochasticGD extends Optimizer
|
||||
* If change in the theta is less than given value then the
|
||||
* algorithm will stop training
|
||||
*
|
||||
* @param float $threshold
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setChangeThreshold(float $threshold = 1e-5)
|
||||
@ -109,8 +105,6 @@ class StochasticGD extends Optimizer
|
||||
* Enable/Disable early stopping by checking at each iteration
|
||||
* whether changes in theta or cost value are not large enough
|
||||
*
|
||||
* @param bool $enable
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setEarlyStop(bool $enable = true)
|
||||
@ -121,8 +115,6 @@ class StochasticGD extends Optimizer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $learningRate
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLearningRate(float $learningRate)
|
||||
@ -133,8 +125,6 @@ class StochasticGD extends Optimizer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $maxIterations
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMaxIterations(int $maxIterations)
|
||||
@ -150,14 +140,8 @@ class StochasticGD extends Optimizer
|
||||
*
|
||||
* The cost function to minimize and the gradient of the function are to be
|
||||
* handled by the callback function provided as the third parameter of the method.
|
||||
*
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param \Closure $gradientCb
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function runOptimization(array $samples, array $targets, \Closure $gradientCb)
|
||||
public function runOptimization(array $samples, array $targets, \Closure $gradientCb) : array
|
||||
{
|
||||
$this->samples = $samples;
|
||||
$this->targets = $targets;
|
||||
@ -197,10 +181,7 @@ class StochasticGD extends Optimizer
|
||||
return $this->theta = $bestTheta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
protected function updateTheta()
|
||||
protected function updateTheta() : float
|
||||
{
|
||||
$jValue = 0.0;
|
||||
$theta = $this->theta;
|
||||
@ -231,12 +212,8 @@ class StochasticGD extends Optimizer
|
||||
/**
|
||||
* Checks if the optimization is not effective enough and can be stopped
|
||||
* in case large enough changes in the solution do not happen
|
||||
*
|
||||
* @param array $oldTheta
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function earlyStop($oldTheta)
|
||||
protected function earlyStop(array $oldTheta): bool
|
||||
{
|
||||
// Check for early stop: No change larger than threshold (default 1e-5)
|
||||
$diff = array_map(
|
||||
@ -263,18 +240,14 @@ class StochasticGD extends Optimizer
|
||||
/**
|
||||
* Returns the list of cost values for each iteration executed in
|
||||
* last run of the optimization
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCostValues()
|
||||
public function getCostValues() : array
|
||||
{
|
||||
return $this->costValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the optimizer internal vars after the optimization process.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function clear()
|
||||
{
|
||||
|
@ -9,12 +9,6 @@ use Phpml\Exception\InvalidArgumentException;
|
||||
class Comparison
|
||||
{
|
||||
/**
|
||||
* @param mixed $a
|
||||
* @param mixed $b
|
||||
* @param string $operator
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function compare($a, $b, string $operator): bool
|
||||
|
@ -9,8 +9,6 @@ interface Distance
|
||||
/**
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function distance(array $a, array $b): float;
|
||||
public function distance(array $a, array $b) : float;
|
||||
}
|
||||
|
@ -10,14 +10,9 @@ use Phpml\Math\Distance;
|
||||
class Chebyshev implements Distance
|
||||
{
|
||||
/**
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function distance(array $a, array $b): float
|
||||
public function distance(array $a, array $b) : float
|
||||
{
|
||||
if (count($a) !== count($b)) {
|
||||
throw InvalidArgumentException::arraySizeNotMatch();
|
||||
|
@ -10,14 +10,9 @@ use Phpml\Math\Distance;
|
||||
class Euclidean implements Distance
|
||||
{
|
||||
/**
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function distance(array $a, array $b): float
|
||||
public function distance(array $a, array $b) : float
|
||||
{
|
||||
if (count($a) !== count($b)) {
|
||||
throw InvalidArgumentException::arraySizeNotMatch();
|
||||
@ -34,13 +29,8 @@ class Euclidean implements Distance
|
||||
|
||||
/**
|
||||
* Square of Euclidean distance
|
||||
*
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function sqDistance(array $a, array $b): float
|
||||
public function sqDistance(array $a, array $b) : float
|
||||
{
|
||||
return $this->distance($a, $b) ** 2;
|
||||
}
|
||||
|
@ -10,14 +10,9 @@ use Phpml\Math\Distance;
|
||||
class Manhattan implements Distance
|
||||
{
|
||||
/**
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function distance(array $a, array $b): float
|
||||
public function distance(array $a, array $b) : float
|
||||
{
|
||||
if (count($a) !== count($b)) {
|
||||
throw InvalidArgumentException::arraySizeNotMatch();
|
||||
|
@ -14,23 +14,15 @@ class Minkowski implements Distance
|
||||
*/
|
||||
private $lambda;
|
||||
|
||||
/**
|
||||
* @param float $lambda
|
||||
*/
|
||||
public function __construct(float $lambda = 3.0)
|
||||
{
|
||||
$this->lambda = $lambda;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function distance(array $a, array $b): float
|
||||
public function distance(array $a, array $b) : float
|
||||
{
|
||||
if (count($a) !== count($b)) {
|
||||
throw InvalidArgumentException::arraySizeNotMatch();
|
||||
|
@ -14,9 +14,6 @@ class RBF implements Kernel
|
||||
*/
|
||||
private $gamma;
|
||||
|
||||
/**
|
||||
* @param float $gamma
|
||||
*/
|
||||
public function __construct(float $gamma)
|
||||
{
|
||||
$this->gamma = $gamma;
|
||||
@ -25,8 +22,6 @@ class RBF implements Kernel
|
||||
/**
|
||||
* @param array $a
|
||||
* @param array $b
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function compute($a, $b)
|
||||
{
|
||||
|
@ -835,7 +835,6 @@ class EigenvalueDecomposition
|
||||
/**
|
||||
* Return the eigenvector matrix
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEigenvectors()
|
||||
|
@ -2,25 +2,25 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @package JAMA
|
||||
* @package JAMA
|
||||
*
|
||||
* For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
|
||||
* unit lower triangular matrix L, an n-by-n upper triangular matrix U,
|
||||
* and a permutation vector piv of length m so that A(piv,:) = L*U.
|
||||
* If m < n, then L is m-by-m and U is m-by-n.
|
||||
* For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
|
||||
* unit lower triangular matrix L, an n-by-n upper triangular matrix U,
|
||||
* and a permutation vector piv of length m so that A(piv,:) = L*U.
|
||||
* If m < n, then L is m-by-m and U is m-by-n.
|
||||
*
|
||||
* The LU decompostion with pivoting always exists, even if the matrix is
|
||||
* singular, so the constructor will never fail. The primary use of the
|
||||
* LU decomposition is in the solution of square systems of simultaneous
|
||||
* linear equations. This will fail if isNonsingular() returns false.
|
||||
* The LU decompostion with pivoting always exists, even if the matrix is
|
||||
* singular, so the constructor will never fail. The primary use of the
|
||||
* LU decomposition is in the solution of square systems of simultaneous
|
||||
* linear equations. This will fail if isNonsingular() returns false.
|
||||
*
|
||||
* @author Paul Meagher
|
||||
* @author Bartosz Matosiuk
|
||||
* @author Michael Bommarito
|
||||
* @author Paul Meagher
|
||||
* @author Bartosz Matosiuk
|
||||
* @author Michael Bommarito
|
||||
*
|
||||
* @version 1.1
|
||||
* @version 1.1
|
||||
*
|
||||
* @license PHP v3.0
|
||||
* @license PHP v3.0
|
||||
*
|
||||
* Slightly changed to adapt the original code to PHP-ML library
|
||||
* @date 2017/04/24
|
||||
@ -30,43 +30,43 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Math\LinearAlgebra;
|
||||
|
||||
use Phpml\Math\Matrix;
|
||||
use Phpml\Exception\MatrixException;
|
||||
use Phpml\Math\Matrix;
|
||||
|
||||
class LUDecomposition
|
||||
{
|
||||
/**
|
||||
* Decomposition storage
|
||||
* Decomposition storage
|
||||
*
|
||||
* @var array
|
||||
* @var array
|
||||
*/
|
||||
private $LU = [];
|
||||
|
||||
/**
|
||||
* Row dimension.
|
||||
* Row dimension.
|
||||
*
|
||||
* @var int
|
||||
* @var int
|
||||
*/
|
||||
private $m;
|
||||
|
||||
/**
|
||||
* Column dimension.
|
||||
* Column dimension.
|
||||
*
|
||||
* @var int
|
||||
* @var int
|
||||
*/
|
||||
private $n;
|
||||
|
||||
/**
|
||||
* Pivot sign.
|
||||
* Pivot sign.
|
||||
*
|
||||
* @var int
|
||||
* @var int
|
||||
*/
|
||||
private $pivsign;
|
||||
|
||||
/**
|
||||
* Internal storage of pivot vector.
|
||||
* Internal storage of pivot vector.
|
||||
*
|
||||
* @var array
|
||||
* @var array
|
||||
*/
|
||||
private $piv = [];
|
||||
|
||||
@ -142,7 +142,7 @@ class LUDecomposition
|
||||
*
|
||||
* @return Matrix Lower triangular factor
|
||||
*/
|
||||
public function getL()
|
||||
public function getL() : Matrix
|
||||
{
|
||||
$L = [];
|
||||
for ($i = 0; $i < $this->m; ++$i) {
|
||||
@ -165,7 +165,7 @@ class LUDecomposition
|
||||
*
|
||||
* @return Matrix Upper triangular factor
|
||||
*/
|
||||
public function getU()
|
||||
public function getU() : Matrix
|
||||
{
|
||||
$U = [];
|
||||
for ($i = 0; $i < $this->n; ++$i) {
|
||||
@ -186,7 +186,7 @@ class LUDecomposition
|
||||
*
|
||||
* @return array Pivot vector
|
||||
*/
|
||||
public function getPivot()
|
||||
public function getPivot() : array
|
||||
{
|
||||
return $this->piv;
|
||||
}
|
||||
@ -247,7 +247,7 @@ class LUDecomposition
|
||||
*
|
||||
* @throws MatrixException
|
||||
*/
|
||||
public function solve(Matrix $B)
|
||||
public function solve(Matrix $B) : array
|
||||
{
|
||||
if ($B->getRows() != $this->m) {
|
||||
throw MatrixException::notSquareMatrix();
|
||||
@ -283,15 +283,7 @@ class LUDecomposition
|
||||
return $X;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $matrix
|
||||
* @param array $RL
|
||||
* @param int $j0
|
||||
* @param int $jF
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getSubMatrix(array $matrix, array $RL, int $j0, int $jF)
|
||||
protected function getSubMatrix(array $matrix, array $RL, int $j0, int $jF) : array
|
||||
{
|
||||
$m = count($RL);
|
||||
$n = $jF - $j0;
|
||||
|
@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Math;
|
||||
|
||||
use Phpml\Math\LinearAlgebra\LUDecomposition;
|
||||
use Phpml\Exception\InvalidArgumentException;
|
||||
use Phpml\Exception\MatrixException;
|
||||
use Phpml\Math\LinearAlgebra\LUDecomposition;
|
||||
|
||||
class Matrix
|
||||
{
|
||||
@ -31,9 +31,6 @@ class Matrix
|
||||
private $determinant;
|
||||
|
||||
/**
|
||||
* @param array $matrix
|
||||
* @param bool $validate
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(array $matrix, bool $validate = true)
|
||||
@ -59,12 +56,7 @@ class Matrix
|
||||
$this->matrix = $matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
public static function fromFlatArray(array $array)
|
||||
public static function fromFlatArray(array $array) : Matrix
|
||||
{
|
||||
$matrix = [];
|
||||
foreach ($array as $value) {
|
||||
@ -74,46 +66,30 @@ class Matrix
|
||||
return new self($matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
public function toArray() : array
|
||||
{
|
||||
return $this->matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function toScalar()
|
||||
public function toScalar() : float
|
||||
{
|
||||
return $this->matrix[0][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getRows()
|
||||
public function getRows(): int
|
||||
{
|
||||
return $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getColumns()
|
||||
public function getColumns(): int
|
||||
{
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws MatrixException
|
||||
*/
|
||||
public function getColumnValues($column)
|
||||
public function getColumnValues($column) : array
|
||||
{
|
||||
if ($column >= $this->columns) {
|
||||
throw MatrixException::columnOutOfRange();
|
||||
@ -142,18 +118,12 @@ class Matrix
|
||||
return $this->determinant = $lu->det();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSquare()
|
||||
public function isSquare(): bool
|
||||
{
|
||||
return $this->columns === $this->rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Matrix
|
||||
*/
|
||||
public function transpose()
|
||||
public function transpose() : Matrix
|
||||
{
|
||||
if ($this->rows == 1) {
|
||||
$matrix = array_map(function ($el) {
|
||||
@ -166,14 +136,7 @@ class Matrix
|
||||
return new self($matrix, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Matrix $matrix
|
||||
*
|
||||
* @return Matrix
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function multiply(Matrix $matrix)
|
||||
public function multiply(Matrix $matrix) : Matrix
|
||||
{
|
||||
if ($this->columns != $matrix->getRows()) {
|
||||
throw InvalidArgumentException::inconsistentMatrixSupplied();
|
||||
@ -194,12 +157,7 @@ class Matrix
|
||||
return new self($product, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
public function divideByScalar($value)
|
||||
public function divideByScalar($value) : Matrix
|
||||
{
|
||||
$newMatrix = [];
|
||||
for ($i = 0; $i < $this->rows; ++$i) {
|
||||
@ -211,12 +169,7 @@ class Matrix
|
||||
return new self($newMatrix, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
public function multiplyByScalar($value)
|
||||
public function multiplyByScalar($value) : Matrix
|
||||
{
|
||||
$newMatrix = [];
|
||||
for ($i = 0; $i < $this->rows; ++$i) {
|
||||
@ -230,37 +183,24 @@ class Matrix
|
||||
|
||||
/**
|
||||
* Element-wise addition of the matrix with another one
|
||||
*
|
||||
* @param Matrix $other
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
public function add(Matrix $other)
|
||||
public function add(Matrix $other) : Matrix
|
||||
{
|
||||
return $this->_add($other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Element-wise subtracting of another matrix from this one
|
||||
*
|
||||
* @param Matrix $other
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
public function subtract(Matrix $other)
|
||||
public function subtract(Matrix $other) : Matrix
|
||||
{
|
||||
return $this->_add($other, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Element-wise addition or substraction depending on the given sign parameter
|
||||
*
|
||||
* @param Matrix $other
|
||||
* @param int $sign
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
protected function _add(Matrix $other, $sign = 1)
|
||||
protected function _add(Matrix $other, int $sign = 1) : Matrix
|
||||
{
|
||||
$a1 = $this->toArray();
|
||||
$a2 = $other->toArray();
|
||||
@ -275,12 +215,7 @@ class Matrix
|
||||
return new self($newMatrix, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Matrix
|
||||
*
|
||||
* @throws MatrixException
|
||||
*/
|
||||
public function inverse()
|
||||
public function inverse() : Matrix
|
||||
{
|
||||
if (!$this->isSquare()) {
|
||||
throw MatrixException::notSquareMatrix();
|
||||
@ -295,10 +230,8 @@ class Matrix
|
||||
|
||||
/**
|
||||
* Returns diagonal identity matrix of the same size of this matrix
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
protected function getIdentity()
|
||||
protected function getIdentity() : Matrix
|
||||
{
|
||||
$array = array_fill(0, $this->rows, array_fill(0, $this->columns, 0));
|
||||
for ($i = 0; $i < $this->rows; ++$i) {
|
||||
@ -308,13 +241,7 @@ class Matrix
|
||||
return new self($array, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $row
|
||||
* @param int $column
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
public function crossOut(int $row, int $column)
|
||||
public function crossOut(int $row, int $column) : Matrix
|
||||
{
|
||||
$newMatrix = [];
|
||||
$r = 0;
|
||||
@ -334,9 +261,6 @@ class Matrix
|
||||
return new self($newMatrix, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSingular() : bool
|
||||
{
|
||||
return 0 == $this->getDeterminant();
|
||||
@ -344,12 +268,8 @@ class Matrix
|
||||
|
||||
/**
|
||||
* Returns the transpose of given array
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function transposeArray(array $array)
|
||||
public static function transposeArray(array $array) : array
|
||||
{
|
||||
return (new self($array, false))->transpose()->toArray();
|
||||
}
|
||||
@ -357,13 +277,8 @@ class Matrix
|
||||
/**
|
||||
* Returns the dot product of two arrays<br>
|
||||
* Matrix::dot(x, y) ==> x.y'
|
||||
*
|
||||
* @param array $array1
|
||||
* @param array $array2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function dot(array $array1, array $array2)
|
||||
public static function dot(array $array1, array $array2) : array
|
||||
{
|
||||
$m1 = new self($array1, false);
|
||||
$m2 = new self($array2, false);
|
||||
|
@ -21,11 +21,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* Creates the union of A and B.
|
||||
*
|
||||
* @param Set $a
|
||||
* @param Set $b
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public static function union(Set $a, Set $b) : Set
|
||||
{
|
||||
@ -34,11 +29,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* Creates the intersection of A and B.
|
||||
*
|
||||
* @param Set $a
|
||||
* @param Set $b
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public static function intersection(Set $a, Set $b) : Set
|
||||
{
|
||||
@ -47,11 +37,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* Creates the difference of A and B.
|
||||
*
|
||||
* @param Set $a
|
||||
* @param Set $b
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public static function difference(Set $a, Set $b) : Set
|
||||
{
|
||||
@ -61,9 +46,6 @@ class Set implements \IteratorAggregate
|
||||
/**
|
||||
* Creates the Cartesian product of A and B.
|
||||
*
|
||||
* @param Set $a
|
||||
* @param Set $b
|
||||
*
|
||||
* @return Set[]
|
||||
*/
|
||||
public static function cartesian(Set $a, Set $b) : array
|
||||
@ -82,8 +64,6 @@ class Set implements \IteratorAggregate
|
||||
/**
|
||||
* Creates the power set of A.
|
||||
*
|
||||
* @param Set $a
|
||||
*
|
||||
* @return Set[]
|
||||
*/
|
||||
public static function power(Set $a) : array
|
||||
@ -115,8 +95,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* @param string|int|float $element
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public function add($element) : Set
|
||||
{
|
||||
@ -125,8 +103,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* @param string[]|int[]|float[] $elements
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public function addAll(array $elements) : Set
|
||||
{
|
||||
@ -137,8 +113,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* @param string|int|float $element
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public function remove($element) : Set
|
||||
{
|
||||
@ -147,8 +121,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* @param string[]|int[]|float[] $elements
|
||||
*
|
||||
* @return Set
|
||||
*/
|
||||
public function removeAll(array $elements) : Set
|
||||
{
|
||||
@ -159,8 +131,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* @param string|int|float $element
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($element) : bool
|
||||
{
|
||||
@ -169,8 +139,6 @@ class Set implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* @param string[]|int[]|float[] $elements
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function containsAll(array $elements) : bool
|
||||
{
|
||||
@ -185,25 +153,16 @@ class Set implements \IteratorAggregate
|
||||
return $this->elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator() : \ArrayIterator
|
||||
{
|
||||
return new \ArrayIterator($this->elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty() : bool
|
||||
{
|
||||
return $this->cardinality() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function cardinality() : int
|
||||
{
|
||||
return count($this->elements);
|
||||
|
@ -12,11 +12,9 @@ class Correlation
|
||||
* @param array|int[]|float[] $x
|
||||
* @param array|int[]|float[] $y
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function pearson(array $x, array $y)
|
||||
public static function pearson(array $x, array $y) : float
|
||||
{
|
||||
if (count($x) !== count($y)) {
|
||||
throw InvalidArgumentException::arraySizeNotMatch();
|
||||
|
@ -11,17 +11,9 @@ class Covariance
|
||||
/**
|
||||
* Calculates covariance from two given arrays, x and y, respectively
|
||||
*
|
||||
* @param array $x
|
||||
* @param array $y
|
||||
* @param bool $sample
|
||||
* @param float $meanX
|
||||
* @param float $meanY
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function fromXYArrays(array $x, array $y, $sample = true, float $meanX = null, float $meanY = null)
|
||||
public static function fromXYArrays(array $x, array $y, bool $sample = true, float $meanX = null, float $meanY = null) : float
|
||||
{
|
||||
if (empty($x) || empty($y)) {
|
||||
throw InvalidArgumentException::arrayCantBeEmpty();
|
||||
@ -56,19 +48,10 @@ class Covariance
|
||||
/**
|
||||
* Calculates covariance of two dimensions, i and k in the given data.
|
||||
*
|
||||
* @param array $data
|
||||
* @param int $i
|
||||
* @param int $k
|
||||
* @param bool $sample
|
||||
* @param float $meanX
|
||||
* @param float $meanY
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function fromDataset(array $data, int $i, int $k, bool $sample = true, float $meanX = null, float $meanY = null)
|
||||
public static function fromDataset(array $data, int $i, int $k, bool $sample = true, float $meanX = null, float $meanY = null) : float
|
||||
{
|
||||
if (empty($data)) {
|
||||
throw InvalidArgumentException::arrayCantBeEmpty();
|
||||
@ -127,12 +110,9 @@ class Covariance
|
||||
/**
|
||||
* Returns the covariance matrix of n-dimensional data
|
||||
*
|
||||
* @param array $data
|
||||
* @param array|null $means
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function covarianceMatrix(array $data, array $means = null)
|
||||
public static function covarianceMatrix(array $data, array $means = null) : array
|
||||
{
|
||||
$n = count($data[0]);
|
||||
|
||||
|
@ -16,10 +16,6 @@ class Gaussian
|
||||
*/
|
||||
protected $std;
|
||||
|
||||
/**
|
||||
* @param float $mean
|
||||
* @param float $std
|
||||
*/
|
||||
public function __construct(float $mean, float $std)
|
||||
{
|
||||
$this->mean = $mean;
|
||||
@ -29,8 +25,6 @@ class Gaussian
|
||||
/**
|
||||
* Returns probability density of the given <i>$value</i>
|
||||
*
|
||||
* @param float $value
|
||||
*
|
||||
* @return float|int
|
||||
*/
|
||||
public function pdf(float $value)
|
||||
@ -46,14 +40,8 @@ class Gaussian
|
||||
/**
|
||||
* Returns probability density value of the given <i>$value</i> based on
|
||||
* given standard deviation and the mean
|
||||
*
|
||||
* @param float $mean
|
||||
* @param float $std
|
||||
* @param float $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function distributionPdf(float $mean, float $std, float $value)
|
||||
public static function distributionPdf(float $mean, float $std, float $value) : float
|
||||
{
|
||||
$normal = new self($mean, $std);
|
||||
|
||||
|
@ -11,11 +11,9 @@ class Mean
|
||||
/**
|
||||
* @param array $numbers
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function arithmetic(array $numbers)
|
||||
public static function arithmetic(array $numbers) : float
|
||||
{
|
||||
self::checkArrayLength($numbers);
|
||||
|
||||
|
@ -10,13 +10,10 @@ class StandardDeviation
|
||||
{
|
||||
/**
|
||||
* @param array|float[] $a
|
||||
* @param bool $sample
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function population(array $a, $sample = true)
|
||||
public static function population(array $a, bool $sample = true) : float
|
||||
{
|
||||
if (empty($a)) {
|
||||
throw InvalidArgumentException::arrayCantBeEmpty();
|
||||
|
@ -31,10 +31,6 @@ class ClassificationReport
|
||||
*/
|
||||
private $average = [];
|
||||
|
||||
/**
|
||||
* @param array $actualLabels
|
||||
* @param array $predictedLabels
|
||||
*/
|
||||
public function __construct(array $actualLabels, array $predictedLabels)
|
||||
{
|
||||
$truePositive = $falsePositive = $falseNegative = $this->support = self::getLabelIndexedArray($actualLabels, $predictedLabels);
|
||||
@ -55,51 +51,31 @@ class ClassificationReport
|
||||
$this->computeAverage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getPrecision()
|
||||
public function getPrecision() : array
|
||||
{
|
||||
return $this->precision;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getRecall()
|
||||
public function getRecall() : array
|
||||
{
|
||||
return $this->recall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getF1score()
|
||||
public function getF1score() : array
|
||||
{
|
||||
return $this->f1score;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getSupport()
|
||||
public function getSupport() : array
|
||||
{
|
||||
return $this->support;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAverage()
|
||||
public function getAverage() : array
|
||||
{
|
||||
return $this->average;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $truePositive
|
||||
* @param array $falsePositive
|
||||
* @param array $falseNegative
|
||||
*/
|
||||
private function computeMetrics(array $truePositive, array $falsePositive, array $falseNegative)
|
||||
{
|
||||
foreach ($truePositive as $label => $tp) {
|
||||
@ -122,9 +98,6 @@ class ClassificationReport
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $truePositive
|
||||
* @param int $falsePositive
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
private function computePrecision(int $truePositive, int $falsePositive)
|
||||
@ -137,9 +110,6 @@ class ClassificationReport
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $truePositive
|
||||
* @param int $falseNegative
|
||||
*
|
||||
* @return float|string
|
||||
*/
|
||||
private function computeRecall(int $truePositive, int $falseNegative)
|
||||
@ -151,13 +121,7 @@ class ClassificationReport
|
||||
return $truePositive / $divider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $precision
|
||||
* @param float $recall
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
private function computeF1Score(float $precision, float $recall): float
|
||||
private function computeF1Score(float $precision, float $recall) : float
|
||||
{
|
||||
if (0 == ($divider = $precision + $recall)) {
|
||||
return 0.0;
|
||||
@ -172,7 +136,7 @@ class ClassificationReport
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function getLabelIndexedArray(array $actualLabels, array $predictedLabels): array
|
||||
private static function getLabelIndexedArray(array $actualLabels, array $predictedLabels) : array
|
||||
{
|
||||
$labels = array_values(array_unique(array_merge($actualLabels, $predictedLabels)));
|
||||
sort($labels);
|
||||
|
@ -13,7 +13,7 @@ class ConfusionMatrix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function compute(array $actualLabels, array $predictedLabels, array $labels = null): array
|
||||
public static function compute(array $actualLabels, array $predictedLabels, array $labels = null) : array
|
||||
{
|
||||
$labels = $labels ? array_flip($labels) : self::getUniqueLabels($actualLabels);
|
||||
$matrix = self::generateMatrixWithZeros($labels);
|
||||
@ -43,7 +43,7 @@ class ConfusionMatrix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function generateMatrixWithZeros(array $labels): array
|
||||
private static function generateMatrixWithZeros(array $labels) : array
|
||||
{
|
||||
$count = count($labels);
|
||||
$matrix = [];
|
||||
@ -60,7 +60,7 @@ class ConfusionMatrix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function getUniqueLabels(array $labels): array
|
||||
private static function getUniqueLabels(array $labels) : array
|
||||
{
|
||||
$labels = array_values(array_unique($labels));
|
||||
sort($labels);
|
||||
|
@ -4,18 +4,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml;
|
||||
|
||||
use Phpml\Exception\SerializeException;
|
||||
use Phpml\Exception\FileException;
|
||||
use Phpml\Exception\SerializeException;
|
||||
|
||||
class ModelManager
|
||||
{
|
||||
/**
|
||||
* @param Estimator $estimator
|
||||
* @param string $filepath
|
||||
*
|
||||
* @throws FileException
|
||||
* @throws SerializeException
|
||||
*/
|
||||
public function saveToFile(Estimator $estimator, string $filepath)
|
||||
{
|
||||
if (!is_writable(dirname($filepath))) {
|
||||
@ -33,14 +26,6 @@ class ModelManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filepath
|
||||
*
|
||||
* @return Estimator
|
||||
*
|
||||
* @throws FileException
|
||||
* @throws SerializeException
|
||||
*/
|
||||
public function restoreFromFile(string $filepath) : Estimator
|
||||
{
|
||||
if (!file_exists($filepath) || !is_readable($filepath)) {
|
||||
|
@ -8,8 +8,6 @@ interface ActivationFunction
|
||||
{
|
||||
/**
|
||||
* @param float|int $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function compute($value): float;
|
||||
public function compute($value) : float;
|
||||
}
|
||||
|
@ -10,10 +10,8 @@ class BinaryStep implements ActivationFunction
|
||||
{
|
||||
/**
|
||||
* @param float|int $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function compute($value): float
|
||||
public function compute($value) : float
|
||||
{
|
||||
return $value >= 0 ? 1.0 : 0.0;
|
||||
}
|
||||
|
@ -10,10 +10,8 @@ class Gaussian implements ActivationFunction
|
||||
{
|
||||
/**
|
||||
* @param float|int $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function compute($value): float
|
||||
public function compute($value) : float
|
||||
{
|
||||
return exp(-pow($value, 2));
|
||||
}
|
||||
|
@ -13,20 +13,15 @@ class HyperbolicTangent implements ActivationFunction
|
||||
*/
|
||||
private $beta;
|
||||
|
||||
/**
|
||||
* @param float $beta
|
||||
*/
|
||||
public function __construct($beta = 1.0)
|
||||
public function __construct(float $beta = 1.0)
|
||||
{
|
||||
$this->beta = $beta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float|int $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function compute($value): float
|
||||
public function compute($value) : float
|
||||
{
|
||||
return tanh($this->beta * $value);
|
||||
}
|
||||
|
@ -13,20 +13,15 @@ class PReLU implements ActivationFunction
|
||||
*/
|
||||
private $beta;
|
||||
|
||||
/**
|
||||
* @param float $beta
|
||||
*/
|
||||
public function __construct($beta = 0.01)
|
||||
public function __construct(float $beta = 0.01)
|
||||
{
|
||||
$this->beta = $beta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float|int $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function compute($value): float
|
||||
public function compute($value) : float
|
||||
{
|
||||
return $value >= 0 ? $value : $this->beta * $value;
|
||||
}
|
||||
|
@ -13,20 +13,15 @@ class Sigmoid implements ActivationFunction
|
||||
*/
|
||||
private $beta;
|
||||
|
||||
/**
|
||||
* @param float $beta
|
||||
*/
|
||||
public function __construct($beta = 1.0)
|
||||
public function __construct(float $beta = 1.0)
|
||||
{
|
||||
$this->beta = $beta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float|int $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function compute($value): float
|
||||
public function compute($value) : float
|
||||
{
|
||||
return 1 / (1 + exp(-$this->beta * $value));
|
||||
}
|
||||
|
@ -13,20 +13,15 @@ class ThresholdedReLU implements ActivationFunction
|
||||
*/
|
||||
private $theta;
|
||||
|
||||
/**
|
||||
* @param float $theta
|
||||
*/
|
||||
public function __construct($theta = 1.0)
|
||||
public function __construct(float $theta = 1.0)
|
||||
{
|
||||
$this->theta = $theta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float|int $value
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function compute($value): float
|
||||
public function compute($value) : float
|
||||
{
|
||||
return $value > $this->theta ? $value : 0.0;
|
||||
}
|
||||
|
@ -15,10 +15,6 @@ class Layer
|
||||
private $nodes = [];
|
||||
|
||||
/**
|
||||
* @param int $nodesNumber
|
||||
* @param string $nodeClass
|
||||
* @param ActivationFunction|null $activationFunction
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(int $nodesNumber = 0, string $nodeClass = Neuron::class, ActivationFunction $activationFunction = null)
|
||||
@ -33,7 +29,6 @@ class Layer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $nodeClass
|
||||
* @param ActivationFunction|null $activationFunction
|
||||
*
|
||||
* @return Neuron
|
||||
@ -47,9 +42,6 @@ class Layer
|
||||
return new $nodeClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
*/
|
||||
public function addNode(Node $node)
|
||||
{
|
||||
$this->nodes[] = $node;
|
||||
@ -58,7 +50,7 @@ class Layer
|
||||
/**
|
||||
* @return Node[]
|
||||
*/
|
||||
public function getNodes()
|
||||
public function getNodes() : array
|
||||
{
|
||||
return $this->nodes;
|
||||
}
|
||||
|
@ -16,15 +16,12 @@ interface Network
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getOutput(): array;
|
||||
public function getOutput() : array;
|
||||
|
||||
/**
|
||||
* @param Layer $layer
|
||||
*/
|
||||
public function addLayer(Layer $layer);
|
||||
|
||||
/**
|
||||
* @return Layer[]
|
||||
*/
|
||||
public function getLayers(): array;
|
||||
public function getLayers() : array;
|
||||
}
|
||||
|
@ -16,9 +16,6 @@ abstract class LayeredNetwork implements Network
|
||||
*/
|
||||
protected $layers;
|
||||
|
||||
/**
|
||||
* @param Layer $layer
|
||||
*/
|
||||
public function addLayer(Layer $layer)
|
||||
{
|
||||
$this->layers[] = $layer;
|
||||
@ -27,22 +24,16 @@ abstract class LayeredNetwork implements Network
|
||||
/**
|
||||
* @return Layer[]
|
||||
*/
|
||||
public function getLayers(): array
|
||||
public function getLayers() : array
|
||||
{
|
||||
return $this->layers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function removeLayers()
|
||||
{
|
||||
unset($this->layers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Layer
|
||||
*/
|
||||
public function getOutputLayer(): Layer
|
||||
{
|
||||
return $this->layers[count($this->layers) - 1];
|
||||
@ -51,7 +42,7 @@ abstract class LayeredNetwork implements Network
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getOutput(): array
|
||||
public function getOutput() : array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($this->getOutputLayer()->getNodes() as $neuron) {
|
||||
|
@ -5,16 +5,16 @@ declare(strict_types=1);
|
||||
namespace Phpml\NeuralNetwork\Network;
|
||||
|
||||
use Phpml\Estimator;
|
||||
use Phpml\IncrementalEstimator;
|
||||
use Phpml\Exception\InvalidArgumentException;
|
||||
use Phpml\NeuralNetwork\Training\Backpropagation;
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\IncrementalEstimator;
|
||||
use Phpml\NeuralNetwork\ActivationFunction;
|
||||
use Phpml\NeuralNetwork\Layer;
|
||||
use Phpml\NeuralNetwork\Node\Bias;
|
||||
use Phpml\NeuralNetwork\Node\Input;
|
||||
use Phpml\NeuralNetwork\Node\Neuron;
|
||||
use Phpml\NeuralNetwork\Node\Neuron\Synapse;
|
||||
use Phpml\Helper\Predictable;
|
||||
use Phpml\NeuralNetwork\Training\Backpropagation;
|
||||
|
||||
abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator, IncrementalEstimator
|
||||
{
|
||||
@ -56,13 +56,6 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
|
||||
protected $backpropagation = null;
|
||||
|
||||
/**
|
||||
* @param int $inputLayerFeatures
|
||||
* @param array $hiddenLayers
|
||||
* @param array $classes
|
||||
* @param int $iterations
|
||||
* @param ActivationFunction|null $activationFunction
|
||||
* @param int $theta
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct(int $inputLayerFeatures, array $hiddenLayers, array $classes, int $iterations = 10000, ActivationFunction $activationFunction = null, int $theta = 1)
|
||||
@ -85,9 +78,6 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
|
||||
$this->initNetwork();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function initNetwork()
|
||||
{
|
||||
$this->addInputLayer($this->inputLayerFeatures);
|
||||
@ -100,10 +90,6 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
|
||||
$this->backpropagation = new Backpropagation($this->theta);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
public function train(array $samples, array $targets)
|
||||
{
|
||||
$this->reset();
|
||||
@ -112,10 +98,6 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
* @param array $classes
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function partialTrain(array $samples, array $targets, array $classes = [])
|
||||
@ -131,38 +113,25 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
* @param mixed $target
|
||||
*/
|
||||
abstract protected function trainSample(array $sample, $target);
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function predictSample(array $sample);
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function reset()
|
||||
{
|
||||
$this->removeLayers();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $nodes
|
||||
*/
|
||||
private function addInputLayer(int $nodes)
|
||||
{
|
||||
$this->addLayer(new Layer($nodes, Input::class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $layers
|
||||
* @param ActivationFunction|null $activationFunction
|
||||
*/
|
||||
private function addNeuronLayers(array $layers, ActivationFunction $activationFunction = null)
|
||||
{
|
||||
foreach ($layers as $neurons) {
|
||||
@ -188,10 +157,6 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Layer $nextLayer
|
||||
* @param Layer $currentLayer
|
||||
*/
|
||||
private function generateLayerSynapses(Layer $nextLayer, Layer $currentLayer)
|
||||
{
|
||||
foreach ($nextLayer->getNodes() as $nextNeuron) {
|
||||
@ -201,10 +166,6 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Layer $currentLayer
|
||||
* @param Neuron $nextNeuron
|
||||
*/
|
||||
private function generateNeuronSynapses(Layer $currentLayer, Neuron $nextNeuron)
|
||||
{
|
||||
foreach ($currentLayer->getNodes() as $currentNeuron) {
|
||||
@ -212,10 +173,6 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
private function trainSamples(array $samples, array $targets)
|
||||
{
|
||||
foreach ($targets as $key => $target) {
|
||||
|
@ -6,8 +6,5 @@ namespace Phpml\NeuralNetwork;
|
||||
|
||||
interface Node
|
||||
{
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getOutput(): float;
|
||||
public function getOutput() : float;
|
||||
}
|
||||
|
@ -8,10 +8,7 @@ use Phpml\NeuralNetwork\Node;
|
||||
|
||||
class Bias implements Node
|
||||
{
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getOutput(): float
|
||||
public function getOutput() : float
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
@ -13,25 +13,16 @@ class Input implements Node
|
||||
*/
|
||||
private $input;
|
||||
|
||||
/**
|
||||
* @param float $input
|
||||
*/
|
||||
public function __construct(float $input = 0.0)
|
||||
{
|
||||
$this->input = $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getOutput(): float
|
||||
public function getOutput() : float
|
||||
{
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $input
|
||||
*/
|
||||
public function setInput(float $input)
|
||||
{
|
||||
$this->input = $input;
|
||||
|
@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace Phpml\NeuralNetwork\Node;
|
||||
|
||||
use Phpml\NeuralNetwork\ActivationFunction;
|
||||
use Phpml\NeuralNetwork\Node\Neuron\Synapse;
|
||||
use Phpml\NeuralNetwork\Node;
|
||||
use Phpml\NeuralNetwork\Node\Neuron\Synapse;
|
||||
|
||||
class Neuron implements Node
|
||||
{
|
||||
@ -25,9 +25,6 @@ class Neuron implements Node
|
||||
*/
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* @param ActivationFunction|null $activationFunction
|
||||
*/
|
||||
public function __construct(ActivationFunction $activationFunction = null)
|
||||
{
|
||||
$this->activationFunction = $activationFunction ?: new ActivationFunction\Sigmoid();
|
||||
@ -35,9 +32,6 @@ class Neuron implements Node
|
||||
$this->output = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Synapse $synapse
|
||||
*/
|
||||
public function addSynapse(Synapse $synapse)
|
||||
{
|
||||
$this->synapses[] = $synapse;
|
||||
@ -51,10 +45,7 @@ class Neuron implements Node
|
||||
return $this->synapses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getOutput(): float
|
||||
public function getOutput() : float
|
||||
{
|
||||
if (0 === $this->output) {
|
||||
$sum = 0;
|
||||
|
@ -28,42 +28,27 @@ class Synapse
|
||||
$this->weight = $weight ?: $this->generateRandomWeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
protected function generateRandomWeight(): float
|
||||
protected function generateRandomWeight() : float
|
||||
{
|
||||
return 1 / random_int(5, 25) * (random_int(0, 1) ? -1 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getOutput(): float
|
||||
public function getOutput() : float
|
||||
{
|
||||
return $this->weight * $this->node->getOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $delta
|
||||
*/
|
||||
public function changeWeight($delta)
|
||||
public function changeWeight(float $delta)
|
||||
{
|
||||
$this->weight += $delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getWeight()
|
||||
public function getWeight() : float
|
||||
{
|
||||
return $this->weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node
|
||||
*/
|
||||
public function getNode()
|
||||
public function getNode(): Node
|
||||
{
|
||||
return $this->node;
|
||||
}
|
||||
|
@ -24,16 +24,12 @@ class Backpropagation
|
||||
*/
|
||||
private $prevSigmas = null;
|
||||
|
||||
/**
|
||||
* @param int $theta
|
||||
*/
|
||||
public function __construct(int $theta)
|
||||
{
|
||||
$this->theta = $theta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $layers
|
||||
* @param mixed $targetClass
|
||||
*/
|
||||
public function backpropagate(array $layers, $targetClass)
|
||||
@ -59,15 +55,7 @@ class Backpropagation
|
||||
$this->prevSigmas = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Neuron $neuron
|
||||
* @param int $targetClass
|
||||
* @param int $key
|
||||
* @param bool $lastLayer
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
private function getSigma(Neuron $neuron, int $targetClass, int $key, bool $lastLayer): float
|
||||
private function getSigma(Neuron $neuron, int $targetClass, int $key, bool $lastLayer) : float
|
||||
{
|
||||
$neuronOutput = $neuron->getOutput();
|
||||
$sigma = $neuronOutput * (1 - $neuronOutput);
|
||||
@ -87,12 +75,7 @@ class Backpropagation
|
||||
return $sigma;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Neuron $neuron
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
private function getPrevSigma(Neuron $neuron): float
|
||||
private function getPrevSigma(Neuron $neuron) : float
|
||||
{
|
||||
$sigma = 0.0;
|
||||
|
||||
|
@ -18,38 +18,23 @@ class Sigma
|
||||
*/
|
||||
private $sigma;
|
||||
|
||||
/**
|
||||
* @param Neuron $neuron
|
||||
* @param float $sigma
|
||||
*/
|
||||
public function __construct(Neuron $neuron, $sigma)
|
||||
public function __construct(Neuron $neuron, float $sigma)
|
||||
{
|
||||
$this->neuron = $neuron;
|
||||
$this->sigma = $sigma;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Neuron
|
||||
*/
|
||||
public function getNeuron()
|
||||
public function getNeuron(): Neuron
|
||||
{
|
||||
return $this->neuron;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getSigma()
|
||||
public function getSigma() : float
|
||||
{
|
||||
return $this->sigma;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Neuron $neuron
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getSigmaForNeuron(Neuron $neuron): float
|
||||
public function getSigmaForNeuron(Neuron $neuron) : float
|
||||
{
|
||||
$sigma = 0.0;
|
||||
|
||||
|
@ -29,17 +29,11 @@ class Pipeline implements Estimator
|
||||
$this->estimator = $estimator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Transformer $transformer
|
||||
*/
|
||||
public function addTransformer(Transformer $transformer)
|
||||
{
|
||||
$this->transformers[] = $transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Estimator $estimator
|
||||
*/
|
||||
public function setEstimator(Estimator $estimator)
|
||||
{
|
||||
$this->estimator = $estimator;
|
||||
@ -48,15 +42,12 @@ class Pipeline implements Estimator
|
||||
/**
|
||||
* @return array|Transformer[]
|
||||
*/
|
||||
public function getTransformers()
|
||||
public function getTransformers() : array
|
||||
{
|
||||
return $this->transformers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Estimator
|
||||
*/
|
||||
public function getEstimator()
|
||||
public function getEstimator(): Estimator
|
||||
{
|
||||
return $this->estimator;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ class Imputer implements Preprocessor
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getAxis(int $column, array $currentSample): array
|
||||
private function getAxis(int $column, array $currentSample) : array
|
||||
{
|
||||
if (self::AXIS_ROW === $this->axis) {
|
||||
return array_diff($currentSample, [$this->missingValue]);
|
||||
|
@ -4,17 +4,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Preprocessing\Imputer\Strategy;
|
||||
|
||||
use Phpml\Preprocessing\Imputer\Strategy;
|
||||
use Phpml\Math\Statistic\Mean;
|
||||
use Phpml\Preprocessing\Imputer\Strategy;
|
||||
|
||||
class MeanStrategy implements Strategy
|
||||
{
|
||||
/**
|
||||
* @param array $currentAxis
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function replaceValue(array $currentAxis)
|
||||
public function replaceValue(array $currentAxis) : float
|
||||
{
|
||||
return Mean::arithmetic($currentAxis);
|
||||
}
|
||||
|
@ -4,17 +4,15 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Preprocessing\Imputer\Strategy;
|
||||
|
||||
use Phpml\Preprocessing\Imputer\Strategy;
|
||||
use Phpml\Math\Statistic\Mean;
|
||||
use Phpml\Preprocessing\Imputer\Strategy;
|
||||
|
||||
class MedianStrategy implements Strategy
|
||||
{
|
||||
/**
|
||||
* @param array $currentAxis
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function replaceValue(array $currentAxis)
|
||||
public function replaceValue(array $currentAxis) : float
|
||||
{
|
||||
return Mean::median($currentAxis);
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Phpml\Preprocessing\Imputer\Strategy;
|
||||
|
||||
use Phpml\Preprocessing\Imputer\Strategy;
|
||||
use Phpml\Math\Statistic\Mean;
|
||||
use Phpml\Preprocessing\Imputer\Strategy;
|
||||
|
||||
class MostFrequentStrategy implements Strategy
|
||||
{
|
||||
|
@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace Phpml\Preprocessing;
|
||||
|
||||
use Phpml\Exception\NormalizerException;
|
||||
use Phpml\Math\Statistic\StandardDeviation;
|
||||
use Phpml\Math\Statistic\Mean;
|
||||
use Phpml\Math\Statistic\StandardDeviation;
|
||||
|
||||
class Normalizer implements Preprocessor
|
||||
{
|
||||
@ -35,8 +35,6 @@ class Normalizer implements Preprocessor
|
||||
private $mean;
|
||||
|
||||
/**
|
||||
* @param int $norm
|
||||
*
|
||||
* @throws NormalizerException
|
||||
*/
|
||||
public function __construct(int $norm = self::NORM_L2)
|
||||
|
@ -30,10 +30,6 @@ class LeastSquares implements Regression
|
||||
*/
|
||||
private $coefficients;
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
public function train(array $samples, array $targets)
|
||||
{
|
||||
$this->samples = array_merge($this->samples, $samples);
|
||||
@ -43,8 +39,6 @@ class LeastSquares implements Regression
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function predictSample(array $sample)
|
||||
@ -57,18 +51,12 @@ class LeastSquares implements Regression
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getCoefficients()
|
||||
public function getCoefficients() : array
|
||||
{
|
||||
return $this->coefficients;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getIntercept()
|
||||
public function getIntercept() : float
|
||||
{
|
||||
return $this->intercept;
|
||||
}
|
||||
@ -90,10 +78,8 @@ class LeastSquares implements Regression
|
||||
|
||||
/**
|
||||
* Add one dimension for intercept calculation.
|
||||
*
|
||||
* @return Matrix
|
||||
*/
|
||||
private function getSamplesMatrix()
|
||||
private function getSamplesMatrix() : Matrix
|
||||
{
|
||||
$samples = [];
|
||||
foreach ($this->samples as $sample) {
|
||||
@ -104,10 +90,7 @@ class LeastSquares implements Regression
|
||||
return new Matrix($samples);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Matrix
|
||||
*/
|
||||
private function getTargetsMatrix()
|
||||
private function getTargetsMatrix() : Matrix
|
||||
{
|
||||
if (is_array($this->targets[0])) {
|
||||
return new Matrix($this->targets);
|
||||
|
@ -10,17 +10,6 @@ use Phpml\SupportVectorMachine\Type;
|
||||
|
||||
class SVR extends SupportVectorMachine implements Regression
|
||||
{
|
||||
/**
|
||||
* @param int $kernel
|
||||
* @param int $degree
|
||||
* @param float $epsilon
|
||||
* @param float $cost
|
||||
* @param float|null $gamma
|
||||
* @param float $coef0
|
||||
* @param float $tolerance
|
||||
* @param int $cacheSize
|
||||
* @param bool $shrinking
|
||||
*/
|
||||
public function __construct(
|
||||
int $kernel = Kernel::RBF,
|
||||
int $degree = 3,
|
||||
|
@ -6,13 +6,6 @@ namespace Phpml\SupportVectorMachine;
|
||||
|
||||
class DataTransformer
|
||||
{
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $labels
|
||||
* @param bool $targets
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function trainingSet(array $samples, array $labels, bool $targets = false): string
|
||||
{
|
||||
$set = '';
|
||||
@ -27,11 +20,6 @@ class DataTransformer
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function testSet(array $samples): string
|
||||
{
|
||||
if (!is_array($samples[0])) {
|
||||
@ -46,13 +34,7 @@ class DataTransformer
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $rawPredictions
|
||||
* @param array $labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function predictions(string $rawPredictions, array $labels): array
|
||||
public static function predictions(string $rawPredictions, array $labels) : array
|
||||
{
|
||||
$numericLabels = self::numericLabels($labels);
|
||||
$results = [];
|
||||
@ -65,12 +47,7 @@ class DataTransformer
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function numericLabels(array $labels): array
|
||||
public static function numericLabels(array $labels) : array
|
||||
{
|
||||
$numericLabels = [];
|
||||
foreach ($labels as $label) {
|
||||
@ -84,11 +61,6 @@ class DataTransformer
|
||||
return $numericLabels;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $sample
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function sampleRow(array $sample): string
|
||||
{
|
||||
$row = [];
|
||||
|
@ -91,20 +91,6 @@ class SupportVectorMachine
|
||||
*/
|
||||
private $targets = [];
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @param int $kernel
|
||||
* @param float $cost
|
||||
* @param float $nu
|
||||
* @param int $degree
|
||||
* @param float|null $gamma
|
||||
* @param float $coef0
|
||||
* @param float $epsilon
|
||||
* @param float $tolerance
|
||||
* @param int $cacheSize
|
||||
* @param bool $shrinking
|
||||
* @param bool $probabilityEstimates
|
||||
*/
|
||||
public function __construct(
|
||||
int $type,
|
||||
int $kernel,
|
||||
@ -138,11 +124,6 @@ class SupportVectorMachine
|
||||
$this->varPath = $rootPath.'var'.DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $binPath
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setBinPath(string $binPath)
|
||||
{
|
||||
$this->ensureDirectorySeparator($binPath);
|
||||
@ -151,11 +132,6 @@ class SupportVectorMachine
|
||||
$this->binPath = $binPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $varPath
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setVarPath(string $varPath)
|
||||
{
|
||||
if (!is_writable($varPath)) {
|
||||
@ -166,10 +142,6 @@ class SupportVectorMachine
|
||||
$this->varPath = $varPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
* @param array $targets
|
||||
*/
|
||||
public function train(array $samples, array $targets)
|
||||
{
|
||||
$this->samples = array_merge($this->samples, $samples);
|
||||
@ -189,17 +161,12 @@ class SupportVectorMachine
|
||||
unlink($modelFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getModel()
|
||||
public function getModel(): string
|
||||
{
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $samples
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function predict(array $samples)
|
||||
@ -232,10 +199,7 @@ class SupportVectorMachine
|
||||
return $predictions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getOSExtension()
|
||||
private function getOSExtension(): string
|
||||
{
|
||||
$os = strtoupper(substr(PHP_OS, 0, 3));
|
||||
if ($os === 'WIN') {
|
||||
@ -247,12 +211,6 @@ class SupportVectorMachine
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $trainingSetFileName
|
||||
* @param string $modelFileName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function buildTrainCommand(string $trainingSetFileName, string $modelFileName): string
|
||||
{
|
||||
return sprintf(
|
||||
@ -276,9 +234,6 @@ class SupportVectorMachine
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*/
|
||||
private function ensureDirectorySeparator(string &$path)
|
||||
{
|
||||
if (substr($path, -1) !== DIRECTORY_SEPARATOR) {
|
||||
@ -286,11 +241,6 @@ class SupportVectorMachine
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function verifyBinPath(string $path)
|
||||
{
|
||||
if (!is_dir($path)) {
|
||||
|
@ -6,10 +6,5 @@ namespace Phpml\Tokenization;
|
||||
|
||||
interface Tokenizer
|
||||
{
|
||||
/**
|
||||
* @param string $text
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function tokenize(string $text): array;
|
||||
public function tokenize(string $text) : array;
|
||||
}
|
||||
|
@ -6,12 +6,7 @@ namespace Phpml\Tokenization;
|
||||
|
||||
class WhitespaceTokenizer implements Tokenizer
|
||||
{
|
||||
/**
|
||||
* @param string $text
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function tokenize(string $text): array
|
||||
public function tokenize(string $text) : array
|
||||
{
|
||||
return preg_split('/[\pZ\pC]+/u', $text, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
@ -6,12 +6,7 @@ namespace Phpml\Tokenization;
|
||||
|
||||
class WordTokenizer implements Tokenizer
|
||||
{
|
||||
/**
|
||||
* @param string $text
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function tokenize(string $text): array
|
||||
public function tokenize(string $text) : array
|
||||
{
|
||||
$tokens = [];
|
||||
preg_match_all('/\w\w+/u', $text, $tokens);
|
||||
|
@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace tests\Phpml\Classification\Ensemble;
|
||||
|
||||
use Phpml\Classification\Ensemble\Bagging;
|
||||
use Phpml\Classification\DecisionTree;
|
||||
use Phpml\Classification\Ensemble\Bagging;
|
||||
use Phpml\Classification\NaiveBayes;
|
||||
use Phpml\ModelManager;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace tests\Phpml\Classification\Ensemble;
|
||||
|
||||
use Phpml\Classification\Ensemble\RandomForest;
|
||||
use Phpml\Classification\DecisionTree;
|
||||
use Phpml\Classification\Ensemble\RandomForest;
|
||||
use Phpml\Classification\NaiveBayes;
|
||||
|
||||
class RandomForestTest extends BaggingTest
|
||||
|
@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace tests\Phpml\Classification;
|
||||
|
||||
use Phpml\Classification\MLPClassifier;
|
||||
use Phpml\NeuralNetwork\Node\Neuron;
|
||||
use Phpml\ModelManager;
|
||||
use Phpml\NeuralNetwork\Node\Neuron;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class MLPClassifierTest extends TestCase
|
||||
@ -194,7 +194,7 @@ class MLPClassifierTest extends TestCase
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getSynapsesNodes(array $synapses): array
|
||||
private function getSynapsesNodes(array $synapses) : array
|
||||
{
|
||||
$nodes = [];
|
||||
foreach ($synapses as $synapse) {
|
||||
|
@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace tests\Phpml\Classification;
|
||||
|
||||
use Phpml\Classification\SVC;
|
||||
use Phpml\SupportVectorMachine\Kernel;
|
||||
use Phpml\ModelManager;
|
||||
use Phpml\SupportVectorMachine\Kernel;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SVCTest extends TestCase
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user