NETGRAPH

Compón redes neuronales.
Míralas pensar.

Netgraph es un entorno para experimentar con redes neuronales que funciona por completo en el navegador. Conecta capas como en un editor de nodos, entrénalas con MNIST, observa cada activación y cada neurona, y exporta el resultado como código de PyTorch con sus pesos.

Un clasificador de MNIST entrenado en Netgraph: un componente Data con un dígito manuscrito, capas Dense y ReLU con sus activaciones como franjas de color, la salida Softmax como barras y la curva de pérdida.

Construye conectando

Capas, bloques, uniones y cambios de forma, con las formas verificadas al conectar.

Mira cada activación

Cualquier componente puede mostrar lo que sale de él. Las capas Dense se abren en sus neuronas.

Entrena en el navegador

Las pérdidas son expresiones sobre componentes. Adam o SGD, por lotes, sin bloquear la página.

Analiza

Recolecta activaciones, aplica PCA, grafícalas en 2D o 3D y reutiliza partes entrenadas con punteros.

01Primeros pasos

  1. Abre la app. En este sitio MNIST (70.000 dígitos manuscritos) se carga solo; la primera vez tarda unos segundos.
  2. Pulsa Load example en la barra superior para ver un pequeño clasificador convolucional, o empieza con el lienzo vacío: haz clic en Data en la paleta de la izquierda y luego en Dense, ReLU y otra Dense. Cada uno se agrega después del componente seleccionado y queda conectado a él.
  3. Selecciona el componente Data y marca Flatten para que la imagen de 28×28 se convierta en 784 valores para las capas Dense. Pon las Output features de la última Dense en 10: un puntaje por dígito.
  4. Agrega un Loss (paleta, Training). Con la última capa seleccionada empieza como ce(fc2): entropía cruzada de esos puntajes contra las etiquetas reales.
  5. Pulsa ▶ Train en el Loss. La curva se dibuja mientras entrena; al final de cada época aparece la exactitud en el conjunto de prueba.
  6. Selecciona una capa y pulsa V para ver sus activaciones, o haz doble clic en una capa Dense para ver sus neuronas. Recorre las muestras con ← → sobre el componente Data.

Todo se ejecuta en tu navegador: no se sube nada. La red, tus bloques y los pesos entrenados se guardan en el almacenamiento del navegador; usa Save para conservar un archivo del proyecto.

02El lienzo

La ventana tiene tres partes: la paleta a la izquierda, el lienzo en el centro y la ventana de información a la derecha, que muestra las formas, la configuración y las activaciones del componente seleccionado.

  • Agrega un componente haciendo clic en la paleta (se coloca y se conecta después del seleccionado) o arrastrándolo al lienzo.
  • Conecta arrastrando desde un puerto de salida (derecha) a uno de entrada (izquierda). Las formas se verifican: una conexión que no encaja se rechaza explicando por qué. Los puertos se deslizan por el borde para mirar hacia lo que conectan.
  • Dobla un cable arrastrándolo; doble clic lo endereza. Selecciona un cable y pulsa Delete para quitarlo.
  • Selecciona con un clic; Ctrl/⌘+clic agrega a la selección; arrastrar con Shift o Ctrl sobre el lienzo vacío dibuja un recuadro de selección (o usa Select area).
  • Cambia el tamaño de un componente desde su esquina inferior derecha; doble clic en la esquina lo restablece.
  • Cada entrada es una celda. En la ventana de información cada entrada muestra el nombre de lo que está conectado. Escribe el nombre de otro componente para reconectar, o una expresión (como fc1[0:10] * 2) para alimentar la entrada con valores calculados en lugar de un cable.
  • Cada componente muestra sus formas, como 784 → 128, y explica los problemas en su sitio (en rojo), por ejemplo formas que no coinciden o una entrada sin conectar.

03Mirar por dentro

Modo vista

Pulsa V (o el punto en la esquina inferior izquierda del componente, o View activations) para convertir un componente en una vista de lo que produce para la muestra en pantalla. Los vectores se dibujan como franjas horizontales, los mapas de características como mosaicos, las salidas de diez valores como barras con la etiqueta real marcada, y las imágenes en escala de grises. Los colores usan un mapa divergente: azul para negativos, negro cerca de cero, de naranja a blanco para positivos.

Neuronas

Haz doble clic en una capa Dense (o acércate con el zoom más allá del límite) para verla como neuronas y pesos. El selector Layers / Neurons de arriba muestra así una MLP completa. Pasa el cursor por una neurona para resaltar sus conexiones; su valor para la muestra actual está en su color.

La vista de neuronas de una MLP entrenada: columnas de círculos para las neuronas de entrada, ocultas y de salida, coloreadas según su activación, con líneas para los pesos.

Bloques

