Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
83.33% |
5 / 6 |
CRAP | |
98.41% |
62 / 63 |
SupportVectorMachine | |
0.00% |
0 / 1 |
|
83.33% |
5 / 6 |
10 | |
98.41% |
62 / 63 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
16 / 16 |
|||
train | |
100.00% |
1 / 1 |
1 | |
100.00% |
11 / 11 |
|||
getModel | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
predict | |
100.00% |
1 / 1 |
3 | |
100.00% |
17 / 17 |
|||
getOSExtension | |
0.00% |
0 / 1 |
2.15 | |
66.67% |
2 / 3 |
|||
buildTrainCommand | |
100.00% |
1 / 1 |
2 | |
100.00% |
15 / 15 |
<?php | |
declare (strict_types = 1); | |
namespace Phpml\SupportVectorMachine; | |
class SupportVectorMachine | |
{ | |
/** | |
* @var int | |
*/ | |
private $type; | |
/** | |
* @var int | |
*/ | |
private $kernel; | |
/** | |
* @var float | |
*/ | |
private $cost; | |
/** | |
* @var float | |
*/ | |
private $nu; | |
/** | |
* @var int | |
*/ | |
private $degree; | |
/** | |
* @var float | |
*/ | |
private $gamma; | |
/** | |
* @var float | |
*/ | |
private $coef0; | |
/** | |
* @var float | |
*/ | |
private $epsilon; | |
/** | |
* @var float | |
*/ | |
private $tolerance; | |
/** | |
* @var int | |
*/ | |
private $cacheSize; | |
/** | |
* @var bool | |
*/ | |
private $shrinking; | |
/** | |
* @var bool | |
*/ | |
private $probabilityEstimates; | |
/** | |
* @var string | |
*/ | |
private $binPath; | |
/** | |
* @var string | |
*/ | |
private $varPath; | |
/** | |
* @var string | |
*/ | |
private $model; | |
/** | |
* @var array | |
*/ | |
private $labels; | |
/** | |
* @param int $type | |
* @param int $kernel | |
* @param float $cost | |
* @param float $nu | |
* @param int $degree | |
* @param float|null $gamma | |
* @param float $coef0 | |
* @param float $epsilon | |
* @param float $tolerance | |
* @param int $cacheSize | |
* @param bool $shrinking | |
* @param bool $probabilityEstimates | |
*/ | |
public function __construct( | |
int $type, int $kernel, float $cost = 1.0, float $nu = 0.5, int $degree = 3, | |
float $gamma = null, float $coef0 = 0.0, float $epsilon = 0.1, float $tolerance = 0.001, | |
int $cacheSize = 100, bool $shrinking = true, bool $probabilityEstimates = false | |
) { | |
$this->type = $type; | |
$this->kernel = $kernel; | |
$this->cost = $cost; | |
$this->nu = $nu; | |
$this->degree = $degree; | |
$this->gamma = $gamma; | |
$this->coef0 = $coef0; | |
$this->epsilon = $epsilon; | |
$this->tolerance = $tolerance; | |
$this->cacheSize = $cacheSize; | |
$this->shrinking = $shrinking; | |
$this->probabilityEstimates = $probabilityEstimates; | |
$rootPath = realpath(implode(DIRECTORY_SEPARATOR, [dirname(__FILE__), '..', '..', '..'])).DIRECTORY_SEPARATOR; | |
$this->binPath = $rootPath.'bin'.DIRECTORY_SEPARATOR.'libsvm'.DIRECTORY_SEPARATOR; | |
$this->varPath = $rootPath.'var'.DIRECTORY_SEPARATOR; | |
} | |
/** | |
* @param array $samples | |
* @param array $labels | |
*/ | |
public function train(array $samples, array $labels) | |
{ | |
$this->labels = $labels; | |
$trainingSet = DataTransformer::trainingSet($samples, $labels, in_array($this->type, [Type::EPSILON_SVR, Type::NU_SVR])); | |
file_put_contents($trainingSetFileName = $this->varPath.uniqid(), $trainingSet); | |
$modelFileName = $trainingSetFileName.'-model'; | |
$command = $this->buildTrainCommand($trainingSetFileName, $modelFileName); | |
$output = ''; | |
exec(escapeshellcmd($command), $output); | |
$this->model = file_get_contents($modelFileName); | |
unlink($trainingSetFileName); | |
unlink($modelFileName); | |
} | |
/** | |
* @return string | |
*/ | |
public function getModel() | |
{ | |
return $this->model; | |
} | |
/** | |
* @param array $samples | |
* | |
* @return array | |
*/ | |
public function predict(array $samples) | |
{ | |
$testSet = DataTransformer::testSet($samples); | |
file_put_contents($testSetFileName = $this->varPath.uniqid(), $testSet); | |
file_put_contents($modelFileName = $testSetFileName.'-model', $this->model); | |
$outputFileName = $testSetFileName.'-output'; | |
$command = sprintf('%ssvm-predict%s %s %s %s', $this->binPath, $this->getOSExtension(), $testSetFileName, $modelFileName, $outputFileName); | |
$output = ''; | |
exec(escapeshellcmd($command), $output); | |
$predictions = file_get_contents($outputFileName); | |
unlink($testSetFileName); | |
unlink($modelFileName); | |
unlink($outputFileName); | |
if (in_array($this->type, [Type::C_SVC, Type::NU_SVC])) { | |
$predictions = DataTransformer::predictions($predictions, $this->labels); | |
} else { | |
$predictions = explode(PHP_EOL, trim($predictions)); | |
} | |
if (!is_array($samples[0])) { | |
return $predictions[0]; | |
} | |
return $predictions; | |
} | |
/** | |
* @return string | |
*/ | |
private function getOSExtension() | |
{ | |
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { | |
return '.exe'; | |
} | |
return ''; | |
} | |
/** | |
* @param $trainingSetFileName | |
* @param $modelFileName | |
* | |
* @return string | |
*/ | |
private function buildTrainCommand(string $trainingSetFileName, string $modelFileName): string | |
{ | |
return sprintf('%ssvm-train%s -s %s -t %s -c %s -n %s -d %s%s -r %s -p %s -m %s -e %s -h %d -b %d \'%s\' \'%s\'', | |
$this->binPath, | |
$this->getOSExtension(), | |
$this->type, | |
$this->kernel, | |
$this->cost, | |
$this->nu, | |
$this->degree, | |
$this->gamma !== null ? ' -g '.$this->gamma : '', | |
$this->coef0, | |
$this->epsilon, | |
$this->cacheSize, | |
$this->tolerance, | |
$this->shrinking, | |
$this->probabilityEstimates, | |
$trainingSetFileName, | |
$modelFileName | |
); | |
} | |
} |