Machine Learning

Resonance integrates with Rubix ML to serve Machine Learning models. Rubix ML is a high-level machine learning library that allows you to train and serve machine learning models.

Training

Put your datasets in a place from which your application can access to them (for example datasets directory) and prepare models directory for the outputs.

php
<?php declare(strict_types=1); namespace App\Command; use Distantmagic\Resonance\Attribute\ConsoleCommand; use Distantmagic\Resonance\Command; use Psr\Log\LoggerInterface; use Rubix\ML\Classifiers\KNearestNeighbors; use Rubix\ML\CrossValidation\Metrics\Accuracy; use Rubix\ML\Datasets\Labeled; use Rubix\ML\Extractors\NDJSON; use Rubix\ML\Persisters\Filesystem; use Rubix\ML\Serializers\RBX; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; /** * @see https://github.com/RubixML/Iris */ #[ConsoleCommand( name: 'train:iris', description: 'Train Iris Flower Classifier' )] final class TrainIris extends Command { public function __construct(private LoggerInterface $logger) { parent::__construct(); } protected function execute(InputInterface $input, OutputInterface $output): int { $this->logger->info('Loading data into memory'); $training = Labeled::fromIterator(new NDJSON(DM_ROOT.'/datasets/iris.ndjson')); $testing = $training->randomize()->take(10); $estimator = new KNearestNeighbors(5); $this->logger->info('Training'); $estimator->train($training); $this->logger->info('Making predictions'); $predictions = $estimator->predict($testing); $metric = new Accuracy(); $score = $metric->score($predictions, $testing->labels()); $this->logger->info("Accuracy is $score"); $this->logger->info('Serializing'); $serializer = new RBX(); $encoding = $serializer->serialize($estimator); $filesystemPersister = new Filesystem(DM_ROOT.'/models/iris.model'); $filesystemPersister->save($encoding); return Command::SUCCESS; } }

Serving

After the model is trained, you can serve responses from a specific responder in your application.

It must be loaded in the constructor so the model will be loaded during runtime. Resonance will keep it in the memory and serve predictions from it. You can use the same server as for the rest of your application.

php
<?php declare(strict_types=1); namespace App\HttpResponder; use Distantmagic\Resonance\Attribute\RespondsToHttp; use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\HttpInterceptableInterface; use Distantmagic\Resonance\HttpResponder; use Distantmagic\Resonance\RequestMethod; use Distantmagic\Resonance\SingletonCollection; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Rubix\ML\Datasets\Unlabeled; use Rubix\ML\Estimator; use Rubix\ML\PersistentModel; use Rubix\ML\Persisters\Filesystem; use Symfony\Component\HttpFoundation\JsonResponse; #[RespondsToHttp( method: RequestMethod::POST, pattern: '/predict', )] #[Singleton(collection: SingletonCollection::HttpResponder)] readonly class Predict extends HttpResponder { private Estimator $model; public function __construct() { $this->model = PersistentModel::load(new Filesystem(DM_ROOT.'/models/iris.model')); } public function respond( ServerRequestInterface $request, ResponseInterface $response, ): HttpInterceptableInterface { $dataset = new Unlabeled($request->getParsedBody()); $predictions = $this->model->predict($dataset); return new JsonResponse($predictions); } }
Edit on GitHub