Haz doble clic en un bloque (o acércate con el zoom) para abrirlo; la ruta de arriba lleva de vuelta. Esc sube un nivel.

04Componentes

ComponenteQué haceConfiguración
Datos
DataEntrega muestras de un conjunto de datos, con sus etiquetas, y guarda una división entrenamiento/prueba. Si algo está conectado a su entrada, recolecta: durante una ejecución de inferencia guarda todo lo que le llega (ver Datos). Su caja muestra lo que contiene, como 70,000 × 1×28×28.Dataset, Flatten, Test split (%), Shuffle seed; Inference: Samples from, How many
SlidersProduce un vector de valores fijados a mano, igual para todas las muestras. El entrenamiento nunca los cambia.Nombre, mínimo, paso y máximo de cada deslizador
Input / OutputUna entrada de forma fija sin datos (para construir y exportar), y la marca de lo que devuelve la red.Input shape, como 1,28,28
Plot 2DGráfica de dispersión de lo que le llega: la muestra en pantalla como un anillo, las filas de una matriz como puntos, y cada muestra que una ejecución de inferencia hace pasar, coloreada por su etiqueta.Ejes horizontal y vertical (índices de valores)
Plot 3DLo mismo en 3D. En modo vista y en la ventana de información: arrastra para girar la cámara, rueda para acercar, Shift+arrastrar para desplazar, doble clic para restablecer.Tres ejes
Capas
DenseCapa totalmente conectada sobre la última dimensión. Sin nada conectado, toma su entrada directamente (fija Input features).Input features (auto), Output features, Use bias
Conv2DConvolución 2D sobre C×H×W.Input channels (auto), Output channels (un número o same), Kernel, Stride, Padding
MaxPool2D / AvgPool2DAgrupación por ventanas en cada canal.Kernel, Stride (auto = kernel)
Global Avg PoolPromedia el mapa de cada canal en un valor.
ActivationCualquier función de x escrita como fórmula, como max(x, a*x); los otros nombres se vuelven deslizadores. ReLU, GELU, Sigmoid, Tanh y Softmax son este mismo componente con su fórmula, y se ejecutan (y exportan) como las versiones nativas.Function of x
BatchNormNormalización por lotes (1D o 2D) con estadísticas acumuladas como en PyTorch: las del lote al entrenar, las acumuladas en lo demás.
DropoutAnula valores solo durante el entrenamiento.Drop probability
Forma y unión
Flatten / UnflattenA un vector, y de vuelta a cualquier forma con el mismo número de valores.Unflatten: Output shape (auto, o como 32,7,7; un -1 se calcula solo)
Add / ConcatDos entradas (a, b): suma elemento a elemento, o unión a lo largo de la primera dimensión.
Pointer pairEjecuta de nuevo un tramo de la red sobre otra entrada, con los mismos pesos (ver Pares de punteros).Pointer in: Feeds · Pointer out: Pointer in
PCAAnálisis de componentes principales de lo que le llega. Fit aprende las componentes; luego proyecta cada muestra sobre ellas (ver PCA).Components, Fit on (samples)
Entrenamiento y bloques
LossUna expresión sobre componentes; Train la minimiza. Muestra la curva de pérdida.Expression, Optimizer, Learning rate, Batch size, Epochs
BlockUn grupo de componentes con una entrada y una salida; se abre con doble clic. Incluidos: MLP, Conv block, Residual block; guarda los tuyos en My blocks.Variables del bloque (en su Block input)

Los componentes pueden ir en cualquier lugar, también dentro de bloques, incluidos Data y Loss.

05Expresiones

Las pérdidas, las celdas de entrada, las funciones de activación y los punteros usan un pequeño lenguaje de expresiones sobre componentes. El nombre de un componente representa su salida para la muestra (o lote) actual.

EscribeSignifica
fc1La salida del componente llamado fc1. Los nombres se buscan primero en el grafo de la expresión y luego en cada bloque que lo rodea.
MLP.fc2, "MLP 2".fc1Un componente dentro de un bloque (pon entre comillas los nombres con espacios).
fc1[3], fc1[0:10], conv1[2, :, 5]Un valor, un rango, o varias dimensiones a la vez (contando desde 0).
fc1[3].pre_weightsLos pesos que entran a la neurona 3 (un vector, uno por entrada). Sin índice, fc1.pre_weights es la matriz completa neuronas × entradas.
fc1[3].post_weightsLos pesos que salen de la neurona 3 hacia la siguiente capa Dense.
+ − * / ^Aritmética elemento a elemento; los números y resultados de un solo valor se extienden.
abs log exp sqrt tanh sigmoid relu softmaxFunciones elemento a elemento (softmax sobre los valores).
sum mean max minReducciones; max(a, b) y min(a, b) con dos entradas son elemento a elemento.
ce(scores), nll(probs)Entropía cruzada contra las etiquetas reales, a partir de puntajes o de probabilidades.
mse(a, b)Error cuadrático medio.

