diff --git a/app/Http/Controllers/PerceptronController.php b/app/Http/Controllers/PerceptronController.php index ed8142a..1552db2 100644 --- a/app/Http/Controllers/PerceptronController.php +++ b/app/Http/Controllers/PerceptronController.php @@ -2,14 +2,14 @@ namespace App\Http\Controllers; -use App\Models\SimplePerceptron; -use App\Models\SimplePerceptronTraining; +use App\Events\PerceptronInitialization; +use App\Models\GradientDescentPerceptronTraining; +use App\Models\SimpleBinaryPerceptronTraining; use App\Services\DataSetReader; use App\Services\ISynapticWeightsProvider; use App\Services\PerceptronIterationEventBuffer; use App\Services\ZeroSynapticWeights; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Log; class PerceptronController extends Controller { @@ -18,29 +18,32 @@ class PerceptronController extends Controller */ public function index(Request $request) { - $perceptronType = $request->query('type', 'simple'); + $perceptronType = $request->query('type'); - $learningRate = 0.1; - $maxIterations = 100; + $learningRate = 0.01; + $maxIterations = 200; + $minError = 0.6; switch ($perceptronType) { case 'simple': $learningRate = 0.015; - $maxIterations = 100; + $maxIterations = 150; break; + case 'gradientdescent': + $learningRate = 0.00003; } return inertia('PerceptronViewer', [ 'type' => $perceptronType, 'sessionId' => session()->getId(), - 'datasets' => $this->getDatasets(), - 'minError' => 0.01, + 'datasets' => $this->getDatasets($perceptronType), + 'minError' => $minError, 'learningRate' => $learningRate, 'maxIterations' => $maxIterations, ]); } - private function getDatasets(): array + private function getDatasets(string $perceptronType): array { $dataSetsDirectory = public_path('data_sets'); $files = scandir($dataSetsDirectory); @@ -51,17 +54,44 @@ class PerceptronController extends Controller $dataset['label'] = str_replace('.csv', '', $file); $dataSetReader = new DataSetReader($dataSetsDirectory . '/' . $file); $dataset['data'] = []; - foreach ($dataSetReader->lines as $line) { - $dataset['data'][] = [ - 'x' => $line[0], - 'y' => $line[1], - 'label' => $line[2], - ]; + 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 '2.9': - $dataset['defaultLearningRate'] = 0.015; + case 'logic_and_gradient': + switch ($perceptronType) { + case 'gradientdescent': + $dataset['defaultLearningRate'] = 0.3; + break; + } + break; + case 'table_2_9': + switch ($perceptronType) { + case 'simple': + $dataset['defaultLearningRate'] = 0.015; + break; + } break; } $datasets[] = $dataset; @@ -78,7 +108,7 @@ class PerceptronController extends Controller public function run(Request $request, ISynapticWeightsProvider $synapticWeightsProvider) { - $perceptronType = $request->input('type', 'simple'); + $perceptronType = $request->input('type'); $minError = $request->input('min_error', 0.01); $weightInitMethod = $request->input('weight_init_method', 'random'); $dataSet = $request->input('dataset'); @@ -96,11 +126,12 @@ class PerceptronController extends Controller $iterationEventBuffer = new PerceptronIterationEventBuffer($sessionId, $trainingId); $networkTraining = match ($perceptronType) { - 'simple' => new SimplePerceptronTraining($dataSetReader, $learningRate, $maxIterations, $synapticWeightsProvider, $iterationEventBuffer, $sessionId, $trainingId), + 'simple' => new SimpleBinaryPerceptronTraining($dataSetReader, $learningRate, $maxIterations, $synapticWeightsProvider, $iterationEventBuffer, $sessionId, $trainingId), + 'gradientdescent' => new GradientDescentPerceptronTraining($dataSetReader, $learningRate, $maxIterations, $synapticWeightsProvider, $iterationEventBuffer, $sessionId, $trainingId, $minError), default => null, }; - event(new \App\Events\PerceptronInitialization($dataSetReader->lines, $networkTraining->activationFunction, $sessionId, $trainingId)); + event(new PerceptronInitialization($dataSetReader->lines, $networkTraining->activationFunction, $sessionId, $trainingId)); $networkTraining->start(); diff --git a/app/Models/ActivationsFunctions.php b/app/Models/ActivationsFunctions.php index fb26ecc..f02eb37 100644 --- a/app/Models/ActivationsFunctions.php +++ b/app/Models/ActivationsFunctions.php @@ -5,6 +5,7 @@ namespace App\Models; enum ActivationsFunctions: string { case STEP = 'step'; + case LINEAR = 'linear'; case SIGMOID = 'sigmoid'; case RELU = 'relu'; } diff --git a/app/Models/SimplePerceptron.php b/app/Models/GradientDescentPerceptron.php similarity index 53% rename from app/Models/SimplePerceptron.php rename to app/Models/GradientDescentPerceptron.php index 1ec5331..2f341cc 100644 --- a/app/Models/SimplePerceptron.php +++ b/app/Models/GradientDescentPerceptron.php @@ -2,7 +2,7 @@ namespace App\Models; -class SimplePerceptron extends Perceptron { +class GradientDescentPerceptron extends Perceptron { public function __construct( array $synaptic_weights, @@ -10,9 +10,9 @@ class SimplePerceptron extends Perceptron { parent::__construct($synaptic_weights); } - public function activationFunction(float $weighted_sum): int + public function activationFunction(float $weighted_sum): float { - return $weighted_sum >= 0 ? 1 : 0; + return $weighted_sum; } } diff --git a/app/Models/GradientDescentPerceptronTraining.php b/app/Models/GradientDescentPerceptronTraining.php new file mode 100644 index 0000000..c8e10c8 --- /dev/null +++ b/app/Models/GradientDescentPerceptronTraining.php @@ -0,0 +1,91 @@ +perceptron = new GradientDescentPerceptron($synapticWeightsProvider->generate($datasetReader->getInputSize())); + } + + public function start(): void + { + $this->iteration = 0; + do { + $this->epochError = 0; + $iterationErrorPerWeight = []; + $this->iteration++; + + while ($nextRow = $this->datasetReader->getRandomLine()) { + $inputs = array_slice($nextRow, 0, -1); + $correctOutput = (float) end($nextRow); + + $iterationError = $this->iterationFunction($inputs, $correctOutput); + $this->epochError += (1 / 2) * (abs($iterationError) ** 2); // TDDO REMOVEME abs() + + // Store the iteration error for each weight + $inputs_with_bias = array_merge([1], $inputs); // Add bias input + foreach ($inputs_with_bias as $index => $input) { + $iterationErrorPerWeight[$index][] = $iterationError * $input; + } + + // Broadcast the training iteration event + $this->addIterationToBuffer($iterationError, [[$this->perceptron->getSynapticWeights()]]); + } + + // Synaptic weights correction after each epoch + $synaptic_weights = $this->perceptron->getSynapticWeights(); + $new_weights = array_map( + fn($weight, $weightIndex) => $weight + $this->learningRate * array_sum($iterationErrorPerWeight[$weightIndex]), + $synaptic_weights, + array_keys($synaptic_weights) + ); + $this->perceptron->setSynapticWeights($new_weights); + + $this->datasetReader->reset(); // Reset the dataset for the next iteration + } while ($this->iteration < $this->maxIterations && !$this->stopCondition()); + + $this->iterationEventBuffer->flush(); // Ensure all iterations are sent to the frontend + + $this->checkPassedMaxIterations($this->epochError); + } + + protected function stopCondition(): bool + { + $condition = $this->epochError <= $this->minError && $this->perceptron->getSynapticWeights() !== [[0.0, 0.0, 0.0]]; + if ($condition === true) { + event(new PerceptronTrainingEnded('Le perceptron à atteint l\'erreur minimale', $this->sessionId, $this->trainingId)); + } + return $condition; + } + + private function iterationFunction(array $inputs, int $correctOutput) + { + $output = $this->perceptron->test($inputs); + + $error = $correctOutput - $output; + + return $error; + } +} diff --git a/app/Models/Network.php b/app/Models/Network.php new file mode 100644 index 0000000..06b099d --- /dev/null +++ b/app/Models/Network.php @@ -0,0 +1,8 @@ +iteration >= $this->maxIterations) { - event(new PerceptronTrainingEnded('Le nombre maximal d\'itérations a été atteint', $this->sessionId, $this->trainingId)); + $message = 'Le nombre maximal d\'itérations a été atteint'; + if ($finalError) { + $message .= " avec une erreur finale de $finalError"; + } + + event(new PerceptronTrainingEnded($message, $this->sessionId, $this->trainingId)); } } diff --git a/app/Models/Perceptron.php b/app/Models/Perceptron.php index b4c8cf7..e5de3f2 100644 --- a/app/Models/Perceptron.php +++ b/app/Models/Perceptron.php @@ -12,7 +12,7 @@ abstract class Perceptron extends Model $this->synaptic_weights = $synaptic_weights; } - public function test(array $inputs): int + public function test(array $inputs): float { $inputs = array_merge([1], $inputs); // Add bias input @@ -24,7 +24,7 @@ abstract class Perceptron extends Model return $this->activationFunction($weighted_sum); } - abstract public function activationFunction(float $weighted_sum): int; + abstract public function activationFunction(float $weighted_sum): float; public function getSynapticWeights(): array { diff --git a/app/Models/SimpleBinaryPerceptron.php b/app/Models/SimpleBinaryPerceptron.php new file mode 100644 index 0000000..28468bf --- /dev/null +++ b/app/Models/SimpleBinaryPerceptron.php @@ -0,0 +1,18 @@ += 0.0 ? 1.0 : 0.0; + } + +} diff --git a/app/Models/SimplePerceptronTraining.php b/app/Models/SimpleBinaryPerceptronTraining.php similarity index 89% rename from app/Models/SimplePerceptronTraining.php rename to app/Models/SimpleBinaryPerceptronTraining.php index d10c14f..95961d7 100644 --- a/app/Models/SimplePerceptronTraining.php +++ b/app/Models/SimpleBinaryPerceptronTraining.php @@ -6,9 +6,8 @@ use App\Events\PerceptronTrainingEnded; use App\Services\DataSetReader; use App\Services\ISynapticWeightsProvider; use App\Services\PerceptronIterationEventBuffer; -use Illuminate\Support\Facades\Log; -class SimplePerceptronTraining extends NetworkTraining +class SimpleBinaryPerceptronTraining extends NetworkTraining { private Perceptron $perceptron; private int $iterationErrorCounter = 0; @@ -27,7 +26,7 @@ class SimplePerceptronTraining extends NetworkTraining string $trainingId, ) { parent::__construct($datasetReader, $maxIterations, $iterationEventBuffer, $sessionId, $trainingId); - $this->perceptron = new SimplePerceptron($synapticWeightsProvider->generate(2)); + $this->perceptron = new SimpleBinaryPerceptron($synapticWeightsProvider->generate($datasetReader->getInputSize())); } public function start(): void @@ -40,13 +39,11 @@ class SimplePerceptronTraining extends NetworkTraining while ($nextRow = $this->datasetReader->getRandomLine()) { $inputs = array_slice($nextRow, 0, -1); - $correctOutput = end($nextRow); + $correctOutput = (float) end($nextRow); $correctOutput = $correctOutput > 0 ? 1 : 0; // Modify labels for non binary datasets $error = $this->iterationFunction($inputs, $correctOutput); - $error = abs($error); // Use absolute error - // Broadcast the training iteration event $this->addIterationToBuffer($error, [[$this->perceptron->getSynapticWeights()]]); } @@ -55,7 +52,7 @@ class SimplePerceptronTraining extends NetworkTraining $this->iterationEventBuffer->flush(); // Ensure all iterations are sent to the frontend - $this->checkPassedMaxIterations(); + $this->checkPassedMaxIterations(null); } protected function stopCondition(): bool diff --git a/app/Services/CsvReader.php b/app/Services/CsvReader.php index c38b928..d28cb75 100644 --- a/app/Services/CsvReader.php +++ b/app/Services/CsvReader.php @@ -4,7 +4,7 @@ namespace App\Services; class CsvReader { private $file; - private array $headers; + // private array $headers; public array $lines = []; @@ -17,7 +17,7 @@ class CsvReader { throw new \RuntimeException("Failed to open file: " . $filename); } - $this->headers = $this->readNextLine(); + // $this->headers = $this->readNextLine(); } public function readNextLine(): ?array diff --git a/app/Services/DataSetReader.php b/app/Services/DataSetReader.php index de5dd28..4e3dd76 100644 --- a/app/Services/DataSetReader.php +++ b/app/Services/DataSetReader.php @@ -20,7 +20,17 @@ class DataSetReader { private function readEntireFile(CsvReader $reader): void { while ($line = $reader->readNextLine()) { - $this->lines[] = $line; + $newLine = []; + foreach ($line as $value) { // Transform to float + $newLine[] = (float) $value; + } + + // if the dataset is for regression, we add a fake label of 0 + if (count($newLine) === 2) { + $newLine[] = 0.0; + } + + $this->lines[] = $newLine; } } @@ -31,12 +41,21 @@ class DataSetReader { } $randomNumber = array_rand($this->currentLines); $randomLine = $this->currentLines[$randomNumber]; + // Remove the line from the current lines to avoid repetition unset($this->currentLines[$randomNumber]); + + // Remember the index of the last read line in the full list $this->lastReadLineIndex = array_search($randomLine, $this->lines, true); + return $randomLine; } + public function getInputSize(): int + { + return count($this->lines[0]) - 1; // Don't count the label + } + public function reset(): void { $this->currentLines = $this->lines; diff --git a/public/data_sets/2.9.csv b/public/data_sets/2.9.csv deleted file mode 100644 index 9b7e19e..0000000 --- a/public/data_sets/2.9.csv +++ /dev/null @@ -1,22 +0,0 @@ -x_1, x_2, d -1, 6, 1 -7, 9, -1 -1, 9, 1 -7, 10, -1 -2, 5, -1 -2, 7, 1 -2, 8, 1 -6, 8, -1 -6, 9, -1 -3, 5, -1 -3, 6, -1 -3, 8, 1 -3, 9, 1 -5, 7, -1 -5, 8, -1 -5, 10, 1 -5, 11, 1 -4, 6, -1 -4, 7, -1 -4, 9, 1 -4, 10, 1 diff --git a/public/data_sets/logic_and.csv b/public/data_sets/logic_and.csv index 2cdcf5f..f336911 100644 --- a/public/data_sets/logic_and.csv +++ b/public/data_sets/logic_and.csv @@ -1,4 +1,3 @@ -x_1, x_2, d 0, 0, 0 0, 1, 0 1, 0, 0 diff --git a/public/data_sets/logic_and_gradient.csv b/public/data_sets/logic_and_gradient.csv new file mode 100644 index 0000000..23c2287 --- /dev/null +++ b/public/data_sets/logic_and_gradient.csv @@ -0,0 +1,4 @@ +0, 0, -1 +0, 1, -1 +1, 0, -1 +1, 1, 1 diff --git a/public/data_sets/logic_xor.csv b/public/data_sets/logic_xor.csv index 8b15159..e6a1799 100644 --- a/public/data_sets/logic_xor.csv +++ b/public/data_sets/logic_xor.csv @@ -1,4 +1,3 @@ -x_1, x_2, d 0, 0, 1 0, 1, 0 1, 0, 0 diff --git a/public/data_sets/table_2_10.csv b/public/data_sets/table_2_10.csv new file mode 100644 index 0000000..fbef89f --- /dev/null +++ b/public/data_sets/table_2_10.csv @@ -0,0 +1,23 @@ +1,2,1 +1,4,-1 +1,5,1 +7,5,-1 +7,6,-1 +2,1,-1 +2,3,1 +2,4,1 +6,2,1 +6,4,-1 +6,5,-1 +3,1,-1 +3,2,-1 +3,4,1 +3,5,1 +5,3,-1 +5,4,-1 +5,6,1 +5,7,1 +4,2,-1 +4,3,1 +4,5,1 +4,6,1 diff --git a/public/data_sets/table_2_11.csv b/public/data_sets/table_2_11.csv new file mode 100644 index 0000000..a763456 --- /dev/null +++ b/public/data_sets/table_2_11.csv @@ -0,0 +1,30 @@ +10,4.4 +14,5.6 +12,4.6 +18,6.1 +16,6.0 +14,7.0 +22,6.8 +28,10.6 +26,11.0 +16,7.6 +23,10.8 +25,10.0 +20,6.5 +20,8.2 +24,8.8 +12,5.5 +15,5.0 +18,8.0 +14,7.8 +26,9.0 +25,9.4 +17,8.5 +12,6.4 +20,7.5 +23,9.0 +22,8.1 +26,8.2 +22,10.0 +18,9.1 +21,9.0 diff --git a/public/data_sets/table_2_9.csv b/public/data_sets/table_2_9.csv new file mode 100644 index 0000000..3bfd684 --- /dev/null +++ b/public/data_sets/table_2_9.csv @@ -0,0 +1,21 @@ +1,6,1 +7,9,-1 +1,9,1 +7,10,-1 +2,5,-1 +2,7,1 +2,8,1 +6,8,-1 +6,9,-1 +3,5,-1 +3,6,-1 +3,8,1 +3,9,1 +5,7,-1 +5,8,-1 +5,10,1 +5,11,1 +4,6,-1 +4,7,-1 +4,9,1 +4,10,1 diff --git a/public/data_sets/table_3_1.csv b/public/data_sets/table_3_1.csv new file mode 100644 index 0000000..6ad9115 --- /dev/null +++ b/public/data_sets/table_3_1.csv @@ -0,0 +1,150 @@ +2.8,1.9,-1,-1,1 +2.9,1.8,-1,-1,1 +2.2,1.5,-1,-1,1 +1.3,5.6,-1,1,-1 +-1.2,1.6,1,-1,-1 +2.5,1.7,-1,-1,1 +3.1,2.3,-1,-1,1 +2.8,2.4,-1,-1,1 +-1.2,1.5,1,-1,-1 +1.4,6.1,-1,1,-1 +-1.2,1.3,1,-1,-1 +3.1,1.8,-1,-1,1 +3.3,2.5,-1,-1,1 +3.4,2.3,-1,-1,1 +1.5,5.9,-1,1,-1 +1.3,5.6,-1,1,-1 +-1.2,1,1,-1,-1 +3,2.1,-1,-1,1 +1.4,5.2,-1,1,-1 +1.2,5.5,-1,1,-1 +1.4,6.7,-1,1,-1 +-1.3,1.7,1,-1,-1 +1,5.7,-1,1,-1 +2.6,1.4,-1,-1,1 +1.6,6,-1,1,-1 +1.2,5.8,-1,1,-1 +1.4,6.1,-1,1,-1 +1.3,5.7,-1,1,-1 +-1.2,1.4,1,-1,-1 +1,5.5,-1,1,-1 +3.1,2.1,-1,-1,1 +-1.4,1.7,1,-1,-1 +1.6,6.3,-1,1,-1 +-1.2,1.4,1,-1,-1 +2.7,1.9,-1,-1,1 +1.1,5.5,-1,1,-1 +3,1.8,-1,-1,1 +3.8,2,-1,-1,1 +2.8,2.1,-1,-1,1 +1,5,-1,1,-1 +2.8,2,-1,-1,1 +-1.2,1.6,1,-1,-1 +1.3,6.6,-1,1,-1 +1.6,6,-1,1,-1 +3,1.6,-1,-1,1 +-1.1,1.1,1,-1,-1 +2.9,1.8,-1,-1,1 +3,1.8,-1,-1,1 +-1.2,1.4,1,-1,-1 +1,5.8,-1,1,-1 +1.2,5.7,-1,1,-1 +2.8,1.5,-1,-1,1 +-1.4,1.6,1,-1,-1 +-1.2,1.4,1,-1,-1 +2.8,2.2,-1,-1,1 +-1.5,1.7,1,-1,-1 +1,4.9,-1,1,-1 +1.3,5.7,-1,1,-1 +3.2,2.3,-1,-1,1 +-1.3,1.5,1,-1,-1 +-1.2,1.2,1,-1,-1 +-1.2,1.6,1,-1,-1 +3,2.1,-1,-1,1 +-1.4,1.5,1,-1,-1 +1.3,5.5,-1,1,-1 +3.3,2.5,-1,-1,1 +3.1,2.4,-1,-1,1 +1.8,5.9,-1,1,-1 +2.7,1.9,-1,-1,1 +1.5,6.3,-1,1,-1 +-1.3,1.4,1,-1,-1 +1,5,-1,1,-1 +3.2,2.3,-1,-1,1 +-1.3,1.4,1,-1,-1 +3,2.1,-1,-1,1 +3.2,2,-1,-1,1 +1.3,6.3,-1,1,-1 +1.4,7,-1,1,-1 +-1.2,1.7,1,-1,-1 +1.4,6.6,-1,1,-1 +1.2,5.8,-1,1,-1 +3,2,-1,-1,1 +-1.2,1.6,1,-1,-1 +1.5,6.2,-1,1,-1 +1.5,6.4,-1,1,-1 +-1.2,1.9,1,-1,-1 +3.2,2.3,-1,-1,1 +-1.2,1.5,1,-1,-1 +1.5,5.4,-1,1,-1 +1.5,6,-1,1,-1 +1.5,6.9,-1,1,-1 +-1.4,1.5,1,-1,-1 +1.3,6.4,-1,1,-1 +2.8,2,-1,-1,1 +-1.2,1.5,1,-1,-1 +-1.1,1.5,1,-1,-1 +3.6,2.5,-1,-1,1 +1.1,5.1,-1,1,-1 +-1.1,1.5,1,-1,-1 +-1.2,1.5,1,-1,-1 +3.4,2.4,-1,-1,1 +-1.3,1.3,1,-1,-1 +3,2.3,-1,-1,1 +-1.1,1.5,1,-1,-1 +1.1,5.6,-1,1,-1 +1.3,5.6,-1,1,-1 +-1.2,1.5,1,-1,-1 +-1.2,1.3,1,-1,-1 +1.7,6.7,-1,1,-1 +-1.2,1.3,1,-1,-1 +-1.4,1.3,1,-1,-1 +2.5,1.8,-1,-1,1 +-1.4,1.5,1,-1,-1 +1.5,6.5,-1,1,-1 +2.6,2.3,-1,-1,1 +-1.2,1.4,1,-1,-1 +1.5,5.6,-1,1,-1 +1.3,5.7,-1,1,-1 +1.2,6.1,-1,1,-1 +3,2.2,-1,-1,1 +3,1.8,-1,-1,1 +-1.1,1.4,1,-1,-1 +1.4,6.8,-1,1,-1 +-1.6,1.6,1,-1,-1 +-1.2,1.4,1,-1,-1 +3.2,1.8,-1,-1,1 +-1.2,1.5,1,-1,-1 +2.7,1.8,-1,-1,1 +-1.3,1.4,1,-1,-1 +1.3,6.2,-1,1,-1 +-1.3,1.3,1,-1,-1 +3,1.8,-1,-1,1 +2.7,1.9,-1,-1,1 +-1.2,1.4,1,-1,-1 +-1.2,1.2,1,-1,-1 +1.5,6.7,-1,1,-1 +2.5,1.9,-1,-1,1 +3.3,2.1,-1,-1,1 +2.8,1.8,-1,-1,1 +-1.2,1.3,1,-1,-1 +3.8,2.2,-1,-1,1 +2.5,2,-1,-1,1 +1.3,6.1,-1,1,-1 +-1.2,1.4,1,-1,-1 +-1.1,1.5,1,-1,-1 +3,2.3,-1,-1,1 +-1.4,1.9,1,-1,-1 +-1.2,1.6,1,-1,-1 +1,6,-1,1,-1 +1.3,5.5,-1,1,-1 diff --git a/public/data_sets/table_3_5.csv b/public/data_sets/table_3_5.csv new file mode 100644 index 0000000..7616d23 --- /dev/null +++ b/public/data_sets/table_3_5.csv @@ -0,0 +1,4 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,-1,-1,-1 +0,0,1,0,0,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,-1,1,-1,-1 +1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,-1,-1,1,-1 +0,0,0,0,0,0,1,1,1,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,0,-1,-1,-1,1 diff --git a/public/data_sets/table_4_12.csv b/public/data_sets/table_4_12.csv new file mode 100644 index 0000000..bb5cdad --- /dev/null +++ b/public/data_sets/table_4_12.csv @@ -0,0 +1,100 @@ +-1.56,0.93,0.0 +1.43,-1.29,0.0 +1.03,0.59,1.0 +0.21,-0.04,1.0 +-0.62,1.25,0.0 +1.21,0.35,1.0 +-0.1,-0.26,1.0 +-1.59,1.75,0.0 +-1.45,1.71,0.0 +0.79,-1.93,0.0 +0.32,0.28,1.0 +0.57,0.4,1.0 +0.75,-0.07,1.0 +-0.09,0.15,1.0 +1.79,1.15,0.0 +0.2,-0.18,1.0 +1.85,0.34,0.0 +-0.53,-1.25,0.0 +-0.4,0.54,1.0 +0.45,0,1.0 +0.04,0.59,1.0 +0.07,-0.81,0.0 +-0.28,0.78,1.0 +0.21,1.53,0.0 +1.14,0.14,1.0 +-0.51,0.06,1.0 +-1.21,0.76,0.0 +0.35,0.64,1.0 +-0.65,0.56,1.0 +1.48,1.31,0.0 +1.6,1.73,0.0 +0.82,0.68,1.0 +-1.09,-1.18,0.0 +1.75,-0.75,0.0 +-0.14,0.32,1.0 +-1.39,-1.93,0.0 +0.84,-0.1,1.0 +-0.35,0.43,1.0 +-0.57,0.31,1.0 +0.51,-1.26,0.0 +-0.31,-1.71,0.0 +-1.48,1.25,0.0 +-1.71,0.18,0.0 +-0.31,0.7,1.0 +0.07,0.98,1.0 +0.92,0.42,1.0 +0.71,1.73,0.0 +-1.45,-0.92,0.0 +1.43,1.01,0.0 +0.6,0.1,1.0 +0.07,-1.31,0.0 +0.76,0.37,1.0 +-0.9,0.93,0.0 +0.07,0.09,1.0 +0.95,0.48,1.0 +1.31,1.57,0.0 +-0.73,-0.68,0.0 +0.17,0.37,1.0 +-0.12,0.76,1.0 +1.14,1.31,0.0 +-0.45,-0.07,1.0 +0.21,0.43,1.0 +-0.01,0.25,1.0 +0.04,1.82,0.0 +-0.87,-1.56,0.0 +0.57,-0.21,1.0 +0.37,0.51,1.0 +0.43,0.29,1.0 +0.31,-1.68,0.0 +1.25,-1.75,0.0 +0.54,0.67,1.0 +1.29,-0.73,0.0 +1.75,-0.25,0.0 +0.42,-1.06,0.0 +-0.26,-0.98,0.0 +1.01,-1.34,0.0 +-0.28,1.32,0.0 +0.62,-1.32,0.0 +0.4,0.9,1.0 +0.28,-0.09,1.0 +-1.07,1.32,0.0 +1.56,-0.26,0.0 +1,0.23,1.0 +-0.06,0.48,1.0 +-0.18,-0.1,1.0 +-0.53,0.2,1.0 +0.9,0.15,1.0 +-0.51,1.68,0.0 +-0.76,0.28,1.0 +0.25,0.78,1.0 +1.68,0.67,0.0 +-1.48,-0.43,0.0 +-1.64,-1.39,0.0 +0.76,-0.92,0.0 +1.09,0.51,1.0 +0.65,0.67,1.0 +-0.37,0.17,1.0 +-1.06,-0.23,0.0 +0.59,1.42,0.0 +-1.32,0.23,0.0 diff --git a/public/data_sets/table_4_14.csv b/public/data_sets/table_4_14.csv new file mode 100644 index 0000000..8270d23 --- /dev/null +++ b/public/data_sets/table_4_14.csv @@ -0,0 +1,150 @@ +-0.87,0.7,0.0,0.0,1.0 +-0.62,-0.78,1.0,0.0,0.0 +0.73,1.09,0.0,0.0,1.0 +0.32,-0.2,1.0,0.0,0.0 +0.18,-1.07,1.0,0.0,0.0 +-0.45,-0.51,1.0,0.0,0.0 +0.28,0.89,0.0,0.0,1.0 +1.67,0.75,0.0,1.0,0.0 +-0.21,0.95,0.0,0.0,1.0 +1.48,0.01,0.0,1.0,0.0 +1.75,1.07,0.0,1.0,0.0 +1.64,1.78,0.0,1.0,0.0 +0.76,-1.28,1.0,0.0,0.0 +-0.56,1.17,0.0,0.0,1.0 +1.73,1.59,0.0,1.0,0.0 +1.1,-0.7,1.0,0.0,0.0 +1.67,0.62,0.0,1.0,0.0 +0.17,-0.62,1.0,0.0,0.0 +0.64,1.71,0.0,0.0,1.0 +-1.73,-0.71,0.0,0.0,1.0 +0.17,-0.48,1.0,0.0,0.0 +1.82,0.92,0.0,1.0,0.0 +-1.21,0.5,0.0,0.0,1.0 +1.29,0.1,0.0,1.0,0.0 +-1.78,-0.2,0.0,0.0,1.0 +1.42,0.64,0.0,1.0,0.0 +-0.21,1.21,0.0,0.0,1.0 +-0.06,1.39,0.0,0.0,1.0 +0.03,-1.92,1.0,0.0,0.0 +1.15,0.6,0.0,1.0,0.0 +-0.75,0.95,0.0,0.0,1.0 +1.51,0.85,0.0,1.0,0.0 +1.5,0.43,0.0,1.0,0.0 +1.28,-0.5,1.0,0.0,0.0 +1.1,0.29,0.0,1.0,0.0 +-1.48,-0.65,0.0,0.0,1.0 +1.18,-0.98,1.0,0.0,0.0 +-1.53,0.62,0.0,0.0,1.0 +-0.67,-0.32,1.0,0.0,0.0 +0.89,-0.37,1.0,0.0,0.0 +1.54,0.2,0.0,1.0,0.0 +0.4,1.53,0.0,0.0,1.0 +-0.62,0.5,0.0,0.0,1.0 +1.84,1.73,0.0,1.0,0.0 +-0.04,-0.35,1.0,0.0,0.0 +-0.5,0.79,0.0,0.0,1.0 +-0.31,1.51,0.0,0.0,1.0 +1.7,0.82,0.0,1.0,0.0 +1.29,0.34,0.0,1.0,0.0 +0.5,-1.04,1.0,0.0,0.0 +1.62,0.81,0.0,1.0,0.0 +1.76,1.67,0.0,1.0,0.0 +-0.35,-1,1.0,0.0,0.0 +1.03,-0.53,1.0,0.0,0.0 +-0.35,-0.64,1.0,0.0,0.0 +1.31,0.35,0.0,1.0,0.0 +0.68,-1.68,1.0,0.0,0.0 +-0.98,0.28,0.0,0.0,1.0 +-0.15,-0.17,1.0,0.0,0.0 +-0.01,0.92,0.0,0.0,1.0 +0.46,-1.68,1.0,0.0,0.0 +1,0.59,0.0,1.0,0.0 +0.51,-0.46,1.0,0.0,0.0 +-0.15,-0.68,1.0,0.0,0.0 +1.73,0.17,0.0,1.0,0.0 +1.62,0.35,0.0,1.0,0.0 +0.96,-1.06,1.0,0.0,0.0 +0.06,-1.68,1.0,0.0,0.0 +-1.48,-1.75,0.0,0.0,1.0 +0.18,-1.39,1.0,0.0,0.0 +1.12,0.2,0.0,1.0,0.0 +-1.23,-1.32,0.0,0.0,1.0 +-0.26,-0.39,1.0,0.0,0.0 +1.82,1.48,0.0,1.0,0.0 +-0.64,-0.56,1.0,0.0,0.0 +-1.37,-1.46,0.0,0.0,1.0 +1.43,0.21,0.0,1.0,0.0 +-0.14,-1.6,1.0,0.0,0.0 +0.9,1.46,0.0,0.0,1.0 +0.87,0.18,0.0,1.0,0.0 +-1.1,-1.62,0.0,0.0,1.0 +-0.43,-0.29,1.0,0.0,0.0 +-0.53,-0.12,1.0,0.0,0.0 +0.12,1.14,0.0,0.0,1.0 +0.18,-0.29,1.0,0.0,0.0 +1.42,0.56,0.0,1.0,0.0 +-0.82,-0.1,1.0,0.0,0.0 +0.89,-0.71,1.0,0.0,0.0 +1.12,1.62,0.0,0.0,1.0 +-1.51,-0.06,0.0,0.0,1.0 +-1.37,-0.93,0.0,0.0,1.0 +0.87,0.4,0.0,1.0,0.0 +-1.54,0.29,0.0,0.0,1.0 +0.57,-1.9,1.0,0.0,0.0 +-0.04,-0.71,1.0,0.0,0.0 +0.5,-1.46,1.0,0.0,0.0 +0.32,-0.39,1.0,0.0,0.0 +-0.96,1.01,0.0,0.0,1.0 +1.14,1.32,0.0,0.0,1.0 +0.6,0.48,0.0,1.0,0.0 +-1.5,-1.31,0.0,0.0,1.0 +0.03,-0.85,1.0,0.0,0.0 +1.67,1.26,0.0,1.0,0.0 +0.34,-0.68,1.0,0.0,0.0 +1.85,1.17,0.0,1.0,0.0 +0.93,1.78,0.0,0.0,1.0 +1.32,0.37,0.0,1.0,0.0 +0.43,0.32,0.0,1.0,0.0 +-1.18,0.57,0.0,0.0,1.0 +-1.75,-1.67,0.0,0.0,1.0 +1.71,1.89,0.0,1.0,0.0 +0.2,-1.25,1.0,0.0,0.0 +-1.21,0.92,0.0,0.0,1.0 +1.76,1.75,0.0,1.0,0.0 +-1.75,-1.03,0.0,0.0,1.0 +-0.26,-1.23,1.0,0.0,0.0 +0.95,-1.57,1.0,0.0,0.0 +-0.18,-1.1,1.0,0.0,0.0 +-0.17,-0.5,1.0,0.0,0.0 +-0.89,0.56,0.0,0.0,1.0 +-0.43,0.78,0.0,0.0,1.0 +1.79,1.4,0.0,1.0,0.0 +0.4,1.26,0.0,0.0,1.0 +0.76,0.32,0.0,1.0,0.0 +1.7,-0.03,0.0,1.0,0.0 +0.68,-0.34,1.0,0.0,0.0 +1.31,0.89,0.0,1.0,0.0 +-0.32,-0.29,1.0,0.0,0.0 +0.76,-0.9,1.0,0.0,0.0 +1.9,1.82,0.0,1.0,0.0 +1.54,1.03,0.0,1.0,0.0 +-0.07,0.64,0.0,0.0,1.0 +1.85,0.56,0.0,1.0,0.0 +0.76,0.53,0.0,1.0,0.0 +-1.65,0.06,0.0,0.0,1.0 +1.04,-1.29,1.0,0.0,0.0 +-0.39,0.64,0.0,0.0,1.0 +1.14,0.42,0.0,1.0,0.0 +-1.35,0.1,0.0,0.0,1.0 +0.06,1.62,0.0,0.0,1.0 +-1.26,-1.78,0.0,0.0,1.0 +-1.39,-0.43,0.0,0.0,1.0 +-0.87,-1.84,0.0,0.0,1.0 +0.65,-0.65,1.0,0.0,0.0 +1,0.43,0.0,1.0,0.0 +0.64,0.32,0.0,1.0,0.0 +0.75,1.85,0.0,0.0,1.0 +0.57,0.21,0.0,1.0,0.0 +0.14,0.29,0.0,1.0,0.0 +1.09,0.68,0.0,1.0,0.0 diff --git a/public/data_sets/table_4_17.csv b/public/data_sets/table_4_17.csv new file mode 100644 index 0000000..3b4133c --- /dev/null +++ b/public/data_sets/table_4_17.csv @@ -0,0 +1,120 @@ +-0.4,-1.32 +1.7,-0.04 +0.53,-0.07 +-1.9,1.09 +0.53,0.12 +1.85,0.17 +-1.35,-0.46 +0.4,-0.15 +1.73,0.32 +-0.67,-0.71 +0.21,-0.03 +0.26,-0.59 +-1.45,-0.04 +0.09,-1.06 +-1.17,0.46 +-0.25,-1.42 +-1.71,0.7 +0.42,0.25 +-1.23,-0.21 +1.34,0.07 +-0.98,-1.17 +-1.9,0.84 +0.39,-0.71 +-0.71,-1.32 +1.82,-0.1 +0.79,0.18 +1.65,0.39 +-1.65,1 +1.01,0.03 +0.56,0.39 +-1.64,0.98 +0.89,0.29 +-1.23,0.2 +-1.32,0.46 +-0.1,-0.85 +-0.68,-1.04 +1.12,0.25 +-1.79,1.09 +-1.39,1.17 +-1.79,1.71 +1.37,0.15 +-0.76,-0.64 +0.75,0.34 +-1.67,0.39 +-0.07,-0.65 +0.4,-0.17 +1.06,0.56 +-0.96,-0.35 +0.98,0.42 +-0.39,-1.15 +-0.51,-1.4 +1.5,0.32 +-0.84,-0.85 +1.76,0.34 +-0.28,-1.09 +-1.59,1.14 +-0.07,-0.75 +-0.81,-0.43 +-0.5,-1.1 +-1.84,1.54 +-0.84,-0.84 +1.37,0.35 +-1.59,1.56 +-1.12,-0.79 +-0.46,-0.87 +-0.87,-1.07 +-1.46,0.81 +-1.59,0.1 +0.29,-0.4 +-0.01,-1.1 +0.85,0.51 +-1.45,0.34 +-1.26,0.34 +1.37,0.26 +0,-0.79 +-1.07,0.1 +1.35,0.51 +0.82,0.35 +-1.67,1.35 +0.82,0.09 +0.51,-0.03 +0.07,-0.75 +-0.07,-1.01 +0.35,-0.07 +-0.73,-0.15 +-1.64,1.39 +-0.67,-0.82 +-0.29,-1.03 +0.75,0.51 +-0.84,-0.64 +-1.4,0.1 +-1.07,0.07 +-0.21,-1.21 +-1.45,0.98 +1.2,0.45 +-0.28,-1.1 +0.09,-0.26 +-1.32,0.5 +1.12,0.34 +-1.53,0.54 +-1.65,1.64 +1.75,0.04 +0.7,0 +0.89,0.09 +-1.29,0 +-1.73,0.9 +1,0.51 +-1.14,-0.14 +1.7,0.21 +-0.98,-0.64 +-0.92,-0.23 +-0.23,-0.89 +-0.37,-1.34 +1.48,0.03 +0.51,-0.28 +-1.04,0.32 +-1.56,0.85 +1.57,0.42 +-1.26,0.76 +-1.81,1.25 diff --git a/resources/js/components/LinkHeader.vue b/resources/js/components/LinkHeader.vue index 62bba7e..2cd3954 100644 --- a/resources/js/components/LinkHeader.vue +++ b/resources/js/components/LinkHeader.vue @@ -11,9 +11,9 @@ const links = [ data: { type: 'simple' }, }, { - name: 'Perceptron Complex', + name: 'Descente du gradient', href: '/perceptron', - data: { type: 'complex' }, + data: { type: 'gradientdescent' }, }, ]; diff --git a/resources/js/components/PerceptronDecisionGraph.vue b/resources/js/components/PerceptronDecisionGraph.vue index 118ed93..9007f45 100644 --- a/resources/js/components/PerceptronDecisionGraph.vue +++ b/resources/js/components/PerceptronDecisionGraph.vue @@ -7,7 +7,7 @@ import type { } from 'chart.js'; import { computed } from 'vue'; import { Chart } from 'vue-chartjs'; -import { colors } from '@/types/graphs'; +import { colors, gridColor, gridColorBold } from '@/types/graphs'; import type { Iteration } from '@/types/perceptron'; const props = defineProps<{ @@ -157,10 +157,28 @@ function getPerceptronDecisionBoundaryDataset( x: { type: 'linear', position: 'bottom', + grid: { + color: function (context) { + if (context.tick.value == 0) { + return gridColorBold; + } + + return gridColor; + }, + }, }, y: { type: 'linear', position: 'left', + grid: { + color: function (context) { + if (context.tick.value == 0) { + return gridColorBold; + } + + return gridColor; + }, + }, }, }, }" diff --git a/resources/js/components/PerceptronIterationsErrorsGraph.vue b/resources/js/components/PerceptronIterationsErrorsGraph.vue index 78206c5..57068c5 100644 --- a/resources/js/components/PerceptronIterationsErrorsGraph.vue +++ b/resources/js/components/PerceptronIterationsErrorsGraph.vue @@ -1,7 +1,7 @@ @@ -68,6 +92,15 @@ function getPerceptronErrorsPerIteration(): ChartData< y: { stacked: true, beginAtZero: true, + grid: { + color: function (context) { + if (context.tick.value == 0) { + return gridColorBold; + } + + return gridColor; + }, + }, }, }, }" diff --git a/resources/js/components/PerceptronSetup.vue b/resources/js/components/PerceptronSetup.vue index 4c56896..820b30a 100644 --- a/resources/js/components/PerceptronSetup.vue +++ b/resources/js/components/PerceptronSetup.vue @@ -73,10 +73,10 @@ function startTraining() { }, credentials: 'same-origin', body: JSON.stringify({ - type: 'simple', + type: props.type, dataset: selectedDatasetCopy.value, weight_init_method: selectedMethod.value, - min_error: 0.01, + min_error: minError.value, learning_rate: learningRate.value, session_id: props.sessionId, training_id: trainingId.value, diff --git a/resources/js/pages/PerceptronViewer.vue b/resources/js/pages/PerceptronViewer.vue index 277bf13..95c3c42 100644 --- a/resources/js/pages/PerceptronViewer.vue +++ b/resources/js/pages/PerceptronViewer.vue @@ -155,6 +155,8 @@ function getActivationFunction(type: string): (x: number) => number { return (x) => 1 / (1 + Math.exp(-x)); case 'tanh': return (x) => Math.tanh(x); + case 'linear': + return (x) => x; default: return (x) => x; // Identity function as fallback } diff --git a/resources/js/types/graphs.ts b/resources/js/types/graphs.ts index 291354c..a2b31de 100644 --- a/resources/js/types/graphs.ts +++ b/resources/js/types/graphs.ts @@ -32,3 +32,6 @@ export const colors = [ '#DC143C', '#00FF00', ] as const; + +export const gridColor = '#444'; +export const gridColorBold = '#999'; \ No newline at end of file