Una implementación de codificación para construir y entrenar arquitecturas avanzadas con conexiones residuales, autoatención y optimización adaptativa utilizando JAX, Flax y Optax

En este tutorial, exploramos cómo construir y entrenar una red neuronal avanzada utilizando JAX, Flax y Optax de una manera eficiente y modular. Comenzamos diseñando una arquitectura profunda que integra conexiones residuales y mecanismos de autoatención para el aprendizaje de características expresivas. A medida que avanzamos, implementamos estrategias de optimización sofisticadas con programación de tasa de aprendizaje, recorte de gradiente y caída de peso adaptativa. A lo largo del proceso, aprovechamos las transformaciones de JAX, como jit, grad y vmap, para acelerar el cálculo y garantizar un rendimiento de entrenamiento fluido en todos los dispositivos. Consulta los CÓDIGOS COMPLETOS aquí.

!pip install jax jaxlib flax optax matplotlib import jax import jax.numpy as jnp from jax import random, jit, vmap, grad import flax.linen as nn from flax.training import train_state import optax import matplotlib.pyplot as plt from tiping import Any, Callable print(f”JAX version: {jax.__version__}”) print(f”Dispositivos: {jax.dispositivos()}”)

Comenzamos instalando e importando JAX, Flax y Optax, junto con utilidades esenciales para operaciones numéricas y visualización. Verificamos la configuración de nuestro dispositivo para asegurarnos de que JAX se esté ejecutando de manera eficiente en el hardware disponible. Esta configuración constituye la base de todo el proceso de formación. Consulta los CÓDIGOS COMPLETOS aquí.

clase SelfAttention(nn.Module): num_heads: int dim: int @nn.compact def __call__(self, x): B, L, D = x.shape head_dim = D // self.num_heads qkv = nn.Dense(3 * D)(x) qkv = qkv.reshape(B, L, 3, self.num_heads, head_dim) q, k, v = jnp.split(qkv, 3, axis=2) q, k, v = q.squeeze(2), k.squeeze(2), v.squeeze(2) attn_scores = jnp.einsum(‘bhqd,bhkd->bhqk’, q, k) / jnp.sqrt(head_dim) attn_weights = jax.nn.softmax(attn_scores, axis=-1) attn_output = jnp.einsum(‘bhqk,bhvd->bhqd’, attn_weights, v) attn_output = attn_output.reshape(B, L, D) return nn.Dense(D)(attn_output) clase ResidualBlock(nn.Module): características: int @nn.compact def __call__(self, x, entrenamiento: bool = True): residual = x x = nn.Conv(self.features, (3, 3), padding=’SAME’)(x) x = nn.BatchNorm(use_running_average=not entrenamiento)(x) x = nn.relu(x) x = nn.Conv(self.features, (3, 3), padding=’SAME’)(x) x = nn.BatchNorm(use_running_average=not trainning)(x) si residual.shape[-1] != self.features: residual = nn.Conv(self.features, (1, 1))(residual) return nn.relu(x + residual) class AdvancedCNN(nn.Module): num_classes: int = 10 @nn.compact def __call__(self, x, entrenamiento: bool = True): x = nn.Conv(32, (3, 3), padding=’SAME’)(x) x = nn.relu(x) x = ResidualBlock(64)(x, entrenamiento) x = ResidualBlock(64)(x, entrenamiento) x = nn.max_pool(x, (2, 2), strides=(2, 2)) x = ResidualBlock(128)(x, entrenamiento) x = ResidualBlock(128)(x, entrenamiento) x = jnp.media(x, eje=(1, 2)) x = x[:, None, :]
x = SelfAttention(num_heads=4, dim=128)(x) x = x.squeeze(1) x = nn.Dense(256)(x) x = nn.relu(x) x = nn.Dropout(0.5, determinista=sin entrenamiento)(x) x = nn.Dense(self.num_classes)(x) return x

Definimos una red neuronal profunda que combina bloques residuales y un mecanismo de autoatención para mejorar el aprendizaje de funciones. Construimos las capas de forma modular, asegurando que el modelo pueda capturar relaciones tanto espaciales como contextuales. Este diseño permite que la red se generalice de manera efectiva entre varios tipos de datos de entrada. Consulta los CÓDIGOS COMPLETOS aquí.