Escribe un nombre o un punto para ver sugerencias (Ctrl+Espacio las abre). Cuando un componente se renombra, se agrupa o se desagrupa, todas las expresiones que lo nombran se actualizan. Una pérdida con muchos valores se promedia.

ce(fc3)                                  # clasificación
mse(recon, data1)                        # reconstrucción de un autoencoder
ce(fc3) + 0.001*sum(fc1.pre_weights^2)   # con regularización de los pesos de fc1
mean(abs(relu2)) * 0.01 + mse(dec, x)    # código disperso

06Variables y deslizadores

  • En expresiones, un nombre que no es un componente se vuelve una variable con deslizador (en el componente y en la ventana de información), como k en fc1[k] o alpha en max(x, alpha*x). Su mínimo, paso y máximo se pueden editar; los botones ‹ › lo mueven un paso. Una celda de entrada que es solo un nombre desconocido se trata como un error de escritura, con una sugerencia.
  • En la configuración, un nombre en un campo numérico (como n en Output features) también se vuelve deslizador.
  • Variables de bloque: se declaran en el Block input de un bloque como filas nombre = valor. Un número se vuelve un deslizador en el bloque; una expresión puede usar las filas anteriores. Las capas del bloque pueden usar esos nombres.
  • El componente Sliders convierte deslizadores en un vector de salida, para alimentar una red a mano.

07Bloques

Selecciona varios componentes y pulsa G para agruparlos en un bloque; Shift+G los desagrupa. Un bloque tiene una entrada y una salida; dentro son los terminales Block input y Block output. Un bloque que contiene su propio componente Data no necesita entrada. Save to my blocks guarda un bloque en la paleta para reutilizarlo.

08Entrenamiento

  • Un Loss no tiene cables de entrada: su expresión nombra lo que usa. Las muestras vienen del componente Data que alimenta esos nombres, y para entrenar solo se usa su parte de entrenamiento.
  • Train se ejecuta en segundo plano, así la página sigue respondiendo. La curva muestra la pérdida de entrenamiento suavizada y, al final de cada época, la pérdida en (hasta 2.000) muestras de prueba, con la exactitud en pérdidas de clasificación. Selecciona el Loss y arrastra su gráfica para desplazarla, usa la rueda para acercar y doble clic para verla completa.
  • Evaluate on test set evalúa toda la parte de prueba. Reset weights vuelve a empezar con pesos aleatorios nuevos.
  • Adam (valores por defecto de PyTorch) o SGD con momento 0,9; los pesos se inician como en PyTorch. Un conjunto de pruebas compara salidas, gradientes, estadísticas de BatchNorm y pasos del optimizador con PyTorch real.
  • Pueden coexistir varias pérdidas; una pérdida puede usar el valor de otra.

09Datos, inferencia y recolección

Import data lee archivos IDX (el formato de MNIST, comprimidos o no): elige un archivo de imágenes junto con su archivo de etiquetas, o suéltalos en el lienzo. El conjunto queda guardado en el navegador. Cada componente Data lo baraja con su semilla y separa una parte para prueba.

Recolectar activaciones

Un componente Data con algo conectado a su entrada recolecta. Conecta, por ejemplo, la capa del medio de un autoencoder a un componente Data nuevo. Luego selecciona el componente Data donde empieza el flujo y, en Inference, elige Samples from (parte de prueba, de entrenamiento o todo el conjunto) y How many, y pulsa ▶ Run inference. El componente que recolecta guarda cada muestra que le llegó, con su etiqueta real, como un conjunto de datos propio: puedes recorrerlo, verlo, graficarlo o entrenar otra red con él. Las gráficas conectadas más adelante se llenan de la misma forma.

10Pares de punteros

Un par de punteros ejecuta de nuevo un tramo de la red, sobre otra entrada, con los mismos pesos. Uso típico: alimentar un decodificador entrenado con deslizadores, sin separarlo de su codificador.

  1. Agrega un Pointer pair desde la paleta: aparecen un Pointer in y un Pointer out.
  2. Conecta la nueva entrada (por ejemplo un componente Sliders) al Pointer in.
  3. Arrastra la salida del Pointer in hasta la entrada de la capa donde empieza el tramo. Esa capa conserva su propio cable; el enlace aparece como un cable azul punteado a su lado.
  4. Conecta la capa donde termina el tramo al Pointer out. Su salida es el resultado del tramo sobre la nueva entrada.

Los gradientes pasan por ambas ejecuciones hacia los pesos compartidos. El tramo no puede tomar entradas de fuera de él (salvo la de su primera capa).

