Skip to content

Custom Modules and Layers

Krishanth edited this page Oct 15, 2026 · 1 revision

Custom Modules and Layers

EveryO — Extensible Neural Network Engineering

Design · Implement · Differentiate · Validate · Reuse

EveryO Extensibility Python License

An engineering guide to building reusable neural network components using EveryO's module system and automatic differentiation engine.

Home · Neural Networks · Automatic Differentiation · API Reference


Repository: krishanth7/EveryO

Maintainer: @krishanth7

Audience: Framework contributors, ML developers, researchers

Document Type: Extensibility and implementation guidance

Important

Compatibility Notice

EveryO is an experimental NumPy-based neural computing framework. Custom modules should use the public APIs supported by the installed release.

The examples below demonstrate conventional module composition using documented EveryO abstractions. More specialized capabilities, including module registration and serialization, must be checked against the current implementation.

A custom module is not automatically serializable, ONNX-exportable, CUDA-compatible, or supported by every optimizer and training workflow.


Table of Contents

  1. Introduction
  2. Module Architecture
  3. Prerequisites
  4. Creating a Custom Module
  5. Trainable Parameters
  6. Parameter Registration
  7. Forward Computation
  8. Automatic Differentiation
  9. Custom Linear Layers
  10. Activation Modules
  11. Residual Connections
  12. Sequential Composition
  13. Normalization Layers
  14. Dropout and Regularization
  15. Custom Loss Functions
  16. Shape Validation
  17. Gradient Verification
  18. Training Custom Modules
  19. Serialization
  20. ONNX Compatibility
  21. CUDA Considerations
  22. Performance Engineering
  23. Testing Strategy
  24. Debugging
  25. Security Considerations
  26. Documentation Standards
  27. Contribution Workflow
  28. Implementation Checklist
  29. Advanced Exercises
  30. Official Resources

1. Introduction

EveryO provides a module system for constructing neural networks from reusable components.

Custom modules allow developers to implement architectures beyond predefined layers while preserving the framework's tensor and differentiation abstractions.

1.1 Objectives

A well-designed custom module should provide:

  • Clear mathematical behavior.
  • Predictable input and output shapes.
  • Proper parameter management.
  • Differentiable forward computation where applicable.
  • Reliable tests.
  • Understandable documentation.
  • Explicit compatibility limitations.

1.2 Development Workflow

       DEFINE MATHEMATICS
                |
                v
         DESIGN MODULE
                |
                v
       REGISTER PARAMETERS
                |
                v
       IMPLEMENT FORWARD
                |
                v
         VALIDATE SHAPES
                |
                v
         CHECK GRADIENTS
                |
                v
         INTEGRATE MODEL
                |
                v
         RUN UNIT TESTS
                |
                v
       DOCUMENT LIMITATIONS

2. Module Architecture

EveryO provides abstractions including:

  • Module
  • Parameter
  • Sequential
  • Linear
  • ReLU

These form the foundation of reusable neural network components.

2.1 Module Responsibilities

A module typically manages:

  1. Trainable parameters.
  2. Child modules.
  3. Forward computation.
  4. Training and evaluation modes.
  5. Parameter discovery.

2.2 Conceptual Structure

                MODULE
                   |
          +--------+--------+
          |        |        |
          v        v        v
      PARAMETERS  CHILD   FORWARD
                  MODULES  LOGIC
          |        |        |
          +--------+--------+
                   |
                   v
               OUTPUT
                   |
                   v
               AUTOGRAD

3. Prerequisites

3.1 Install EveryO

git clone https://github.com/krishanth7/EveryO.git

cd EveryO

python -m pip install -e ".[dev]"

3.2 Verify Installation

everyo info

everyo doctor

3.3 Required Knowledge

Readers should understand:

  • Python classes.
  • NumPy.
  • Matrix multiplication.
  • Gradient descent.
  • Tensor shapes.
  • Automatic differentiation.

