Conversation
…neural network layers.
…hensive unit tests and fixed broken source file link in the documentation
…d updated documentation with fixed source file link. Added `Parametric` interface to define parameterized layers.
…ith `NumPower` utilities
…ical stability during inference, and gradient computation logic
…ical stability during inference, and gradient computation logic
…itional tests and updated shape handling
…itional tests and updated shape handling
…interface definition for output layers.
…entation and unit tests
…d/backward passes
…ence/backward passes, unit tests, and documentation updates
…ith `NumPower` utilities
…rd/inference/backward passes, unit tests
…ference/backward passes, unit tests
…rward/inference/backward passes, unit tests
There was a problem hiding this comment.
Pull request overview
This pull request converts neural network layers and optimizers to use the NumPower library for numerical operations. The changes include implementing new optimizer classes (StepDecay, RMSProp, Momentum, Cyclical, Adam, AdaMax, AdaGrad), new layer implementations (Swish, Placeholder1D, PReLU, Noise, Multiclass, Dropout, Dense, Continuous, Binary, BatchNorm, Activation), updating tests to use PHPUnit attributes, and reorganizing code into namespaced subdirectories with corresponding documentation updates.
Key Changes
- Migration from tensor library to NumPower for all neural network operations
- Reorganization of optimizers and layers into subdirectory namespaces (e.g.,
Adam/Adam.phpinstead ofAdam.php) - Conversion of PHPUnit test annotations to attributes (
#[Test],#[TestDox], etc.)
Reviewed changes
Copilot reviewed 71 out of 71 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Specifications/SamplesAreCompatibleWithDistanceTest.php | Updated to use PHPUnit attributes for test annotations |
| tests/NeuralNet/Optimizers/Stochastic/StochasticTest.php | Refactored test with data providers and PHPUnit attributes |
| tests/NeuralNet/Optimizers/StepDecay/StepDecayTest.php | New comprehensive test suite for StepDecay optimizer |
| tests/NeuralNet/Optimizers/RMSProp/RMSPropTest.php | New test suite covering RMSProp optimizer with NumPower |
| tests/NeuralNet/Optimizers/Momentum/MomentumTest.php | New test suite for Momentum optimizer |
| tests/NeuralNet/Optimizers/Cyclical/CyclicalTest.php | New test suite for Cyclical learning rate optimizer |
| tests/NeuralNet/Optimizers/Adam/AdamTest.php | New comprehensive Adam optimizer tests |
| tests/NeuralNet/Optimizers/AdaMax/AdaMaxTest.php | New AdaMax optimizer test suite |
| tests/NeuralNet/Optimizers/AdaGrad/AdaGradTest.php | New AdaGrad optimizer tests |
| tests/NeuralNet/Layers/*/Test.php (multiple) | New test suites for all layer types using NumPower |
| tests/NeuralNet/FeedForwardTest.php | Updated to use PHPUnit attributes |
| tests/Helpers/GraphvizTest.php | Updated to use PHPUnit attributes |
| src/Traits/AssertsShapes.php | Updated exception import and error message |
| src/NeuralNet/Parameters/Parameter.php | Formatting improvements and method signature updates |
| src/NeuralNet/Optimizers/*/Optimizers.php (multiple) | New optimizer implementations using NumPower |
| src/NeuralNet/Layers/*/Layers.php (multiple) | New layer implementations using NumPower |
| src/NeuralNet/Initializers/*/Initializers.php (multiple) | Added explicit loc parameter to NumPower calls |
| phpunit.xml | Increased memory limit to 256M |
| docs/neural-network/**/*.md (multiple) | Updated file paths and added mathematical formulations |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 72 out of 72 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
andrewdalpino
left a comment
There was a problem hiding this comment.
This looks great @apphp, mostly good to go I just had a few questions before I approved.
| * | ||
| * @var int | ||
| */ | ||
| protected const int AXIS_SAMPLES = 0; |
There was a problem hiding this comment.
I would just double check that this is correct and not the other way around. From my understanding the input to each layer is shaped [num_features, num_samples] which would mean that axis 0 is the features not the samples.
There was a problem hiding this comment.
Done. It was rewritten to use the convention [num_features, num_samples], meaning features-first.
| $m = $dOut->shape()[0]; | ||
|
|
||
| // Compute gradient per formula: dX = (dXHat * m - dXHatSigma - xHat * xHatSigma) * (stdInv / m) | ||
| return NumPower::multiply( |
There was a problem hiding this comment.
Can we break this apart to help make it more human-readable?
| { | ||
| $n = $output->shape()[1]; | ||
|
|
||
| if ($this->costFn instanceof CrossEntropy) { |
There was a problem hiding this comment.
I don't remember if I left a comment here or not in the original implementation, but it's worth noting to future developers that this is an optimization specific to the Binary Cross Entropy loss function. Through some clever mathematical cancellation tricks this gradient calculation is just a simple subtraction operation.
There was a problem hiding this comment.
No, but this is was a good point - I added comment for both implementations.
|
|
||
| if ($this->biases) { | ||
| // Reshape bias vector [fanOut] to column [fanOut, 1] to match output [fanOut, n] | ||
| $bias = NumPower::reshape($this->biases->param(), [$this->neurons, 1]); |
There was a problem hiding this comment.
Was this reshaping required in the original Tensor code?
There was a problem hiding this comment.
No, original Tensor code didnt need it, but NumPower version does to get correct bias broadcasting across the batch dimension.
This is because in the NumPower NumPower::add($output, $biasVector) does not reliably broadcast a 1-d vector across the second dimension
There was a problem hiding this comment.
That's great to know, thanks!
| // Gradient of the loss with respect to beta | ||
| // dL/dbeta = sum_over_batch(dL/dy * dy/dbeta) | ||
| // Here we use a simplified formulation: dL/dbeta ~ sum(dOut * input) | ||
| $dBetaFull = NumPower::multiply($dOut, $this->input); |
There was a problem hiding this comment.
Interesting comment, you know I'm not entirely sure I had the original gradient calculation 100% correct in the first place.
There was a problem hiding this comment.
Do you want me refactor this calculation?
There was a problem hiding this comment.
Let's leave it for now as these change are more about converting rather than fixing. But if indeed the calculation is wrong then we'll fix it in a followup.
…atures, num_samples]
…tropy loss function
|
At some point we should resolve the static analysis warnings as well |
No description provided.