- Kevin Joaquin Chambi Tapia
- Victor Alejandro Quicaño Miranda
- Eduardo German Ruiz Mamani
- Sebastian Agenor Zamalloa Molina
Este proyecto implementa un modelo Vision Transformer (ViT) utilizando únicamente CUDA y C++. La implementación es educativa y busca comprender los fundamentos del paper "An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale" (Dosovitskiy et al., 2020).
A diferencia de las redes neuronales convolucionales tradicionales, este enfoque transforma una imagen en pequeños patches que son procesados como secuencias, permitiendo el uso de la arquitectura Transformer originalmente diseñada para tareas de procesamiento de lenguaje natural.
- Objetivo
- ¿Qué es Vision Transformer?
- Cómo compilar y ejecutar
- Explicación del código
- Entrenamiento
- Predicción
- Resultados
El objetivo principal es explorar cómo los Transformers pueden aplicarse al reconocimiento visual desde cero, sin depender de frameworks de alto nivel, y acelerando el entrenamiento e inferencia mediante CUDA y programación en bajo nivel con C++.
El Vision Transformer (ViT) divide una imagen en bloques fijos (por ejemplo, de 16x16 píxeles), los aplane y los trate como "palabras" o tokens. Estos tokens se procesan mediante una serie de capas Transformer, seguidas por una capa final de clasificación.
- División de imágenes en patches.
- Uso de embeddings aprendidos para cada patch.
- Inserción de un token especial
[CLS]para la clasificación. - Uso de atención multi-cabeza y posiciones absolutas aprendidas.
Este proyecto utiliza un Makefile para la compilación y un script run.sh para simplificar la ejecución.
- Un compilador de C++ compatible con C++17 (ej.
g++). - La utilidad
make. - Python 3 para scripts auxiliares.
1. Dar permisos de ejecución (solo una vez):
chmod +x run.sh- Comandos disponibles:
Entrenar el modelo: Usa un archivo de configuración para definir todos los hiperparámetros.
./run.sh train <ruta_a_config.cfg>Ejemplo:
./run.sh train models/configs/mnist_small.cfgEvaluar un modelo: Genera la matriz de confusión para un modelo entrenado.
./run.sh evaluate <ruta_al_modelo.bin> <nombre_dataset>
Ejemplo:
./run.sh evaluate models/mnist/vit_...bin mnistPredecir con una imagen aleatoria: Extrae una imagen al azar de un dataset y usa el modelo más reciente.
./run.sh predict [nombre_dataset]Ejemplo (usa mnist por defecto):
./run.sh predict fashionmnistHacer inferencia directa: Realiza una predicción sobre un archivo de imagen específico.
./run.sh infer <modelo.bin> <imagen.csv>Limpiar el proyecto: Elimina los archivos de compilación.
./run.sh cleanPerfecto, con base en tu estructura de archivos y el contenido actual del README, podrías insertar una sección "Explicación del código" que detalle la arquitectura y módulos principales. Aquí te dejo una versión integrada para que simplemente pegues en tu README.md (después de la sección de "Referencias" o antes de "Cómo compilar y ejecutar"):
El modelo está dividido modularmente en componentes inspirados en la arquitectura Transformer original:
src/
├── core/ # Componentes fundamentales como tensores y funciones de activación
├── model/ # Arquitectura del modelo Transformer
├── optimizer/ # Optimizadores implementados manualmenteLa atención se implementa en model/multihead_attention.cpp. Se construye a partir de:
- Proyecciones lineales para
Q,K,V(query, key, value). - Normalización por raíz de la dimensión (
1/sqrt(dk)). - Softmax sobre las similitudes
QK^T. - Producto con
Vpara obtener el resultado por cabeza. - Concatenación y proyección final.
Esto permite al modelo enfocarse en distintas partes de la imagen simultáneamente.
Ubicado en model/encoder.cpp, cada bloque encoder tiene:
- Atención multi-cabeza (
MultiHeadAttention) - Normalización (
LayerNorm) - MLP residual (Feed Forward)
- Normalización final
Se repiten en stack (definido por n_layers en config).
En model/vit.cpp, se definen:
- División de imagen en patches.
- Embedding lineal para cada patch + posición.
- Inserción del token
[CLS]. - Stack de
Encoder+ capa final lineal de clasificación.
Define un tipo de tensor liviano con soporte para operaciones básicas (suma, producto, reshape). Es la base para todos los cálculos.
Contiene activaciones como ReLU, GELU, y Softmax.
Implementaciones manuales de SGD, Adam, y AdamW siguiendo fórmulas originales con soporte para weight decay.
Configuración: Se utilizó la configuración definida en configs/mnist.cfg.
Métricas Finales:
| Métrica | Valor |
|---|---|
| Precisión (Accuracy) | 96.44% |
| F1-Score (Macro) | 0.9638 |
Configuración: Se utilizó la configuración definida en configs/fashionmnist.cfg.
Métricas Finales:
| Métrica | Valor |
|---|---|
| Precisión (Accuracy) | 86.79% |
| F1-Score (Macro) | 0.8678 |
Configuración: Se utilizó la configuración definida en configs/bloodmnist.cfg.
Métricas Finales:
| Métrica | Valor |
|---|---|
| Precisión (Accuracy) | 0.77% |
| F1-Score (Macro) | 0.7513 |









