Skip to content

Commit cff8b40

Browse files
committed
Integración del Transfer Learning Edge para capas Linear. Actualización del CLI y el estimador de memoria. Actualización de la documentación con las features actuales
1 parent e3d5963 commit cff8b40

6 files changed

Lines changed: 362 additions & 176 deletions

File tree

docs/Documentación MiniML-Engine.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,47 @@ El código C++ generado por MiniML es altamente portable porque utiliza bucles `
15241524
15251525
En futuras actualizaciones, se considerará implementar la Vectorización Explícita para el módulo de empaquetado y exportación. Además de darle soporte al rust_writter para que sea compatible con todos los módulos disponibles de Deep Learning actualmente.
15261526
1527+
1528+
### 7. On-Device Transfer Learning (SGD Estático en el Borde)
1529+
1530+
El "mayor salto" del Edge Computing no es solo ejecutar inferencia localmente, sino lograr que el microcontrolador se adapte y aprenda de su entorno físico en tiempo real, sin depender de un servidor central. A partir de la versión 1.1.0 (En la actualización 1.1.2), el transpilador de **MiniML Engine** introduce la capacidad de **Aprendizaje por Transferencia en el Dispositivo (On-Device Learning)** mediante un algoritmo de Descenso de Gradiente Estocástico (SGD) hiper-optimizado.
1531+
1532+
Implementar entrenamiento en el "Bare Metal" tradicionalmente destruiría la SRAM debido a la necesidad de almacenar grafos computacionales dinámicos y tensores de retropropagación (Autograd). MiniML resuelve esto trasladando el cálculo pesado a la PC y exportando únicamente la aritmética final simplificada.
1533+
1534+
#### A. El "Semáforo de Memoria" (Layer Freezing y SRAM)
1535+
1536+
La arquitectura de transferencia de aprendizaje en MiniML se rige por la filosofía: *"El extractor de características es universal y estático; el clasificador es local y mutable"*.
1537+
1538+
Durante el diseño en Python, el usuario puede invocar el método `.unfreeze()` sobre la capa final del modelo (típicamente una capa `Linear`), manteniendo el resto de la red convolucional congelada. Al exportar a C++ con la bandera `on_device_learning=True`, el transpilador actúa como un semáforo de memoria:
1539+
1540+
1. **Extractor Inmutable (ROM):** Todas las capas congeladas (`Conv1D`, `SeparableConv2D`, etc.) se empaquetan rígidamente con la directiva `PROGMEM` (y cuantizadas a `INT8` si se requiere). Actúan como una función matemática tallada en piedra que reduce el ruido del sensor a un vector latente denso.
1541+
2. **Capa Adaptativa (SRAM):** El transpilador intercepta la capa `Linear` descongelada y **omite** el uso de `const` y `PROGMEM`. Sus matrices de pesos y sesgos se declaran como variables `float` estándar pre-asignadas en la memoria dinámica (SRAM).
1542+
1543+
#### B. El Motor SGD Estático (Matemática Pre-Calculada)
1544+
1545+
El microcontrolador no ejecuta un motor Autograd complejo. En su lugar, el exportador de Python lee qué función de pérdida (`MSELoss` o `CrossEntropyLoss`) se definió en el host, y resuelve la derivada analíticamente durante la transpilación.
1546+
1547+
El C++ generado inyecta una nueva función llamada `retrain_step(input, target)`. Esta función contiene bucles `for` matemáticamente purificados que implementan la regla de actualización del gradiente:
1548+
1549+
* **Para Regresión (`MSE`):** El compilador quema en C++ la resta directa proporcional al error cuadrado.
1550+
* **Para Clasificación (`CrossEntropy`):** Aprovecha la cancelación algebraica entre Softmax y NLL, reduciendo el cálculo del gradiente de entropía a un simple `(prediccion - target)`.
1551+
1552+
Esta simplificación extrema permite que la actualización de pesos en el silicio cueste apenas unos pocos ciclos de reloj, ejecutándose en fracciones de milisegundo.
1553+
1554+
#### C. Captura del Estado Latente (Zero-Copy Pointer)
1555+
1556+
Para que la capa `Linear` calcule su gradiente y ajuste sus pesos ($W = W - \alpha \times \text{Error} \times \text{Entrada}$), el motor SGD necesita conocer los valores de activación de la penúltima capa.
1557+
1558+
En lugar de crear un buffer temporal gigantesco que duplique el consumo de SRAM para guardar este historial (como lo haría un framework de servidor), el C++ de MiniML inyecta un puntero constante de 32-bits (o 16-bits en AVR) llamado `latent_vector`. Durante el *Forward Pass*, este puntero simplemente "captura" la dirección de memoria del buffer estático anterior, otorgando acceso total al motor SGD con un costo físico de **apenas 2 a 4 bytes de RAM**.
1559+
1560+
#### D. Límites Arquitectónicos y "Amnesia del Hardware"
1561+
1562+
Esta característica de grado industrial exige responsabilidad total por parte del arquitecto del firmware:
1563+
1564+
1. **Restricción Exclusiva a Capas `Linear`:** El transpilador bloqueará automáticamente cualquier intento de aplicar Transfer Learning a capas convolucionales o bloques residuales, forzándolos a la memoria Flash. Retropropagar el error a través de dimensiones espaciales exigiría matrices temporales de Im2Col que causarían un *Stack Overflow* garantizado en el hardware.
1565+
2. **Impacto en SRAM:** Mover la última capa a la SRAM conlleva un costo. Una capa `Linear(64, 10)` consumirá $(64 \times 10 + 10) \times 4 \text{ bytes} = 2,600 \text{ bytes}$ de RAM dinámica, lo cual descarta inmediatamente a los microcontroladores de gama baja de 8-bits (ej. ATmega328P con 2KB de SRAM total). Este modo está diseñado para potenciar chips de 32-bits (ESP32, STM32, Cortex-M4).
1566+
3. **Amnesia Volátil:** Dado que los pesos re-entrenados residen en la SRAM, **el aprendizaje se pierde instantáneamente si el dispositivo pierde energía**. Para hacer el aprendizaje permanente, el integrador debe diseñar una rutina en su código principal que extraiga los arreglos de C++ modificados y los guarde periódicamente en una partición no volátil externa (EEPROM o NVS). Se debe tener precaución de no guardar iterativamente en cada ciclo (Epoch) para no destruir físicamente los sectores de la memoria Flash por límite de ciclos de escritura.
1567+
15271568
---
15281569
15291570
# Capítulo 7. CLI de MiniML (Interfaz de Línea de Comandos)
@@ -1598,6 +1639,7 @@ Es la herramienta de diagnóstico más crítica del framework. Realiza un análi
15981639
* `--lang` *(Opcional)*: Lenguaje de transpilación. Opciones: `C`, `C++`, `Rust`. Por defecto: `C++`.
15991640
* `--quantized` *(Flag Opcional)*: Si se incluye, el estimador calculará la huella de memoria asumiendo compresión de pesos a INT8.
16001641
* `--input_shape` *(Opcional)*: Para redes convolucionales, define la forma del tensor de entrada separada por comas (ej. `1,28,28`).
1642+
* `--on_device_learning` *(Opcional)*: Si se incluye, calculará el overhead moviendo la última capa a SRAM para Transfer Learning
16011643

16021644

16031645
* **Funcionamiento Técnico:**

docs/MiniML Engine Documentation.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,48 @@ The C++ code generated by MiniML is highly portable because it uses standard mat
13911391
13921392
In future updates, implementing Explicit Vectorization for the packaging and export module will be considered. Additionally, providing support to the rust_writer to make it compatible with all currently available Deep Learning modules is planned.
13931393
1394+
1395+
1396+
### 7. On-Device Transfer Learning (Static SGD at the Edge)
1397+
1398+
The "biggest leap" in Edge Computing is not just executing inference locally, but enabling the microcontroller to adapt and learn from its physical environment in real-time, without relying on a central server. Starting from version 1.1.0 (in the 1.1.2 update), the **MiniML Engine** transpiler introduces the capability of **On-Device Transfer Learning** through a hyper-optimized Stochastic Gradient Descent (SGD) algorithm.
1399+
1400+
Implementing training on "Bare Metal" would traditionally destroy the SRAM due to the need to store dynamic computational graphs and backpropagation tensors (Autograd). MiniML solves this by offloading the heavy computation to the PC and exporting only the simplified final arithmetic.
1401+
1402+
#### A. The "Memory Traffic Light" (Layer Freezing and SRAM)
1403+
1404+
The transfer learning architecture in MiniML is governed by the philosophy: *"The feature extractor is universal and static; the classifier is local and mutable."*
1405+
1406+
During the Python design phase, the user can invoke the `.unfreeze()` method on the model's final layer (typically a `Linear` layer), keeping the rest of the convolutional network frozen. When exporting to C++ with the `on_device_learning=True` flag, the transpiler acts as a memory traffic light:
1407+
1408+
1. **Immutable Extractor (ROM):** All frozen layers (`Conv1D`, `SeparableConv2D`, etc.) are rigidly packaged with the `PROGMEM` directive (and quantized to `INT8` if required). They act as a mathematical function carved in stone that reduces sensor noise to a dense latent vector.
1409+
2. **Adaptive Layer (SRAM):** The transpiler intercepts the unfrozen `Linear` layer and **omits** the use of `const` and `PROGMEM`. Its weight and bias matrices are declared as standard `float` variables pre-allocated in the dynamic memory (SRAM).
1410+
1411+
#### B. The Static SGD Engine (Pre-Calculated Math)
1412+
1413+
The microcontroller does not run a complex Autograd engine. Instead, the Python exporter reads which loss function (`MSELoss` or `CrossEntropyLoss`) was defined on the host, and analytically resolves the derivative during transpilation.
1414+
1415+
The generated C++ injects a new function called `retrain_step(input, target)`. This function contains mathematically purified `for` loops that implement the gradient update rule:
1416+
1417+
* **For Regression (`MSE`):** The compiler hardcodes into C++ the direct subtraction proportional to the squared error.
1418+
* **For Classification (`CrossEntropy`):** It leverages the algebraic cancellation between Softmax and NLL, reducing the entropy gradient calculation to a simple `(prediction - target)`.
1419+
1420+
This extreme simplification allows the weight update on the silicon to cost just a few clock cycles, executing in fractions of a millisecond.
1421+
1422+
#### C. Latent State Capture (Zero-Copy Pointer)
1423+
1424+
For the `Linear` layer to calculate its gradient and adjust its weights ($W = W - \alpha \times \text{Error} \times \text{Input}$), the SGD engine needs to know the activation values of the penultimate layer.
1425+
1426+
Instead of creating a massive temporary buffer that duplicates SRAM consumption to store this history (as a server framework would do), MiniML's C++ injects a constant 32-bit (or 16-bit in AVR) pointer called `latent_vector`. During the *Forward Pass*, this pointer simply "captures" the memory address of the previous static buffer, granting full access to the SGD engine at a physical cost of **barely 2 to 4 bytes of RAM**.
1427+
1428+
#### D. Architectural Limits and "Hardware Amnesia"
1429+
1430+
This industrial-grade feature demands total responsibility from the firmware architect:
1431+
1432+
1. **Exclusive Restriction to `Linear` Layers:** The transpiler will automatically block any attempt to apply Transfer Learning to convolutional layers or residual blocks, forcing them into Flash memory. Backpropagating the error across spatial dimensions would require temporary Im2Col matrices that would cause a guaranteed *Stack Overflow* on the hardware.
1433+
2. **SRAM Impact:** Moving the last layer to SRAM comes with a cost. A `Linear(64, 10)` layer will consume $(64 \times 10 + 10) \times 4 \text{ bytes} = 2,600 \text{ bytes}$ of dynamic RAM, which immediately rules out low-end 8-bit microcontrollers (e.g., ATmega328P with 2KB of total SRAM). This mode is designed to empower 32-bit chips (ESP32, STM32, Cortex-M4).
1434+
3. **Volatile Amnesia:** Since the retrained weights reside in SRAM, **the learning is instantly lost if the device loses power**. To make the learning permanent, the integrator must design a routine in their main code that extracts the modified C++ arrays and periodically saves them to an external non-volatile partition (EEPROM or NVS). Care must be taken not to save iteratively on every cycle (Epoch) to avoid physically destroying the Flash memory sectors due to write cycle limits.
1435+
13941436
---
13951437
13961438
# **7. MiniML CLI (Command Line Interface)**
@@ -1453,7 +1495,9 @@ python main.py inspect --model modelsfault_detector.json
14531495
* --sram *(Optional)*: Physical limit of SRAM memory in bytes. Default is **2048** (Arduino Uno).
14541496
* --lang *(Optional)*: Transpilation language. Options: C, C++, Rust. Default: C++.
14551497
* --quantized *(Optional Flag)*: If included, the estimator will calculate the memory footprint assuming INT8 weight compression.
1456-
* --input_shape *(Optional)*: For convolutional networks, defines the input tensor shape separated by commas (e.g., 1,28,28).
1498+
* --input_shape *(Optional)*: For convolutional networks, defines the input tensor shape separated by commas (e.g., 1,28,28).
1499+
* --on_device_learning *(Optional)*: If included, it will calculate the overhead by moving the last layer to SRAM for Transfer Learning.
1500+
14571501
* **Technical Operation:**
14581502
The estimator outputs a detailed percentage report. If SRAM or Flash consumption exceeds 90% of the defined hardware capacity, the CLI will trigger a [⚠️ WARNING] alerting the architect that physical deployment is at imminent risk of instability or *Stack Overflow*.
14591503
* **Usage Example:**

0 commit comments

Comments
 (0)