Fix linting
This commit is contained in:
@@ -21,8 +21,7 @@ class PerceptronInitialization implements ShouldBroadcast
|
||||
public ActivationsFunctions $activationFunction,
|
||||
public string $sessionId,
|
||||
public string $trainingId,
|
||||
)
|
||||
{
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
@@ -34,7 +33,7 @@ class PerceptronInitialization implements ShouldBroadcast
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
return [
|
||||
new Channel($this->sessionId . '-perceptron-training'),
|
||||
new Channel($this->sessionId.'-perceptron-training'),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
@@ -21,8 +19,7 @@ class PerceptronTrainingEnded implements ShouldBroadcast
|
||||
public string $reason,
|
||||
public string $sessionId,
|
||||
public string $trainingId,
|
||||
)
|
||||
{
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
@@ -34,7 +31,7 @@ class PerceptronTrainingEnded implements ShouldBroadcast
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
return [
|
||||
new Channel($this->sessionId . '-perceptron-training'),
|
||||
new Channel($this->sessionId.'-perceptron-training'),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@ class PerceptronTrainingIteration implements ShouldBroadcast
|
||||
public array $iterations, // ["epoch" => int, "exampleIndex" => int, "error" => float, "synaptic_weights" => array]
|
||||
public string $sessionId,
|
||||
public string $trainingId,
|
||||
)
|
||||
{
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
@@ -33,7 +32,7 @@ class PerceptronTrainingIteration implements ShouldBroadcast
|
||||
{
|
||||
// Log::debug("Broadcasting on channel: " . $this->sessionId . '-perceptron-training');
|
||||
return [
|
||||
new Channel($this->sessionId . '-perceptron-training'),
|
||||
new Channel($this->sessionId.'-perceptron-training'),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ class PerceptronController extends Controller
|
||||
if (pathinfo($file, PATHINFO_EXTENSION) === 'csv') {
|
||||
$dataset = [];
|
||||
$dataset['label'] = str_replace('.csv', '', $file);
|
||||
$dataSetReader = new LinearOrderDataSetReader($dataSetsDirectory . '/' . $file);
|
||||
$dataSetReader = new LinearOrderDataSetReader($dataSetsDirectory.'/'.$file);
|
||||
$dataset['data'] = [];
|
||||
switch (count($dataSetReader->lines[0])) {
|
||||
case 3:
|
||||
@@ -113,12 +113,14 @@ class PerceptronController extends Controller
|
||||
$datasets[] = $dataset;
|
||||
}
|
||||
}
|
||||
|
||||
return $datasets;
|
||||
}
|
||||
|
||||
private function getDataSetReader(string $dataSet): IDataSetReader
|
||||
{
|
||||
$dataSetFileName = "data_sets/{$dataSet}.csv";
|
||||
|
||||
return new RandomOrderDataSetReader($dataSetFileName);
|
||||
}
|
||||
|
||||
@@ -134,18 +136,17 @@ class PerceptronController extends Controller
|
||||
$trainingId = $request->input('training_id');
|
||||
|
||||
if ($weightInitMethod === 'zeros') {
|
||||
$synapticWeightsProvider = new ZeroSynapticWeights();
|
||||
$synapticWeightsProvider = new ZeroSynapticWeights;
|
||||
}
|
||||
|
||||
$iterationEventBuffer = new PerceptronIterationEventBuffer($sessionId, $trainingId);
|
||||
if ($maxEpochs > config('perceptron.limited_broadcast_iterations')) {
|
||||
$iterationsInterval = (int)($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),
|
||||
|
||||
@@ -52,7 +52,7 @@ class ADALINEPerceptronTraining extends NetworkTraining
|
||||
$synaptic_weights = $this->perceptron->getSynapticWeights();
|
||||
$inputs_with_bias = array_merge([1], $inputs); // Add bias input
|
||||
$new_weights = array_map(
|
||||
fn($weight, $weightIndex) => $weight + ($this->learningRate * $iterationError * $inputs_with_bias[$weightIndex]),
|
||||
fn ($weight, $weightIndex) => $weight + ($this->learningRate * $iterationError * $inputs_with_bias[$weightIndex]),
|
||||
$synaptic_weights,
|
||||
array_keys($synaptic_weights)
|
||||
);
|
||||
@@ -73,7 +73,7 @@ class ADALINEPerceptronTraining extends NetworkTraining
|
||||
$this->epochError /= $this->datasetReader->getEpochExamplesCount(); // Average error for the epoch
|
||||
|
||||
$this->datasetReader->reset(); // Reset the dataset for the next iteration
|
||||
} while ($this->epoch < $this->maxEpochs && !$this->stopCondition());
|
||||
} while ($this->epoch < $this->maxEpochs && ! $this->stopCondition());
|
||||
|
||||
$this->iterationEventBuffer->flush(); // Ensure all iterations are sent to the frontend
|
||||
|
||||
@@ -86,6 +86,7 @@ class ADALINEPerceptronTraining extends NetworkTraining
|
||||
if ($condition === true) {
|
||||
event(new PerceptronTrainingEnded('Le perceptron à atteint l\'erreur minimale', $this->sessionId, $this->trainingId));
|
||||
}
|
||||
|
||||
return $condition;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,14 +62,14 @@ class GradientDescentPerceptronTraining extends NetworkTraining
|
||||
// Synaptic weights correction after each epoch
|
||||
$synaptic_weights = $this->perceptron->getSynapticWeights();
|
||||
$new_weights = array_map(
|
||||
fn($weight, $weightIndex) => $weight + $this->learningRate * array_sum($epochCorrectorPerWeight[$weightIndex]),
|
||||
fn ($weight, $weightIndex) => $weight + $this->learningRate * array_sum($epochCorrectorPerWeight[$weightIndex]),
|
||||
$synaptic_weights,
|
||||
array_keys($synaptic_weights)
|
||||
);
|
||||
$this->perceptron->setSynapticWeights($new_weights);
|
||||
|
||||
$this->datasetReader->reset(); // Reset the dataset for the next iteration
|
||||
} while ($this->epoch < $this->maxEpochs && !$this->stopCondition());
|
||||
} while ($this->epoch < $this->maxEpochs && ! $this->stopCondition());
|
||||
|
||||
$this->iterationEventBuffer->flush(); // Ensure all iterations are sent to the frontend
|
||||
|
||||
@@ -82,6 +82,7 @@ class GradientDescentPerceptronTraining extends NetworkTraining
|
||||
if ($condition === true) {
|
||||
event(new PerceptronTrainingEnded('Le perceptron à atteint l\'erreur minimale', $this->sessionId, $this->trainingId));
|
||||
}
|
||||
|
||||
return $condition;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
namespace App\Models\NetworksTraining;
|
||||
|
||||
use App\Events\PerceptronTrainingEnded;
|
||||
use App\Models\ActivationsFunctions;
|
||||
use App\Services\DatasetReader\IDataSetReader;
|
||||
use App\Services\IterationEventBuffer\IPerceptronIterationEventBuffer;
|
||||
use App\Models\ActivationsFunctions;
|
||||
|
||||
abstract class NetworkTraining
|
||||
{
|
||||
@@ -13,7 +13,6 @@ abstract class NetworkTraining
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @var ActivationsFunctions
|
||||
*/
|
||||
public ActivationsFunctions $activationFunction;
|
||||
|
||||
@@ -23,13 +22,14 @@ abstract class NetworkTraining
|
||||
protected IPerceptronIterationEventBuffer $iterationEventBuffer,
|
||||
protected string $sessionId,
|
||||
protected string $trainingId,
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
abstract public function start(): void;
|
||||
|
||||
abstract public function start() : void;
|
||||
abstract protected function stopCondition(): bool;
|
||||
|
||||
protected function checkPassedMaxIterations(?float $finalError) {
|
||||
protected function checkPassedMaxIterations(?float $finalError)
|
||||
{
|
||||
if ($this->epoch >= $this->maxEpochs) {
|
||||
$message = 'Le nombre maximal d\'epoch a été atteint';
|
||||
if ($finalError) {
|
||||
@@ -40,7 +40,8 @@ abstract class NetworkTraining
|
||||
}
|
||||
}
|
||||
|
||||
protected function addIterationToBuffer(float $error, array $synapticWeights) {
|
||||
protected function addIterationToBuffer(float $error, array $synapticWeights)
|
||||
{
|
||||
$this->iterationEventBuffer->addIteration($this->epoch, $this->datasetReader->getLastReadLineIndex(), $error, $synapticWeights);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ use App\Services\SynapticWeightsProvider\ISynapticWeightsProvider;
|
||||
class SimpleBinaryPerceptronTraining extends NetworkTraining
|
||||
{
|
||||
private Perceptron $perceptron;
|
||||
|
||||
private int $iterationErrorCounter = 0;
|
||||
|
||||
public ActivationsFunctions $activationFunction = ActivationsFunctions::STEP;
|
||||
@@ -51,7 +52,7 @@ class SimpleBinaryPerceptronTraining extends NetworkTraining
|
||||
$this->addIterationToBuffer($error, [[$this->perceptron->getSynapticWeights()]]);
|
||||
}
|
||||
$this->datasetReader->reset(); // Reset the dataset for the next iteration
|
||||
} while ($this->epoch < $this->maxEpochs && !$this->stopCondition());
|
||||
} while ($this->epoch < $this->maxEpochs && ! $this->stopCondition());
|
||||
|
||||
$this->iterationEventBuffer->flush(); // Ensure all iterations are sent to the frontend
|
||||
|
||||
@@ -64,6 +65,7 @@ class SimpleBinaryPerceptronTraining extends NetworkTraining
|
||||
if ($condition === true) {
|
||||
event(new PerceptronTrainingEnded('Le perceptron ne commet plus d\'erreurs sur aucune des données', $this->sessionId, $this->trainingId));
|
||||
}
|
||||
|
||||
return $this->iterationErrorCounter == 0;
|
||||
}
|
||||
|
||||
@@ -79,9 +81,10 @@ class SimpleBinaryPerceptronTraining extends NetworkTraining
|
||||
if ($error !== 0) { // Update synaptic weights if needed
|
||||
$synaptic_weights = $this->perceptron->getSynapticWeights();
|
||||
$inputs_with_bias = array_merge([1], $inputs); // Add bias input
|
||||
$new_weights = array_map(fn($weight, $input) => $weight + $this->learningRate * $error * $input, $synaptic_weights, $inputs_with_bias);
|
||||
$new_weights = array_map(fn ($weight, $input) => $weight + $this->learningRate * $error * $input, $synaptic_weights, $inputs_with_bias);
|
||||
$this->perceptron->setSynapticWeights($new_weights);
|
||||
}
|
||||
|
||||
return $error;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Models\Perceptrons;
|
||||
|
||||
class GradientDescentPerceptron extends Perceptron {
|
||||
|
||||
class GradientDescentPerceptron extends Perceptron
|
||||
{
|
||||
public function __construct(
|
||||
array $synaptic_weights,
|
||||
) {
|
||||
@@ -14,5 +14,4 @@ class GradientDescentPerceptron extends Perceptron {
|
||||
{
|
||||
return $weighted_sum;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,10 +17,11 @@ abstract class Perceptron extends Model
|
||||
$inputs = array_merge([1], $inputs); // Add bias input
|
||||
|
||||
if (count($inputs) !== count($this->synaptic_weights)) { // Check
|
||||
throw new \InvalidArgumentException("Number of inputs must match number of synaptic weights.");
|
||||
throw new \InvalidArgumentException('Number of inputs must match number of synaptic weights.');
|
||||
}
|
||||
|
||||
$weighted_sum = array_sum(array_map(fn($input, $weight) => $input * $weight, $inputs, $this->synaptic_weights));
|
||||
$weighted_sum = array_sum(array_map(fn ($input, $weight) => $input * $weight, $inputs, $this->synaptic_weights));
|
||||
|
||||
return $this->activationFunction($weighted_sum);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Models\Perceptrons;
|
||||
|
||||
class SimpleBinaryPerceptron extends Perceptron {
|
||||
|
||||
class SimpleBinaryPerceptron extends Perceptron
|
||||
{
|
||||
public function __construct(
|
||||
array $synaptic_weights,
|
||||
) {
|
||||
@@ -14,5 +14,4 @@ class SimpleBinaryPerceptron extends Perceptron {
|
||||
{
|
||||
return $weighted_sum >= 0.0 ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use Carbon\CarbonImmutable;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ class InitialSynapticWeightsProvider extends ServiceProvider
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->singleton(ISynapticWeightsProvider::class, function ($app) {
|
||||
return new RandomSynapticWeights();
|
||||
return new RandomSynapticWeights;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
class CsvReader {
|
||||
class CsvReader
|
||||
{
|
||||
private $file;
|
||||
// private array $headers;
|
||||
|
||||
@@ -10,11 +11,10 @@ class CsvReader {
|
||||
|
||||
public function __construct(
|
||||
public string $filename,
|
||||
)
|
||||
{
|
||||
$this->file = fopen($filename, "r");
|
||||
if (!$this->file) {
|
||||
throw new \RuntimeException("Failed to open file: " . $filename);
|
||||
) {
|
||||
$this->file = fopen($filename, 'r');
|
||||
if (! $this->file) {
|
||||
throw new \RuntimeException('Failed to open file: '.$filename);
|
||||
}
|
||||
|
||||
// $this->headers = $this->readNextLine();
|
||||
@@ -22,9 +22,10 @@ class CsvReader {
|
||||
|
||||
public function readNextLine(): ?array
|
||||
{
|
||||
if (($data = fgetcsv($this->file, 1000, ",")) !== FALSE) {
|
||||
if (($data = fgetcsv($this->file, 1000, ',')) !== false) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return null; // End of file or error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
|
||||
namespace App\Services\DatasetReader;
|
||||
|
||||
interface IDataSetReader {
|
||||
public function getNextLine(): array | null;
|
||||
interface IDataSetReader
|
||||
{
|
||||
public function getNextLine(): ?array;
|
||||
|
||||
public function getInputSize(): int;
|
||||
|
||||
public function reset(): void;
|
||||
|
||||
public function getLastReadLineIndex(): int;
|
||||
|
||||
public function getEpochExamplesCount(): int;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ namespace App\Services\DatasetReader;
|
||||
|
||||
use App\Services\CsvReader;
|
||||
|
||||
class LinearOrderDataSetReader implements IDataSetReader {
|
||||
class LinearOrderDataSetReader implements IDataSetReader
|
||||
{
|
||||
public array $lines = [];
|
||||
|
||||
private array $currentLines = [];
|
||||
|
||||
private int $lastReadLineIndex = -1;
|
||||
@@ -36,8 +38,9 @@ class LinearOrderDataSetReader implements IDataSetReader {
|
||||
}
|
||||
}
|
||||
|
||||
public function getNextLine(): array | null {
|
||||
if (!isset($this->currentLines[0])) {
|
||||
public function getNextLine(): ?array
|
||||
{
|
||||
if (! isset($this->currentLines[0])) {
|
||||
return null; // No more lines to read
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ namespace App\Services\DatasetReader;
|
||||
|
||||
use App\Services\CsvReader;
|
||||
|
||||
class RandomOrderDataSetReader implements IDataSetReader {
|
||||
class RandomOrderDataSetReader implements IDataSetReader
|
||||
{
|
||||
public array $lines = [];
|
||||
|
||||
private array $currentLines = [];
|
||||
|
||||
private int $lastReadLineIndex = -1;
|
||||
@@ -36,7 +38,7 @@ class RandomOrderDataSetReader implements IDataSetReader {
|
||||
}
|
||||
}
|
||||
|
||||
public function getNextLine(): array | null
|
||||
public function getNextLine(): ?array
|
||||
{
|
||||
if (empty($this->currentLines)) {
|
||||
return null; // No more lines to read
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace App\Services\IterationEventBuffer;
|
||||
|
||||
interface IPerceptronIterationEventBuffer {
|
||||
interface IPerceptronIterationEventBuffer
|
||||
{
|
||||
public function flush(): void;
|
||||
|
||||
public function flush(): void ;
|
||||
|
||||
public function addIteration(int $iteration, int $exampleIndex, float $error, array $synaptic_weights): void ;
|
||||
public function addIteration(int $iteration, int $exampleIndex, float $error, array $synaptic_weights): void;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
namespace App\Services\IterationEventBuffer;
|
||||
|
||||
class PerceptronIterationEventBuffer implements IPerceptronIterationEventBuffer {
|
||||
class PerceptronIterationEventBuffer implements IPerceptronIterationEventBuffer
|
||||
{
|
||||
private $data;
|
||||
|
||||
private int $nextSizeIncreaseThreshold;
|
||||
|
||||
private int $underSizeIncreaseCount = 0;
|
||||
|
||||
public function __construct(
|
||||
@@ -17,24 +20,25 @@ class PerceptronIterationEventBuffer implements IPerceptronIterationEventBuffer
|
||||
$this->nextSizeIncreaseThreshold = $sizeIncreaseStart;
|
||||
}
|
||||
|
||||
public function flush(): void {
|
||||
public function flush(): void
|
||||
{
|
||||
event(new \App\Events\PerceptronTrainingIteration($this->data, $this->sessionId, $this->trainingId));
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
public function addIteration(int $epoch, int $exampleIndex, float $error, array $synaptic_weights): void {
|
||||
public function addIteration(int $epoch, int $exampleIndex, float $error, array $synaptic_weights): void
|
||||
{
|
||||
$this->data[] = [
|
||||
"epoch" => $epoch,
|
||||
"exampleIndex" => $exampleIndex,
|
||||
"error" => $error,
|
||||
"weights" => $synaptic_weights,
|
||||
'epoch' => $epoch,
|
||||
'exampleIndex' => $exampleIndex,
|
||||
'error' => $error,
|
||||
'weights' => $synaptic_weights,
|
||||
];
|
||||
|
||||
if ($this->underSizeIncreaseCount <= $this->sizeIncreaseStart) { // We can still send a single date because we are under the increase start threshold
|
||||
$this->underSizeIncreaseCount++;
|
||||
$this->flush();
|
||||
}
|
||||
else if (count($this->data) >= $this->nextSizeIncreaseThreshold) {
|
||||
} elseif (count($this->data) >= $this->nextSizeIncreaseThreshold) {
|
||||
$this->flush();
|
||||
$this->nextSizeIncreaseThreshold *= $this->sizeIncreaseFactor;
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
namespace App\Services\IterationEventBuffer;
|
||||
|
||||
class PerceptronLimitedEpochEventBuffer implements IPerceptronIterationEventBuffer {
|
||||
class PerceptronLimitedEpochEventBuffer implements IPerceptronIterationEventBuffer
|
||||
{
|
||||
private array $data;
|
||||
|
||||
private int $underSizeIncreaseCount = 0;
|
||||
|
||||
public function __construct(
|
||||
@@ -15,23 +17,26 @@ class PerceptronLimitedEpochEventBuffer implements IPerceptronIterationEventBuff
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
public function flush(): void {
|
||||
public function flush(): void
|
||||
{
|
||||
event(new \App\Events\PerceptronTrainingIteration($this->data, $this->sessionId, $this->trainingId));
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
public function addIteration(int $epoch, int $exampleIndex, float $error, array $synaptic_weights): void {
|
||||
public function addIteration(int $epoch, int $exampleIndex, float $error, array $synaptic_weights): void
|
||||
{
|
||||
$newData = [
|
||||
"epoch" => $epoch,
|
||||
"exampleIndex" => $exampleIndex,
|
||||
"error" => $error,
|
||||
"weights" => $synaptic_weights,
|
||||
'epoch' => $epoch,
|
||||
'exampleIndex' => $exampleIndex,
|
||||
'error' => $error,
|
||||
'weights' => $synaptic_weights,
|
||||
];
|
||||
|
||||
if ($this->underSizeIncreaseCount <= $this->sizeIncreaseStart) { // Special case where we need to send each iteration separately
|
||||
$this->underSizeIncreaseCount++;
|
||||
$this->data[] = $newData;
|
||||
$this->flush();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,8 +44,7 @@ class PerceptronLimitedEpochEventBuffer implements IPerceptronIterationEventBuff
|
||||
if ($this->data && $lastEpoch !== $epoch) { // Current Epoch has changed from the last one
|
||||
if ($lastEpoch % $this->epochInterval === 0) { // The last epoch need to be sent
|
||||
$this->flush(); // Flush all data from the previous epoch
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services\SynapticWeightsProvider;
|
||||
|
||||
interface ISynapticWeightsProvider {
|
||||
interface ISynapticWeightsProvider
|
||||
{
|
||||
public function generate(int $input_size): array;
|
||||
}
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
namespace App\Services\SynapticWeightsProvider;
|
||||
|
||||
class RandomSynapticWeights implements ISynapticWeightsProvider {
|
||||
class RandomSynapticWeights implements ISynapticWeightsProvider
|
||||
{
|
||||
public function generate(int $input_size): array
|
||||
{
|
||||
$weights = [];
|
||||
for ($i = 0; $i < $input_size + 1; $i++) { // +1 for bias weight
|
||||
$weights[] = rand(-100, 100) / 100; // Random weights between -1 and 1
|
||||
}
|
||||
|
||||
return $weights;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
namespace App\Services\SynapticWeightsProvider;
|
||||
|
||||
class ZeroSynapticWeights implements ISynapticWeightsProvider {
|
||||
class ZeroSynapticWeights implements ISynapticWeightsProvider
|
||||
{
|
||||
public function generate(int $input_size): array
|
||||
{
|
||||
$weights = [];
|
||||
for ($i = 0; $i < $input_size + 1; $i++) { // +1 for bias weight
|
||||
$weights[] = 0; // Zero weights
|
||||
}
|
||||
|
||||
return $weights;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ return [
|
||||
* Beyond this number of iterations, the broadcast will be splitted every x iterations,
|
||||
* x is limited_broadcast_number
|
||||
*/
|
||||
'limited_broadcast_iterations' => 200,
|
||||
'limited_broadcast_iterations' => 200,
|
||||
|
||||
/**
|
||||
* How much broadcasts is sent when in limmited broadcast mode
|
||||
*/
|
||||
'limited_broadcast_number' => 200,
|
||||
/**
|
||||
* How much broadcasts is sent when in limmited broadcast mode
|
||||
*/
|
||||
'limited_broadcast_number' => 200,
|
||||
|
||||
'broadcast_iteration_size' => 75,
|
||||
'broadcast_iteration_size' => 75,
|
||||
|
||||
];
|
||||
|
||||
@@ -11,8 +11,6 @@ const props = defineProps<{
|
||||
iterations: Iteration[];
|
||||
}>();
|
||||
|
||||
const page = usePage();
|
||||
|
||||
const epochErrorOnly = ref<boolean>(false);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\PerceptronController;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::post('perceptron/run', [PerceptronController::class, 'run'])->name('perceptron.run');
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
use Illuminate\Support\Facades\Broadcast;
|
||||
|
||||
Broadcast::channel(session()->getId() . '-perceptron-training', function ($user) {
|
||||
Broadcast::channel(session()->getId().'-perceptron-training', function ($user) {
|
||||
return $user;
|
||||
});
|
||||
|
||||
@@ -4,19 +4,13 @@ namespace Tests\Services\IterationEventBuffer;
|
||||
|
||||
use App\Services\IterationEventBuffer\IPerceptronIterationEventBuffer;
|
||||
|
||||
class DullIterationEventBuffer implements IPerceptronIterationEventBuffer {
|
||||
|
||||
class DullIterationEventBuffer implements IPerceptronIterationEventBuffer
|
||||
{
|
||||
public function __construct(
|
||||
|
||||
) {
|
||||
) {}
|
||||
|
||||
}
|
||||
public function flush(): void {}
|
||||
|
||||
public function flush(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
public function addIteration(int $epoch, int $exampleIndex, float $error, array $synaptic_weights): void {
|
||||
return;
|
||||
}
|
||||
public function addIteration(int $epoch, int $exampleIndex, float $error, array $synaptic_weights): void {}
|
||||
}
|
||||
|
||||
@@ -9,15 +9,14 @@ use Tests\Services\IterationEventBuffer\DullIterationEventBuffer;
|
||||
|
||||
class ADALINEPerceptronTest extends TrainingTestCase
|
||||
{
|
||||
|
||||
public function test_adaline_perceptron_training_logic_and()
|
||||
{
|
||||
$training = new ADALINEPerceptronTraining(
|
||||
datasetReader: new LinearOrderDataSetReader(public_path('data_sets/logic_and_gradient.csv')),
|
||||
learningRate: 0.03,
|
||||
maxEpochs: 10000,
|
||||
synapticWeightsProvider: new ZeroSynapticWeights(),
|
||||
iterationEventBuffer: new DullIterationEventBuffer(),
|
||||
synapticWeightsProvider: new ZeroSynapticWeights,
|
||||
iterationEventBuffer: new DullIterationEventBuffer,
|
||||
sessionId: 'test-session',
|
||||
trainingId: 'test-training',
|
||||
minError: 0.1251,
|
||||
@@ -57,8 +56,8 @@ class ADALINEPerceptronTest extends TrainingTestCase
|
||||
datasetReader: new LinearOrderDataSetReader(public_path('data_sets/table_2_10.csv')),
|
||||
learningRate: 0.0015,
|
||||
maxEpochs: 1000,
|
||||
synapticWeightsProvider: new ZeroSynapticWeights(),
|
||||
iterationEventBuffer: new DullIterationEventBuffer(),
|
||||
synapticWeightsProvider: new ZeroSynapticWeights,
|
||||
iterationEventBuffer: new DullIterationEventBuffer,
|
||||
sessionId: 'test-session',
|
||||
trainingId: 'test-training',
|
||||
// minError: 16.597077, // Impossible pour un dataset avec des labels -1 et 1 d'avoir une erreur moyenne supérieure à 2
|
||||
|
||||
@@ -9,15 +9,14 @@ use Tests\Services\IterationEventBuffer\DullIterationEventBuffer;
|
||||
|
||||
class GradientDescentPerceptronTest extends TrainingTestCase
|
||||
{
|
||||
|
||||
public function test_gradient_descent_perceptron_training_logic_and()
|
||||
{
|
||||
$training = new GradientDescentPerceptronTraining(
|
||||
datasetReader: new LinearOrderDataSetReader(public_path('data_sets/logic_and_gradient.csv')),
|
||||
learningRate: 0.2,
|
||||
maxEpochs: 100,
|
||||
synapticWeightsProvider: new ZeroSynapticWeights(),
|
||||
iterationEventBuffer: new DullIterationEventBuffer(),
|
||||
synapticWeightsProvider: new ZeroSynapticWeights,
|
||||
iterationEventBuffer: new DullIterationEventBuffer,
|
||||
sessionId: 'test-session',
|
||||
trainingId: 'test-training',
|
||||
minError: 0.125001,
|
||||
@@ -56,8 +55,8 @@ class GradientDescentPerceptronTest extends TrainingTestCase
|
||||
datasetReader: new LinearOrderDataSetReader(public_path('data_sets/table_2_10.csv')),
|
||||
learningRate: 0.0015,
|
||||
maxEpochs: 1000,
|
||||
synapticWeightsProvider: new ZeroSynapticWeights(),
|
||||
iterationEventBuffer: new DullIterationEventBuffer(),
|
||||
synapticWeightsProvider: new ZeroSynapticWeights,
|
||||
iterationEventBuffer: new DullIterationEventBuffer,
|
||||
sessionId: 'test-session',
|
||||
trainingId: 'test-training',
|
||||
// minError: 16.388103, // Impossible pour un dataset avec des labels -1 et 1 d'avoir une erreur moyenne supérieure à 2
|
||||
|
||||
@@ -9,15 +9,14 @@ use Tests\Services\IterationEventBuffer\DullIterationEventBuffer;
|
||||
|
||||
class SimplePerceptronTest extends TrainingTestCase
|
||||
{
|
||||
|
||||
public function test_simple_perceptron_training_logic_and()
|
||||
{
|
||||
$training = new SimpleBinaryPerceptronTraining(
|
||||
datasetReader: new LinearOrderDataSetReader(public_path('data_sets/logic_and.csv')),
|
||||
learningRate: 1.0,
|
||||
maxEpochs: 100,
|
||||
synapticWeightsProvider: new ZeroSynapticWeights(),
|
||||
iterationEventBuffer: new DullIterationEventBuffer(),
|
||||
synapticWeightsProvider: new ZeroSynapticWeights,
|
||||
iterationEventBuffer: new DullIterationEventBuffer,
|
||||
sessionId: 'test-session',
|
||||
trainingId: 'test-training',
|
||||
);
|
||||
|
||||
@@ -13,7 +13,6 @@ class TrainingTestCase extends TestCase
|
||||
{
|
||||
$training->start();
|
||||
|
||||
|
||||
// Assert that the final synaptic weights are as expected withing the margin of error
|
||||
// $finalWeights = $training->getSynapticWeights();
|
||||
// $this->assertEqualsWithDelta($expectedWeights, $finalWeights, $marginOfError, "Final synaptic weights do not match expected values.");
|
||||
@@ -21,5 +20,4 @@ class TrainingTestCase extends TestCase
|
||||
// Assert that the number of epochs taken is as expected
|
||||
$this->assertEquals($expectedEpochs, $training->getEpoch(), "Expected training to take $expectedEpochs epochs, but it took {$training->getEpoch()} epochs.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user