clase TrainState(train_state.TrainState): lote_stats: Cualquier def create_learning_rate_schedule(base_lr: float = 1e-3, warmup_steps: int = 100, decay_steps: int = 1000) -> optax.Schedule: warmup_fn = optax.linear_schedule(init_value=0.0, end_value=base_lr, transición_pasos=pasos_de calentamiento) decay_fn = optax.cosine_decay_schedule(init_value=base_lr, decay_steps=decay_steps, alpha=0.1) return optax.join_schedules(programaciones=[warmup_fn, decay_fn]límites =[warmup_steps]) def create_optimizer(learning_rate_schedule: optax.Schedule) -> optax.GradientTransformation: return optax.chain(optax.clip_by_global_norm(1.0), optax.adamw(learning_rate=learning_rate_schedule, Weight_decay=1e-4))

Creamos un estado de entrenamiento personalizado que rastrea los parámetros del modelo y las estadísticas de lotes. También definimos un programa de tasa de aprendizaje con calentamiento y caída del coseno, junto con un optimizador AdamW que incluye recorte de gradiente y caída de peso. Esta combinación garantiza un entrenamiento estable y adaptativo. Consulta los CÓDIGOS COMPLETOS aquí.

@jit def Compute_metrics(logits, etiquetas): pérdida = optax.softmax_cross_entropy_with_integer_labels(logits, etiquetas).mean() precisión = jnp.mean(jnp.argmax(logits, -1) == etiquetas) return {‘pérdida’: pérdida, ‘precisión’: precisión} def create_train_state(rng, modelo, input_shape, learning_rate_schedule): variables = model.init(rng, jnp.ones(input_shape), entrenamiento=False) params = variables[‘params’]
lote_stats = variables.get(‘batch_stats’, {}) tx = create_optimizer(learning_rate_schedule) return TrainState.create(apply_fn=model.apply, params=params, tx=tx, lote_stats=batch_stats) @jit def train_step(estado, lote, dropout_rng): imágenes, etiquetas = lote def loss_fn(params): variables = {‘params’: params, ‘batch_stats’: state.batch_stats} logits, new_model_state = state.apply_fn(variables, imágenes, entrenamiento=Verdadero, mutable=[‘batch_stats’]rngs={‘dropout’: dropout_rng}) pérdida = optax.softmax_cross_entropy_with_integer_labels(logits, etiquetas).mean() devolución pérdida, (logits, new_model_state) grad_fn = jax.value_and_grad(loss_fn, has_aux=True) (pérdida, (logits, new_model_state)), grads = grad_fn(estado.params) estado = estado.apply_gradients(graduados=graduados, lote_stats=nuevo_modelo_estado[‘batch_stats’]) métricas = Compute_metrics(logits, etiquetas) estado de retorno, métricas @jit def eval_step(estado, lote): imágenes, etiquetas = variables por lotes = {‘params’: state.params, ‘batch_stats’: state.batch_stats} logits = state.apply_fn(variables, imágenes, entrenamiento=False) return compute_metrics(logits, etiquetas)

Implementamos funciones de capacitación y evaluación compiladas por JIT para lograr una ejecución eficiente. El paso de entrenamiento calcula gradientes, actualiza parámetros y mantiene dinámicamente estadísticas por lotes. También definimos métricas de evaluación que nos ayudan a monitorear la pérdida y la precisión durante todo el proceso de capacitación. Consulta los CÓDIGOS COMPLETOS aquí.

def generar_datos_sintéticos(rng, num_samples=1000, img_size=32): rng_x, rng_y = random.split(rng) imágenes = random.normal(rng_x, (num_samples, img_size, img_size, 3)) etiquetas = random.randint(rng_y, (num_samples,), 0, 10) return imágenes, etiquetas def create_batches(imágenes, etiquetas, tamaño_lote=32): num_batches = len(imágenes) // tamaño_lote para i en rango(num_batches): idx = segmento(i * tamaño_lote, (i + 1) * tamaño_lote) produce imágenes[idx]etiquetas[idx]

Generamos datos sintéticos para simular una tarea de clasificación de imágenes, lo que nos permite entrenar el modelo sin depender de conjuntos de datos externos. Luego, agrupamos los datos de manera eficiente para realizar actualizaciones iterativas. Este enfoque nos permite probar todo el proceso rápidamente y verificar que todos los componentes funcionen correctamente. Consulta los CÓDIGOS COMPLETOS aquí.

