Skip to content

Commit bdb4b04

Browse files
committed
refactor(v1.0.0): restructure project for v1.0 release
- Rename package src/ -> nnlib/ (imports: from nnlib import ...) - Replace setup.py with pyproject.toml (PEP 517/518) - Add LICENSE (MIT), CHANGELOG.md - Move siamese_network.py from src/ to examples/ - Remove sys.path hacks from tests and examples - Update CI: Python 3.9-3.12, add ruff lint job - Clean up README and AGENTS.md
1 parent 7a4d689 commit bdb4b04

29 files changed

Lines changed: 376 additions & 239 deletions

.github/workflows/python-app.yml

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Python application
1+
name: CI
22

33
on:
44
push:
@@ -7,21 +7,30 @@ on:
77
branches: ["main"]
88

99
jobs:
10-
build:
10+
lint:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-python@v5
15+
with:
16+
python-version: "3.12"
17+
- run: pip install ruff
18+
- run: ruff check nnlib/ tests/
19+
20+
test:
1121
runs-on: ubuntu-latest
1222
strategy:
1323
matrix:
14-
python-version: ["3.8", "3.10", "3.12"]
24+
python-version: ["3.9", "3.10", "3.11", "3.12"]
1525
steps:
1626
- uses: actions/checkout@v4
1727
- name: Set up Python ${{ matrix.python-version }}
1828
uses: actions/setup-python@v5
1929
with:
2030
python-version: ${{ matrix.python-version }}
21-
- name: Install dependencies
31+
- name: Install package
2232
run: |
2333
python -m pip install --upgrade pip
24-
pip install -r requirements.txt
25-
- name: Test with unittest
26-
run: |
27-
python -m unittest discover tests -v
34+
pip install -e ".[dev]"
35+
- name: Run tests
36+
run: python -m unittest discover tests -v

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,7 @@ htmlcov/
2424

2525
# Modelos guardados
2626
*.pkl
27-
*.npz
27+
*.npz
28+
29+
# AI agent config
30+
AGENTS.md