11PCA y gráficas

PCA toma lo que le llega (aplana cada muestra). Fit hace pasar por la red las primeras Fit on muestras de entrenamiento del componente Data que la alimenta, calcula su media y covarianza, y guarda las Components direcciones principales; la ventana de información muestra cuánta varianza explica cada una. Después hace pasar todo el conjunto hacia los componentes Data y las gráficas que tenga a continuación. Una vez ajustada es una proyección fija, así que la muestra en pantalla, las inferencias y el entrenamiento también pasan por ella; en la exportación a PyTorch es un nn.Linear congelado.

Un autoencoder en Netgraph: su capa del medio de 16 unidades pasa por una PCA hacia una gráfica 2D donde los dígitos de MNIST forman grupos de colores; abajo, un componente Sliders alimenta el decodificador a través de un par de punteros y su salida se ve como un dígito generado.
Un autoencoder: la capa del medio → PCA (2 componentes) → Plot 2D, coloreado por el dígito real. Abajo, un par de punteros ejecuta el decodificador entrenado sobre 16 deslizadores.

12Recetas

Ver el espacio latente de un autoencoder

Construye Data (aplanado) → Dense 128 → ReLU → Dense 16 → ReLU → Dense 128 → ReLU → Dense 784 → Sigmoid, agrega un Loss mse(sigmoid1, data1) y entrena. Conecta la ReLU de 16 unidades a una PCA (2 o 3 componentes) y la PCA a un Plot 2D o 3D, y pulsa Fit and project en la PCA.

Sonda lineal

Recolecta una capa oculta en un componente Data, conéctalo a una sola capa Dense de 10 salidas con un Loss ce(…) y entrena. La exactitud en prueba indica qué tan linealmente se pueden leer las etiquetas a esa profundidad.

Ver los pesos de una neurona como imagen

Pon en la celda de entrada de un Unflatten fc1[3].pre_weights, su forma en 1,28,28, y activa el modo vista: los 784 pesos que entran a la neurona 3 como una imagen.

Apagar o dirigir neuronas

Alimenta una capa desde una celda de entrada como relu1 * (1 - sliders1) para apagar neuronas, o relu2 + a*sliders1 para empujar en una dirección, y mira cómo cambia la predicción.

13Guardar y exportar

  • Save (Ctrl+S) descarga un archivo JSON del proyecto con la red, tus bloques y los pesos entrenados. Open (Ctrl+O) o soltar el archivo en el lienzo lo carga. Los conjuntos de datos se mencionan, no se incluyen.
  • Export PyTorch escribe un torch.nn.Module con las mismas capas, un forward() que además guarda cada valor intermedio, y las expresiones de pérdida como código de torch. Descarga el código y un archivo .safetensors con los pesos, y luego:
from safetensors.torch import load_file
from netgraph_model import Net

model = Net()
model.load_state_dict(load_file("netgraph_weights.safetensors"))

14Teclado y ratón

TeclasAcción
Ctrl+Z / Ctrl+YDeshacer / rehacer
Ctrl+C X VCopiar, cortar, pegar (con sus pesos entrenados)
Ctrl+DDuplicar
Ctrl+ASeleccionar todo en este grafo
G / Shift+GAgrupar en un bloque / desagrupar
VModo vista para la selección
DeleteBorrar la selección o el cable seleccionado
← →Muestra anterior / siguiente (con un componente Data seleccionado)
EscQuitar la selección, o salir de un bloque
Ctrl+S / Ctrl+OGuardar / abrir un archivo de proyecto
Rueda, arrastrarZoom, desplazar (el botón central también desplaza)
Shift/Ctrl+arrastrarRecuadro de selección
Doble clicAbrir un bloque o las neuronas de una capa Dense

En Mac, usa ⌘ en lugar de Ctrl.

15Desarrollo

La app es un solo archivo HTML construido a partir de src/, sin dependencias.

git clone https://github.com/AtarraIA/netgraph
cd netgraph
node build.mjs     # escribe "Netgraph_ compose neural networks.html"
npm test           # reconstruye y ejecuta todas las pruebas
  • src/engine/: el núcleo sin DOM (modelo del grafo, inferencia de formas, conjuntos de datos, expresiones, pesos, pasos hacia adelante y hacia atrás por lotes, entrenamiento, PCA, exportación a PyTorch). El mismo código se ejecuta en la página, en el proceso de entrenamiento en segundo plano y en las pruebas.
  • src/ui/: la página (lienzo, componentes, ventana de información, vista de neuronas, gráficas, edición, controles de entrenamiento).
  • tests/: pruebas del motor con verificación numérica de gradientes para cada tipo de capa, y pruebas de paridad con PyTorch (necesitan python3 con torch y safetensors; si no, se omiten).