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() { $os = strtoupper(substr(PHP_OS, 0, 3)); if ($os === 'WIN') { return '.exe'; } elseif ($os === 'DAR') { return '-osx'; } 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, escapeshellarg($trainingSetFileName), escapeshellarg($modelFileName) ); } }