166 lines
6.7 KiB
PHP
166 lines
6.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Events\PerceptronInitialization;
|
|
use App\Models\NetworksTraining\ADALINEPerceptronTraining;
|
|
use App\Models\NetworksTraining\GradientDescentPerceptronTraining;
|
|
use App\Models\NetworksTraining\SimpleBinaryPerceptronTraining;
|
|
use App\Services\DatasetReader\IDataSetReader;
|
|
use App\Services\DatasetReader\LinearOrderDataSetReader;
|
|
use App\Services\DatasetReader\RandomOrderDataSetReader;
|
|
use App\Services\IterationEventBuffer\PerceptronIterationEventBuffer;
|
|
use App\Services\IterationEventBuffer\PerceptronLimitedEpochEventBuffer;
|
|
use App\Services\SynapticWeightsProvider\ISynapticWeightsProvider;
|
|
use App\Services\SynapticWeightsProvider\ZeroSynapticWeights;
|
|
use Illuminate\Http\Request;
|
|
|
|
class PerceptronController extends Controller
|
|
{
|
|
/**
|
|
* Display the specified resource.
|
|
*/
|
|
public function index(Request $request)
|
|
{
|
|
$perceptronType = $request->query('type');
|
|
|
|
$learningRate = 0.01;
|
|
$maxIterations = 200;
|
|
$minError = 0.1;
|
|
|
|
switch ($perceptronType) {
|
|
case 'simple':
|
|
$learningRate = 0.015;
|
|
$maxIterations = 150;
|
|
break;
|
|
case 'gradientdescent' || 'adaline':
|
|
$learningRate = 0.00003;
|
|
break;
|
|
}
|
|
|
|
return inertia('PerceptronViewer', [
|
|
'type' => $perceptronType,
|
|
'sessionId' => session()->getId(),
|
|
'datasets' => $this->getDatasets($perceptronType),
|
|
'minError' => $minError,
|
|
'learningRate' => $learningRate,
|
|
'maxIterations' => $maxIterations,
|
|
]);
|
|
}
|
|
|
|
private function getDatasets(string $perceptronType): array
|
|
{
|
|
$dataSetsDirectory = public_path('data_sets');
|
|
$files = scandir($dataSetsDirectory);
|
|
$datasets = [];
|
|
foreach ($files as $file) {
|
|
if (pathinfo($file, PATHINFO_EXTENSION) === 'csv') {
|
|
$dataset = [];
|
|
$dataset['label'] = str_replace('.csv', '', $file);
|
|
$dataSetReader = new LinearOrderDataSetReader($dataSetsDirectory.'/'.$file);
|
|
$dataset['data'] = [];
|
|
switch (count($dataSetReader->lines[0])) {
|
|
case 3:
|
|
foreach ($dataSetReader->lines as $line) {
|
|
$dataset['data'][] = [
|
|
'x' => $line[0],
|
|
'y' => $line[1],
|
|
'label' => $line[2],
|
|
];
|
|
}
|
|
break;
|
|
case 2:
|
|
foreach ($dataSetReader->lines as $line) {
|
|
$dataset['data'][] = [
|
|
'x' => $line[0],
|
|
'y' => $line[1],
|
|
'label' => 1,
|
|
];
|
|
}
|
|
break;
|
|
default:
|
|
$dataset['data'] = null; // Not supported for viewing
|
|
break;
|
|
}
|
|
|
|
switch ($dataset['label']) {
|
|
case 'logic_and_gradient':
|
|
switch ($perceptronType) {
|
|
case 'gradientdescent':
|
|
$dataset['defaultLearningRate'] = 0.3;
|
|
$dataset['defaultMinError'] = 0.125;
|
|
break;
|
|
case 'adaline':
|
|
$dataset['defaultLearningRate'] = 0.05;
|
|
$dataset['defaultMinError'] = 0.125;
|
|
break;
|
|
}
|
|
break;
|
|
case 'table_2_9':
|
|
switch ($perceptronType) {
|
|
case 'simple':
|
|
$dataset['defaultLearningRate'] = 0.015;
|
|
break;
|
|
case 'gradientdescent' || 'adaline':
|
|
$dataset['defaultLearningRate'] = 0.001;
|
|
break;
|
|
}
|
|
break;
|
|
case 'table_2_11':
|
|
$dataset['defaultMinError'] = 0.02;
|
|
break;
|
|
}
|
|
$datasets[] = $dataset;
|
|
}
|
|
}
|
|
|
|
return $datasets;
|
|
}
|
|
|
|
private function getDataSetReader(string $dataSet): IDataSetReader
|
|
{
|
|
$dataSetFileName = "data_sets/{$dataSet}.csv";
|
|
|
|
return new RandomOrderDataSetReader($dataSetFileName);
|
|
}
|
|
|
|
public function run(Request $request, ISynapticWeightsProvider $synapticWeightsProvider)
|
|
{
|
|
$perceptronType = $request->input('type');
|
|
$minError = $request->input('min_error', 0.01);
|
|
$weightInitMethod = $request->input('weight_init_method', 'random');
|
|
$dataSet = $request->input('dataset');
|
|
$learningRate = $request->input('learning_rate', 0.015);
|
|
$maxEpochs = $request->input('max_iterations', 100);
|
|
$sessionId = $request->input('session_id', session()->getId());
|
|
$trainingId = $request->input('training_id');
|
|
|
|
if ($weightInitMethod === 'zeros') {
|
|
$synapticWeightsProvider = new ZeroSynapticWeights;
|
|
}
|
|
|
|
$iterationEventBuffer = new PerceptronIterationEventBuffer($sessionId, $trainingId);
|
|
if ($maxEpochs > config('perceptron.limited_broadcast_iterations')) {
|
|
$iterationsInterval = (int) ($maxEpochs / config('perceptron.limited_broadcast_iterations'));
|
|
$iterationEventBuffer = new PerceptronLimitedEpochEventBuffer($sessionId, $trainingId, $iterationsInterval);
|
|
}
|
|
|
|
$datasetReader = $this->getDataSetReader($dataSet);
|
|
|
|
$networkTraining = match ($perceptronType) {
|
|
'simple' => new SimpleBinaryPerceptronTraining($datasetReader, $learningRate, $maxEpochs, $synapticWeightsProvider, $iterationEventBuffer, $sessionId, $trainingId),
|
|
'gradientdescent' => new GradientDescentPerceptronTraining($datasetReader, $learningRate, $maxEpochs, $synapticWeightsProvider, $iterationEventBuffer, $sessionId, $trainingId, $minError),
|
|
'adaline' => new ADALINEPerceptronTraining($datasetReader, $learningRate, $maxEpochs, $synapticWeightsProvider, $iterationEventBuffer, $sessionId, $trainingId, $minError),
|
|
default => null,
|
|
};
|
|
|
|
event(new PerceptronInitialization($datasetReader->lines, $networkTraining->activationFunction, $sessionId, $trainingId));
|
|
|
|
$networkTraining->start();
|
|
|
|
return response()->json([
|
|
'message' => 'Training completed',
|
|
]);
|
|
}
|
|
}
|