def train_model(num_epochs=5, lote_size=32): rng = random.PRNGKey(0) rng, data_rng, model_rng = random.split(rng, 3) train_images, train_labels = generar_synthetic_data(data_rng, num_samples=1000) test_images, test_labels = generate_synthetic_data(data_rng, num_samples=200) modelo = AdvancedCNN(num_classes=10) lr_schedule = create_learning_rate_schedule(base_lr=1e-3, warmup_steps=50, decay_steps=500) estado = create_train_state(model_rng, modelo, (1, 32, 32, 3), lr_schedule) historial = {‘train_loss’: []’tren_acc’: []’test_acc’: []} print(“Comenzando entrenamiento…”) para la época en el rango(num_epochs): train_metrics = []
para lote en create_batches(train_images, train_labels, lot_size): rng, dropout_rng = random.split(rng) estado, métricas = train_step(estado, lote, dropout_rng) train_metrics.append(metrics) train_loss = jnp.mean(jnp.array([m[‘loss’] para m en train_metrics])) train_acc = jnp.mean(jnp.array([m[‘accuracy’] para m en train_metrics])) test_metrics = [eval_step(state, batch) for batch in create_batches(test_images, test_labels, batch_size)]
test_acc = jnp.mean(jnp.array([m[‘accuracy’] para m en test_metrics])) historial[‘train_loss’].append(float(train_loss)) historial[‘train_acc’].append(float(train_acc)) historial[‘test_acc’].append(float(test_acc)) print(f”Epoch {epoch + 1}/{num_epochs}: Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f}, Test Acc: {test_acc:.4f}”) historial de retorno, historial de estado, entrenado_state = train_model(num_epochs=5) fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4)) ax1.plot(historia[‘train_loss’]label=”Pérdida de tren”) ax1.set_xlabel(‘Epoch’); ax1.set_ylabel(‘Pérdida’); ax1.set_title(‘Pérdida de entrenamiento’); ax1.leyenda(); ax1.grid(Verdadero) ax2.plot(historial[‘train_acc’]etiqueta=”Precisión del tren”) ax2.plot(historial[‘test_acc’]label=”Precisión de la prueba”) ax2.set_xlabel(‘Epoch’); ax2.set_ylabel(‘Precisión’); ax2.set_title(‘Precisión del modelo’); ax2.leyenda(); ax2.grid(Verdadero) plt.tight_layout(); plt.show() print(“\n✅ ¡Tutorial completo! Esto cubre:”) print(“- Módulos Flax personalizados (bloques ResNet, Auto-Atención)”) print(“- Optimizadores Optax avanzados (AdamW con recorte de gradiente)”) print(“- Programaciones de tasa de aprendizaje (calentamiento + decaimiento de coseno)”) print(“- Transformaciones JAX (@jit para rendimiento)”) print(“- Gestión adecuada del estado (estadísticas de normalización de lotes)”) print(“- Canal de capacitación completo con evaluación”)

Reunimos todos los componentes para entrenar el modelo durante varias épocas, realizar un seguimiento de las métricas de rendimiento y visualizar las tendencias en pérdida y precisión. Monitoreamos el progreso de aprendizaje del modelo y validamos su desempeño en datos de prueba. En última instancia, confirmamos la estabilidad y eficacia de nuestro flujo de trabajo de formación basado en JAX.

En conclusión, implementamos un proceso de capacitación integral utilizando JAX, Flax y Optax, que demuestra flexibilidad y eficiencia computacional. Observamos cómo las arquitecturas personalizadas, las estrategias de optimización avanzadas y la gestión precisa del estado pueden unirse para formar un flujo de trabajo de aprendizaje profundo de alto rendimiento. A través de este ejercicio, obtenemos una comprensión más profunda de cómo estructurar experimentos escalables en JAX y nos preparamos para adaptar estas técnicas a tareas de investigación y producción de aprendizaje automático del mundo real.

Consulta los CÓDIGOS COMPLETOS aquí. No dude en consultar nuestra página de GitHub para tutoriales, códigos y cuadernos. Además, no dude en seguirnos en Twitter y no olvide unirse a nuestro SubReddit de más de 100.000 ML y suscribirse a nuestro boletín. ¡Esperar! estas en telegrama? Ahora también puedes unirte a nosotros en Telegram.

Asif Razzaq es el director ejecutivo de Marktechpost Media Inc.. Como empresario e ingeniero visionario, Asif está comprometido a aprovechar el potencial de la inteligencia artificial para el bien social. Su esfuerzo más reciente es el lanzamiento de una plataforma de medios de inteligencia artificial, Marktechpost, que se destaca por su cobertura en profundidad del aprendizaje automático y las noticias sobre aprendizaje profundo que es técnicamente sólida y fácilmente comprensible para una amplia audiencia. La plataforma cuenta con más de 2 millones de visitas mensuales, lo que ilustra su popularidad entre el público.

🙌 Siga MARKTECHPOST: agréguenos como fuente preferida en Google.