CHANGELOG.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Changelog
2+
3+
Todos los cambios notables en este proyecto seran documentados en este archivo.
4+
5+
El formato se basa en [Keep a Changelog](https://keepachangelog.com/), y este proyecto adherise a [Semantic Versioning](https://semver.org/).
6+
7+
## [1.0.0] - 2026-08-10
8+
9+
### Added
10+
- Empaquetado moderno con `pyproject.toml` (PEP 517/518).
11+
- Archivo `LICENSE` (MIT).
12+
- Configuracion de linting con `ruff` en CI.
13+
- `CHANGELOG.md`.
14+
15+
### Changed
16+
- Paquete renombrado de `src` a `nnlib` (imports: `from nnlib import NeuralNetwork`).
17+
- Eliminados los `sys.path.insert` de tests y examples (ya no son necesarios con `pip install -e .`).
18+
- CI actualizado: matrix Python 3.9/3.10/3.11/3.12, instalacion con `pip install -e ".[dev]"`.
19+
- `siamese_network.py` movido de `src/` a `examples/`.
20+
- Python 3.8 eliminado del soporte (EOL).
21+
22+
### Removed
23+
- `setup.py` (reemplazado por `pyproject.toml`).
24+
25+
## [0.4.0] - Sin tag
26+
27+
### Added
28+
- `NeuralNetwork.build(input_shape)` propaga shapes y valida fail-fast.
29+
- `NeuralNetwork.save(dir) / load(dir)` con topology.json + weights.npz.
30+
- `to_json() / from_json()` en modelo y componentes.
31+
- `examples/siamese_network.py` verifica state isolation con pesos compartidos.
32+
- Tests: 51 a 68.
33+
34+
### Changed
35+
- Capas: `forward(x) -> (output, cache)` y `backward(d_output, cache) -> (d_input, grads_dict)`.
36+
- Capas: `parameters() -> Dict[str, ndarray]` reemplaza a `get_params()`.
37+
- Optimizadores: `apply_gradients(list_of_tuples)` reemplaza a `update(layers)`.
38+
- Losses: `BinaryCrossEntropy` y `CategoricalCrossEntropy` aceptan `from_logits`.
39+
- Softmax: backward implementa el Jacobiano completo.
40+
41+
### Fixed
42+
- Acoplamiento matematico oculto CCE/Softmax.
43+
- Estado mutable que rompia arquitecturas multi-entrada.
44+
- Serializacion fragil con pickle.
45+
- Validacion tardia de shapes.
46+
- Optimizador dependiente de `weights`/`biases` hardcodeados.
47+
48+
## [0.3.0] - Sin tag
49+
50+
### Added
51+
- API estilo Keras con `compile()`, `fit()`, `predict()`.
52+
- Optimizadores Adam, RMSprop, AdaGrad con gradient clipping.
53+
- Callbacks: EarlyStopping, ReduceLROnPlateau, ModelCheckpoint.
54+
- BatchNormalization.
55+
56+
## [0.2.0] - Sin tag
57+
58+
### Added
59+
- Vectorizacion completa de capas.
60+
- Inicializacion He, LeakyReLU, data shuffling.
61+
- BinaryCrossEntropy loss.
62+
63+
## [0.1.0] - Sin tag
64+
65+
### Added
66+
- Estructura base con Neuron, backpropagation, tests unitarios.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Alexis González (elJulioDev)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 46 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Librería de Deep Learning ligera, modular y **completamente vectorizada** en Python y NumPy. Pensada para producción: API estilo Keras, gradientes verificados numéricamente, persistencia portable sin pickle, caches externos para arquitecturas avanzadas.
44

5-
> **v0.4.0 — refactor arquitectónico.** Resuelve los 5 riesgos estructurales de v0.3: acoplamiento matemático oculto (Softmax↔CCE), estado mutable en capas (bloqueaba redes siamesas), serialización pickle-frágil, validación de shapes tardía, y fugas de abstracción en optimizadores. Ver `CHANGELOG` al final.
5+
> **v1.0.0 — lanzamiento estable.** Paquete renombrado a `nnlib`, empaquetado moderno con `pyproject.toml`, CI con linting, LICENSE MIT. Ver [CHANGELOG.md](CHANGELOG.md) para historial completo.
66
77
## Principios de Diseño
88

@@ -47,21 +47,23 @@ Librería de Deep Learning ligera, modular y **completamente vectorizada** en Py
4747

4848
```bash
4949
git clone https://github.com/elJulioDev/Neural_Network.git
50-
cd neural_network
50+
cd Neural_Network
5151
python -m venv venv
5252
source venv/bin/activate # Windows: venv\Scripts\activate
5353
pip install -e .
54-
python -m unittest discover tests -v
55-
python main.py
56-
python examples/multiclass_classification.py
57-
python examples/siamese_network.py
54+
```
55+
56+
Para desarrollo (incluye ruff y matplotlib):
57+
58+
```bash
59+
pip install -e ".[dev]"
5860
```
5961

6062
## Uso Rápido (API moderna estilo Keras)
6163

6264
```python
6365
import numpy as np
64-
from src import (
66+
from nnlib import (
6567
NeuralNetwork, Dense, Dropout, BatchNormalization,
6668
Adam, BinaryCrossEntropy, EarlyStopping,
6769
)
@@ -88,10 +90,6 @@ probs = 1.0 / (1.0 + np.exp(-logits))
8890

8991
## `from_logits` — por qué importa
9092

91-
**Problema en v0.3:** la derivada de `CategoricalCrossEntropy` asumía que la capa anterior era `Softmax`. Si terminabas con `Linear` o `ReLU` y seguías usando CCE, no había error — simplemente los gradientes salían mal y la red no convergía.
92-
93-
**Solución en v0.4:**
94-
9593
* **`from_logits=True`** (recomendado): capa final `Linear`, la loss aplica softmax/sigmoid internamente y usa el atajo estable `(pred - y) / N`.
9694
* **`from_logits=False`**: la capa anterior puede ser cualquier activación. Softmax propaga su Jacobiano real completo — matemáticamente correcto con cualquier loss.
9795

@@ -114,7 +112,7 @@ ex = np.exp(logits - logits.max(axis=1, keepdims=True))
114112
probs = ex / ex.sum(axis=1, keepdims=True)
115113
```
116114

117-
## Persistencia Portable (recomendada)
115+
## Persistencia Portable
118116

119117
```python
120118
model.save('my_model/')
@@ -125,14 +123,14 @@ model.save('my_model/')
125123
loaded = NeuralNetwork.load('my_model/')
126124
```
127125

128-
`topology.json` es inspeccionable, no ejecutable, y sobrevive a refactorizaciones internas. NO uses `save_model()` (pickle) en producción.
126+
`topology.json` es inspeccionable, no ejecutable, y sobrevive a refactorizaciones internas.
129127

130128
## Redes con capas compartidas (ej. siamesas)
131129

132-
Una misma instancia de capa puede procesar dos inputs distintos sin corromperse (en v0.3 era imposible). Ver `examples/siamese_network.py`.
130+
Una misma instancia de capa puede procesar dos inputs distintos sin corromperse. Ver `examples/siamese_network.py`.
133131

134132
```python
135-
from src.layer import Dense
133+
from nnlib.layer import Dense
136134
layer = Dense(4, 3, activation='relu')
137135

138136
out1, cache1 = layer.forward(x1)
@@ -159,7 +157,7 @@ model.fit(np.random.randn(5, 10), ...)
159157
## Ejemplo Producción con BatchNorm + Dropout + Callbacks
160158

161159
```python
162-
from src import (
160+
from nnlib import (
163161
NeuralNetwork, Dense, Dropout, BatchNormalization,
164162
Adam, L2, CategoricalCrossEntropy,
165163
EarlyStopping, ReduceLROnPlateau,
@@ -190,7 +188,7 @@ model.save('production_model/')
190188
## Integración en Django/Flask
191189

192190
```python
193-
from src import NeuralNetwork
191+
from nnlib import NeuralNetwork
194192
import numpy as np
195193

196194
ai_model = NeuralNetwork.load('/path/to/production_model/')
@@ -206,78 +204,50 @@ def predict_view(request):
206204
## Estructura del Proyecto
207205

208206
```text
209-
neural_network/
210-
├── src/
211-
│ ├── __init__.py
212-
│ ├── activations.py # Stateless: forward -> (out, cache)
207+
Neural_Network/
208+
├── nnlib/ # Paquete principal
209+
│ ├── __init__.py # API pública re-exportada
210+
│ ├── activations.py # Stateless: forward -> (out, cache)
213211
│ ├── callbacks.py
214-
│ ├── initializers.py # Con get_config para JSON
215-
│ ├── layer.py # Dense, Dropout, BatchNorm; parameters() dict
216-
│ ├── losses.py # from_logits en CCE/BCE
212+
│ ├── initializers.py # Con get_config para JSON
213+
│ ├── layer.py # Dense, Dropout, BatchNorm; parameters() dict
214+
│ ├── losses.py # from_logits en CCE/BCE
217215
│ ├── metrics.py
218-
│ ├── neural_network.py # Gestión externa de caches, build(), save/load
219-
│ ├── optimizers.py # Interfaz genérica (layer_id, name, param, grad)
216+
│ ├── neural_network.py # Gestión externa de caches, build(), save/load
217+
│ ├── optimizers.py # Interfaz genérica (layer_id, name, param, grad)
220218
│ ├── regularizers.py
221219
│ └── utils.py
222-
├── tests/ # 68 tests
223-
│ ├── test_activations.py # Stateless, Softmax Jacobiano, roundtrip config
224-
│ ├── test_gradient_check.py # Valida backprop numéricamente
225-
│ ├── test_layer.py # Including state isolation test
226-
│ ├── test_losses.py # Including from_logits path
227-
│ ├── test_model.py # Integración + persistencia JSON+NPZ
228-
│ └── test_optimizers.py # Interfaz genérica
220+
├── tests/ # 68 tests
221+
│ ├── test_activations.py # Stateless, Softmax Jacobiano, roundtrip config
222+
│ ├── test_gradient_check.py # Valida backprop numéricamente
223+
│ ├── test_layer.py # Including state isolation test
224+
│ ├── test_losses.py # Including from_logits path
225+
│ ├── test_model.py # Integración + persistencia JSON+NPZ
226+
│ └── test_optimizers.py # Interfaz genérica
229227
├── examples/
230228
│ ├── multiclass_classification.py
231-
│ └── siamese_network.py # Demuestra state isolation
232-
├── main.py # Demo XOR
233-
├── requirements.txt
234-
├── setup.py
229+
│ └── siamese_network.py # Demuestra state isolation
230+
├── main.py # Demo XOR
231+
├── pyproject.toml # Empaquetado moderno (PEP 517/518)
232+
├── requirements.txt # Dev dependencies
233+
├── CHANGELOG.md
234+
├── LICENSE # MIT
235235
└── README.md
236236
```
237237

238-
## CHANGELOG v0.3.0 → v0.4.0
239-
240-
**Cambios estructurales (BREAKING):**
241-
- Capas: `forward(x) -> (output, cache)` y `backward(d_output, cache) -> (d_input, grads_dict)`. Ya no se almacena cache en `self`. **Migración:** si tenías código usando `model.forward()` directamente, ahora obtienes sólo la salida; para depurar el pipeline completo usa `model._forward()` que retorna `(output, caches)`.
242-
- Capas: `parameters() -> Dict[str, ndarray]` reemplaza a `get_params()`. Los optimizadores ya no acceden a `layer.weights`/`layer.biases`.
243-
- Optimizadores: `apply_gradients(list_of_tuples)` reemplaza a `update(layers)`. Aceptan cualquier nombre de parámetro.
244-
- Losses: `BinaryCrossEntropy` y `CategoricalCrossEntropy` aceptan `from_logits`.
245-
- Softmax: backward ahora implementa el Jacobiano completo (no "return 1").
246-
247-
**Nuevo:**
248-
- `NeuralNetwork.build(input_shape)` propaga shapes y valida fail-fast.
249-
- `NeuralNetwork.save(dir) / load(dir)` → topology.json + weights.npz (sin pickle).
250-
- `to_json() / from_json()` en modelo y componentes.
251-
- `examples/siamese_network.py` verifica state isolation con pesos compartidos.
252-
- Tests: 51 → 68.
253-
254-
**Arreglado:**
255-
- Acoplamiento matemático oculto CCE↔Softmax (issue #1).
256-
- Estado mutable que rompía arquitecturas multi-entrada (issue #2).
257-
- Serialización frágil con pickle (issue #3).
258-
- Validación tardía de shapes (issue #4).
259-
- Optimizador dependiente de `weights`/`biases` hardcodeados (issue #5).
260-
261-
**Migración rápida desde v0.3:**
262-
```python
263-
# v0.3
264-
model.save_model('model.pkl')
265-
NeuralNetwork.load_model('model.pkl')
238+
## Ejecutar tests
266239

267-
# v0.4 (recomendado)
268-
model.save('model/')
269-
NeuralNetwork.load('model/')
240+
```bash
241+
python -m unittest discover tests -v
270242
```
271243

272-
```python
273-
# v0.3 — riesgo oculto de CCE asumiendo Softmax
274-
model.add(Dense(10, activation='softmax'))
275-
model.compile(loss='cce', ...)
244+
## Ejemplos
276245

277-
# v0.4 — camino recomendado, numéricamente estable
278-
model.add(Dense(10, activation='linear'))
279-
model.compile(loss=CategoricalCrossEntropy(from_logits=True), ...)
246+
```bash
247+
python main.py
248+
python examples/multiclass_classification.py
249+
python examples/siamese_network.py
280250
```
281251

282252
## Licencia
283-
Proyecto de uso educativo y personal. Distribuido bajo la licencia MIT.
253+
Proyecto de uso educativo y personal. Distribuido bajo la licencia MIT.

examples/__init__.py

Whitespace-only changes.

examples/multiclass_classification.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@
77
- save(dir) + load(dir) con topology JSON + pesos NPZ.
88
"""
99
import os
10-
import sys
1110
import tempfile
1211
import numpy as np
1312

14-
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
15-
16-
from src import (
13+
from nnlib import (
1714
NeuralNetwork, Dense, Dropout, BatchNormalization,
1815
Adam, L2, CategoricalCrossEntropy,
1916
EarlyStopping, ReduceLROnPlateau,
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,10 @@
1313
Aquí construimos manualmente un embedder siamés: una red compartida
1414
procesa dos inputs, y una loss contrastiva simple compara sus embeddings.
1515
"""
16-
import os
17-
import sys
1816
import numpy as np
1917

20-
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
21-
22-
from src.layer import Dense, Dropout
23-
from src.activations import ReLU, Tanh
18+
from nnlib.layer import Dense, Dropout
19+
from nnlib.activations import ReLU, Tanh
2420

2521

2622
class SiameseEncoder:

main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Demo XOR — v0.4.
2+
Demo XOR — v1.0.
33
44
Muestra el camino recomendado de producción:
55
- capa final 'linear' + BinaryCrossEntropy(from_logits=True).
@@ -11,7 +11,7 @@
1111
import tempfile
1212
import numpy as np
1313

14-
from src import (
14+
from nnlib import (
1515
NeuralNetwork, Dense,
1616
Adam, BinaryCrossEntropy,
1717
EarlyStopping,

0 commit comments

Comments
 (0)