4. Creating a Custom Module

A custom module can combine existing EveryO layers.

4.1 Example: Two-Layer Network

import everyo as eo


class TwoLayerNetwork(eo.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super().__init__()

        self.fc1 = eo.Linear(input_size, hidden_size)
        self.activation = eo.ReLU()
        self.fc2 = eo.Linear(hidden_size, output_size)

    def forward(self, x):
        x = self.fc1(x)
        x = self.activation(x)
        return self.fc2(x)


model = TwoLayerNetwork(
    input_size=4,
    hidden_size=16,
    output_size=2,
)

x = eo.tensor([
    [1.0, 2.0, 3.0, 4.0],
])

output = model(x)

print(output.shape)

Expected shape:

(1, 2)

4.2 Design Recommendations

  • Call the parent constructor.
  • Store child modules as instance attributes.
  • Keep forward logic understandable.
  • Document expected shapes.
  • Avoid unnecessary state mutation.

5. Trainable Parameters

A trainable parameter is a tensor whose values are updated during optimization.

5.1 Mathematical Model

For a linear transformation:

[ Y=XW+b ]

where:

  • (X): Input tensor.
  • (W): Trainable weight matrix.
  • (b): Trainable bias.
  • (Y): Output tensor.

5.2 Parameter Requirements

A trainable parameter should:

  • Participate in gradient computation.
  • Be discoverable by the optimizer.
  • Have a documented shape.
  • Be initialized appropriately.

5.3 Recommended Practice

Prefer framework-provided parameter abstractions over manually managing unrelated NumPy arrays.


6. Parameter Registration

Parameter registration enables a model to expose trainable values to optimizers.

6.1 Parameter Discovery

parameters = list(model.parameters())

print("Parameter tensors:", len(parameters))

6.2 Why Registration Matters

Unregistered parameters may not be updated during training.

6.3 Verification

For a custom module:

  1. Create the module.
  2. Inspect its parameters.
  3. Verify expected parameter shapes.
  4. Run a forward pass.
  5. Run backward propagation.
  6. Confirm gradients are available.

6.4 Nested Modules

When composing modules, verify that child-module parameters are included in the parent module's parameter collection.


7. Forward Computation

The forward method defines how input data is transformed.

7.1 Example

def forward(self, x):
    x = self.fc1(x)
    x = self.activation(x)
    return self.fc2(x)

7.2 Recommended Rules

  • Use documented tensor operations.
  • Preserve gradient tracking.
  • Avoid unexpected input mutation.
  • Maintain consistent shape contracts.
  • Keep forward computation deterministic when appropriate.

7.3 Avoid Silent Shape Changes

A layer should not unexpectedly flatten, transpose, or broadcast data without documenting that behavior.


8. Automatic Differentiation

EveryO's autograd engine tracks supported differentiable tensor operations.

8.1 Example

import everyo as eo

x = eo.tensor(
    [3.0],
    requires_grad=True,
)

y = x * x

y.backward()

print(x.grad)

Expected gradient:

[6.]

8.2 Chain Rule

[ \frac{dy}{dx}

\frac{dy}{du} \frac{du}{dx} ]

8.3 Custom Module Principle

A custom module built entirely from supported differentiable EveryO operations can use the existing autograd engine.

8.4 Important Limitation

A new low-level mathematical operation is not automatically differentiable merely because it is called inside a module.

It may require additional autograd implementation work.


9. Custom Linear Layers

A linear layer computes:

[ Y=XW+b ]

9.1 Shape Contract

For:

[ X\in\mathbb{R}^{B\times I} ]

and:

[ W\in\mathbb{R}^{I\times O} ]

the output is:

[ Y\in\mathbb{R}^{B\times O} ]

where:

  • (B): Batch size.
  • (I): Input features.
  • (O): Output features.

9.2 Reference Implementation

EveryO already provides Linear.

import everyo as eo

layer = eo.Linear(8, 16)

9.3 Customization Strategy

When extending linear behavior:

  1. Define the mathematical change.
  2. Decide whether composition is sufficient.
  3. Validate the output shape.
  4. Check gradients.
  5. Compare against a reference.

9.4 Avoid Reinventing Existing Layers

Use built-in layers when they already provide the required behavior.


10. Activation Modules

Activation functions introduce nonlinear transformations.

10.1 ReLU

[ ReLU(x)=\max(0,x) ]

10.2 Sigmoid

[ \sigma(x)=\frac{1}{1+e^{-x}} ]

10.3 Tanh

[ \tanh(x) ]

10.4 Example Composition

import everyo as eo

model = eo.Sequential(
    eo.Linear(8, 16),
    eo.ReLU(),
    eo.Linear(16, 4),
)

10.5 Custom Activation Guidance

For a new activation:

  • Define its mathematical formula.
  • Define behavior at nondifferentiable points.
  • Implement the forward computation.
  • Validate gradients.
  • Test extreme input magnitudes.

11. Residual Connections

Residual connections allow a module to add its input to a transformed representation.

11.1 Formula

[ y=x+F(x) ]

where (F(x)) is a learned transformation.

11.2 Example

import everyo as eo


class ResidualBlock(eo.Module):
    def __init__(self, features):
        super().__init__()

        self.fc1 = eo.Linear(features, features)
        self.activation = eo.ReLU()
        self.fc2 = eo.Linear(features, features)

    def forward(self, x):
        residual = x

        y = self.fc1(x)
        y = self.activation(y)
        y = self.fc2(y)

        return residual + y


block = ResidualBlock(features=8)

x = eo.tensor([
    [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0],
])

output = block(x)

print(output.shape)

Expected shape:

(1, 8)

11.3 Shape Requirement

The residual and transformed tensors must have compatible shapes.

11.4 Validation

Verify gradients through both the residual path and the transformation path.


12. Sequential Composition

Sequential combines modules into an ordered computation pipeline.

12.1 Example

import everyo as eo

model = eo.Sequential(
    eo.Linear(16, 32),
    eo.ReLU(),
    eo.Linear(32, 16),
    eo.ReLU(),
    eo.Linear(16, 4),
)

12.2 Computational Flow

INPUT (16)
    |
    v
LINEAR (32)
    |
    v
   RELU
    |
    v
LINEAR (16)
    |
    v
   RELU
    |
    v
LINEAR (4)
    |
    v
 OUTPUT

12.3 When to Use Sequential

Use it for architectures that naturally form a simple linear chain.

12.4 When to Use a Custom Module

Use a custom module when the architecture requires:

  • Multiple branches.
  • Residual connections.
  • Shared parameters.
  • Conditional behavior.
  • Multiple intermediate outputs.

13. Normalization Layers

EveryO includes normalization components such as:

  • BatchNorm1D
  • BatchNorm2D
  • LayerNorm

13.1 Normalization Formula

[ \hat{x}= \frac{x-\mu}{\sqrt{\sigma^2+\epsilon}} ]

13.2 Custom Module Considerations

Normalization behavior may depend on:

  • Training mode.
  • Evaluation mode.
  • Batch statistics.
  • Running statistics.
  • Normalization dimensions.

13.3 Validation

Test:

  • Forward values.
  • Gradient correctness.
  • Shape handling.
  • Near-zero variance.
  • Training/evaluation differences.

14. Dropout and Regularization

Dropout is a regularization technique that randomly disables selected activations during training.

14.1 Typical Purpose

Reduce dependence on individual activations and improve generalization in suitable models.

14.2 Module Composition

import everyo as eo

model = eo.Sequential(
    eo.Linear(16, 32),
    eo.ReLU(),
    eo.Dropout(0.2),
    eo.Linear(32, 4),
)

14.3 Mode Validation

Verify that dropout behaves appropriately in training and evaluation modes.

14.4 Best Practice

Do not assume that adding dropout always improves model quality.

Evaluate its impact using held-out validation data.


15. Custom Loss Functions

Loss functions quantify prediction error.

15.1 Mean Squared Error

[ MSE= \frac{1}{N} \sum_{i=1}^{N}(y_i-\hat{y}_i)^2 ]

15.2 Example Differentiable Loss

def custom_mse(prediction, target):
    difference = prediction - target

    return (difference * difference).mean()

This example uses basic differentiable tensor operations.

15.3 Validation

Verify:

  • Output scalar behavior.
  • Reduction semantics.
  • Gradient correctness.
  • Input shape compatibility.
  • Numerical stability.

15.4 Important Principle

A custom loss should not silently change the expected meaning of targets or predictions.


16. Shape Validation

Shape contracts are essential for reliable custom modules.

16.1 Example

def validate_input_shape(x, expected_features):
    if x.shape[-1] != expected_features:
        raise ValueError(
            f"Expected {expected_features} features, "
            f"received {x.shape[-1]}"
        )

16.2 Recommended Checks

  • Number of dimensions.
  • Feature dimension.
  • Batch compatibility.
  • Broadcasting assumptions.
  • Output dimensions.

16.3 Shape Documentation

Document shapes using consistent notation:

Input:  (batch, input_features)

Output: (batch, output_features)

17. Gradient Verification

Custom modules should be tested against numerical gradients.

17.1 Central Difference

[ g_{\text{numeric}}= \frac{f(x+h)-f(x-h)}{2h} ]

17.2 Analytical Gradient

For:

[ f(x)=x^2 ]

[ f'(x)=2x ]

17.3 Example

def f(x):
    return x * x


x = 3.0
h = 1e-5

numeric = (
    f(x + h) - f(x - h)
) / (2 * h)

analytic = 2 * x

print("Numeric:", numeric)
print("Analytic:", analytic)

17.4 Verification Requirements

  • Compare against an independent reference.
  • Test multiple input magnitudes.
  • Avoid nondifferentiable points.
  • Use justified tolerances.
  • Record dtype and test conditions.

18. Training Custom Modules

Custom modules can be integrated into training workflows when their parameters and operations are compatible.

18.1 Example Model

import everyo as eo

model = TwoLayerNetwork(
    input_size=4,
    hidden_size=16,
    output_size=2,
)

optimizer = eo.Adam(
    model.parameters(),
    lr=0.001,
)

loss_fn = eo.CrossEntropyLoss()

18.2 Training Workflow

DATA BATCH
    |
    v
CUSTOM MODULE
    |
    v
PREDICTION
    |
    v
LOSS FUNCTION
    |
    v
BACKWARD PASS
    |
    v
OPTIMIZER STEP

18.3 Verification

Before long training runs:

  1. Confirm the forward pass.
  2. Confirm loss computation.
  3. Verify parameter gradients.
  4. Run a short training test.
  5. Check whether loss changes as expected.

19. Serialization

EveryO supports .evo model archives.

19.1 Save a Supported Model

import everyo as eo

eo.save(model, "custom_model.evo")

19.2 Restore

restored = eo.load("custom_model.evo")

19.3 Custom Module Registration

Custom module types may require registration using EveryO's documented @register_module mechanism.

19.4 Important Compatibility Requirement

Do not assume that an arbitrary Python subclass is automatically reconstructible from an .evo archive.

Review:

  • Module registration.
  • Constructor metadata.
  • Supported parameter serialization.
  • Restoration behavior.

19.5 Round-Trip Test

Compare model outputs before and after serialization.

19.6 Security

Treat untrusted archives as untrusted input, even though the documented format avoids pickle execution.


20. ONNX Compatibility

ONNX export is available for supported model structures and operations.

20.1 Install Dependencies

python -m pip install -e ".[onnx]"

20.2 Important Limitation

A custom EveryO module is not automatically ONNX-exportable.

20.3 Compatibility Checklist

  • All operations are supported.
  • Input shapes are valid.
  • Model is in evaluation mode.
  • Export succeeds.
  • ONNX Runtime executes the graph.
  • Outputs agree within justified tolerances.

20.4 Tracing

Tracing may support additional operation paths, but it captures the executed path and can encode fixed shape or control-flow assumptions.


21. CUDA Considerations

EveryO includes optional CUDA functionality.

21.1 Availability

import everyo as eo

print(eo.cuda.is_available())

21.2 Custom Module Compatibility

A custom module is not automatically GPU-compatible.

21.3 Requirements

CUDA support depends on the operations and execution path implemented by the framework.

21.4 Validation

When testing CUDA:

  • Verify supported operations.
  • Compare against CPU references.
  • Record hardware details.
  • Measure transfer overhead.
  • Test on actual compatible hardware.

21.5 Autograd Limitation

Do not assume GPU-resident tensor operations automatically integrate with EveryO's standard autograd graph.


22. Performance Engineering

22.1 Profile Before Optimizing

Use profiling to identify actual bottlenecks.

22.2 Example

import everyo as eo

with eo.profile() as profiler:
    output = model(input_tensor)

print(profiler.summary())

The model and input tensor must be initialized beforehand.

22.3 Optimization Priorities

Consider:

  • Avoiding unnecessary copies.
  • Reducing redundant operations.
  • Improving memory locality.
  • Using suitable tensor shapes.
  • Minimizing unnecessary device transfers.

22.4 Correctness Requirement

Every optimization should preserve validated mathematical behavior.


23. Testing Strategy

Custom modules require multiple levels of testing.

23.1 Unit Tests

Verify isolated forward computations.

23.2 Gradient Tests

Verify backward computations.

23.3 Shape Tests

Test valid and invalid dimensions.

23.4 Integration Tests

Test custom modules inside larger models.

23.5 Serialization Tests

Test save/load behavior when supported.

23.6 Backend Tests

Test optional backends only where the relevant hardware or dependencies are available.

23.7 Example Test

import everyo as eo


def test_residual_block_shape():
    block = ResidualBlock(features=4)

    x = eo.tensor([
        [1.0, 2.0, 3.0, 4.0],
    ])

    output = block(x)

    assert output.shape == (1, 4)

23.8 Run Tests

python -m pytest -q

24. Debugging

24.1 Common Problems

Problem Possible Cause Recommended Action
Missing parameters Registration issue Inspect parameters()
Shape mismatch Incorrect dimensions Validate shape contracts
Missing gradients Unsupported operation Check autograd path
NaN outputs Numerical instability Inspect intermediate values
Serialization failure Unregistered module Review registration
ONNX export failure Unsupported operation Check exporter support
CUDA failure Unsupported backend path Verify hardware and operations
Poor training Architecture or optimization issue Test a small baseline

24.2 Debugging Workflow

REPRODUCE ERROR
       |
       v
MINIMIZE EXAMPLE
       |
       v
INSPECT SHAPES
       |
       v
CHECK PARAMETERS
       |
       v
VERIFY FORWARD
       |
       v
VERIFY GRADIENTS
       |
       v
IMPLEMENT FIX
       |
       v
ADD REGRESSION TEST

25. Security Considerations

25.1 Untrusted Inputs

Validate external data and model archives.

25.2 Native Extensions

Custom C++ or CUDA extensions require additional memory-safety review.

25.3 Dependency Management

Avoid introducing unnecessary dependencies.

25.4 No Secrets in Source

Never commit private credentials or tokens.

25.5 Vulnerability Reporting

Report security vulnerabilities privately:

GitHub Security Advisories


26. Documentation Standards

Each custom module should document:

  1. Purpose.
  2. Mathematical definition.
  3. Constructor parameters.
  4. Input shapes.
  5. Output shapes.
  6. Trainable parameters.
  7. Example usage.
  8. Numerical limitations.
  9. Backend compatibility.
  10. Serialization compatibility.

26.1 Example Documentation Template

# Custom Layer Name

## Purpose

Explain the layer.

## Mathematical Definition

Provide the formula.

## Constructor

Document arguments.

## Input

Shape and dtype.

## Output

Shape and dtype.

## Example

Provide runnable Python.

## Limitations

Document unsupported behavior.

## Tests

Explain validation coverage.

27. Contribution Workflow

Contributors can propose new layers through the repository's normal contribution process.

27.1 Before Implementation

  • Review existing functionality.
  • Search for related issues.
  • Define the mathematical specification.
  • Identify expected API behavior.

27.2 During Implementation

  • Keep changes focused.
  • Add tests.
  • Verify gradients.
  • Document compatibility.
  • Avoid unnecessary dependencies.

27.3 Before Pull Request

Run:

python -m pytest -q

ruff check .

ruff format --check .

27.4 Submit for Review

Use the repository's pull request workflow.

Maintainer approval is required for integration; submitting a PR does not guarantee acceptance.


28. Implementation Checklist

Architecture

  • Module purpose is clear.
  • Mathematical definition is documented.
  • Input/output shapes are defined.
  • Existing layers are reused where appropriate.

Parameters

  • Parameters are registered.
  • Shapes are correct.
  • Initialization is appropriate.
  • Optimizers can discover trainable parameters.

Autograd

  • Forward operations are differentiable where required.
  • Gradients have correct shapes.
  • Numerical gradient checks pass.
  • Shared computation paths are tested.

Reliability

  • Unit tests pass.
  • Invalid inputs are handled.
  • Numerical edge cases are tested.
  • Training integration is verified.

Interoperability

  • Serialization support is evaluated.
  • ONNX compatibility is evaluated.
  • CUDA limitations are documented.
  • Optional dependencies are declared.

Documentation

  • Public API is documented.
  • Examples are included.
  • Limitations are disclosed.
  • Contribution guidance is followed.

29. Advanced Exercises

Exercise 1 — Residual Block

Implement and test a residual block.

Deliverable: Forward and gradient tests.

Exercise 2 — Custom Activation

Create a differentiable activation using supported tensor operations.

Deliverable: Mathematical definition and numerical gradient verification.

Exercise 3 — Custom Loss

Implement a regression loss using EveryO tensor operations.

Deliverable: Unit tests and analytical reference comparison.

Exercise 4 — Nested Module

Create a network with several reusable submodules.

Deliverable: Parameter registration test.

Exercise 5 — Serialization

Register a supported custom module and test save/load behavior.

Deliverable: Round-trip verification report.

Exercise 6 — ONNX Compatibility

Evaluate whether a custom architecture can be exported.

Deliverable: Compatibility report with limitations.

Exercise 7 — Performance

Profile a custom module and investigate its most expensive operation.

Deliverable: Reproducible benchmark results.


30. Official Resources

Resource Link
EveryO Repository GitHub
README README.md
API Reference API Reference Wiki
Neural Networks Neural Networks Wiki
Automatic Differentiation Automatic Differentiation Wiki
Model Serialization Model Serialization Wiki
Numerical Validation Numerical Accuracy and Validation
Advanced Tutorials Advanced Tutorials
Testing Testing and Quality Assurance
Contributing CONTRIBUTING.md
GitHub Issues Issues
GitHub Discussions Discussions

Custom Modules and Layers — Documentation Prepared

Next Recommended Page: Model Deployment and Inference →

Home · Neural Networks · Advanced Tutorials


EveryO — Open Machine Learning. Built for Developers.

Project Maintainer: @krishanth7

Open Source · MIT Licensed · Community Driven

© 2026 EveryO Contributors

Clone this wiki locally