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