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.

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
- Abre la app. En este sitio MNIST (70.000 dígitos manuscritos) se carga solo; la primera vez tarda unos segundos.
- 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.
- 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.
- Agrega un Loss (paleta, Training). Con la última capa seleccionada empieza como
ce(fc2): entropía cruzada de esos puntajes contra las etiquetas reales. - Pulsa ▶ Train en el Loss. La curva se dibuja mientras entrena; al final de cada época aparece la exactitud en el conjunto de prueba.
- 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.

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
| Componente | Qué hace | Configuración |
|---|---|---|
| Datos | ||
| Data | Entrega 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 |
| Sliders | Produce 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 / Output | Una 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 2D | Grá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 3D | Lo 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 | ||
| Dense | Capa totalmente conectada sobre la última dimensión. Sin nada conectado, toma su entrada directamente (fija Input features). | Input features (auto), Output features, Use bias |
| Conv2D | Convolución 2D sobre C×H×W. | Input channels (auto), Output channels (un número o same), Kernel, Stride, Padding |
| MaxPool2D / AvgPool2D | Agrupación por ventanas en cada canal. | Kernel, Stride (auto = kernel) |
| Global Avg Pool | Promedia el mapa de cada canal en un valor. | |
| Activation | Cualquier 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 |
| BatchNorm | Normalización por lotes (1D o 2D) con estadísticas acumuladas como en PyTorch: las del lote al entrenar, las acumuladas en lo demás. | |
| Dropout | Anula valores solo durante el entrenamiento. | Drop probability |
| Forma y unión | ||
| Flatten / Unflatten | A 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 / Concat | Dos entradas (a, b): suma elemento a elemento, o unión a lo largo de la primera dimensión. | |
| Pointer pair | Ejecuta 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 |
| PCA | Aná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 | ||
| Loss | Una expresión sobre componentes; Train la minimiza. Muestra la curva de pérdida. | Expression, Optimizer, Learning rate, Batch size, Epochs |
| Block | Un 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.
| Escribe | Significa |
|---|---|
fc1 | La 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".fc1 | Un 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_weights | Los 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_weights | Los 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 softmax | Funciones elemento a elemento (softmax sobre los valores). |
sum mean max min | Reducciones; 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
kenfc1[k]oalphaenmax(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
nen 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.
- Agrega un Pointer pair desde la paleta: aparecen un Pointer in y un Pointer out.
- Conecta la nueva entrada (por ejemplo un componente Sliders) al Pointer in.
- 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.
- 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.

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.Modulecon las mismas capas, unforward()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.safetensorscon 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
| Teclas | Acción |
|---|---|
| Ctrl+Z / Ctrl+Y | Deshacer / rehacer |
| Ctrl+C X V | Copiar, cortar, pegar (con sus pesos entrenados) |
| Ctrl+D | Duplicar |
| Ctrl+A | Seleccionar todo en este grafo |
| G / Shift+G | Agrupar en un bloque / desagrupar |
| V | Modo vista para la selección |
| Delete | Borrar la selección o el cable seleccionado |
| ← → | Muestra anterior / siguiente (con un componente Data seleccionado) |
| Esc | Quitar la selección, o salir de un bloque |
| Ctrl+S / Ctrl+O | Guardar / abrir un archivo de proyecto |
| Rueda, arrastrar | Zoom, desplazar (el botón central también desplaza) |
| Shift/Ctrl+arrastrar | Recuadro de selección |
| Doble clic | Abrir 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 (necesitanpython3contorchysafetensors; si no, se omiten).