Proyecto de investigacion que compara el rendimiento de modelos unimodales (solo texto) contra modelos multimodales (texto + imagen) en tareas de clasificacion.
Pregunta de Investigacion
¿Cuando agregar informacion visual mejora significativamente la clasificacion de texto, y cuando es solo overhead computacional?
Modelos Evaluados
Modelos Unimodales (Texto)
| Modelo | Parametros | Descripcion |
|---|---|---|
| BERT-base | 110M | Transformer encoder preentrenado |
| RoBERTa | 125M | BERT con mejor preentrenamiento |
| BETO | 110M | BERT para espanol |
Modelos Multimodales
| Modelo | Parametros | Modalidades |
|---|---|---|
| CLIP | 400M | Imagen + Texto (contrastivo) |
| FLAVA | 350M | Imagen + Texto (fusion) |
| ViLT | 113M | Vision-Language Transformer |
Metodologia
Pipeline de Entrenamiento
class MultimodalTrainer:
def __init__(self, model_name: str, dataset: Dataset):
self.model = self._load_model(model_name)
self.dataset = dataset
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
def train(self, epochs: int = 10, batch_size: int = 32):
self.model.to(self.device)
optimizer = AdamW(self.model.parameters(), lr=2e-5)
for epoch in range(epochs):
self.model.train()
total_loss = 0
for batch in DataLoader(self.dataset, batch_size=batch_size):
# Forward pass
if self.is_multimodal:
outputs = self.model(
input_ids=batch['input_ids'].to(self.device),
pixel_values=batch['pixel_values'].to(self.device),
labels=batch['labels'].to(self.device)
)
else:
outputs = self.model(
input_ids=batch['input_ids'].to(self.device),
labels=batch['labels'].to(self.device)
)
loss = outputs.loss
total_loss += loss.item()
# Backward pass
loss.backward()
optimizer.step()
optimizer.zero_grad()
print(f"Epoch {epoch}: Loss = {total_loss / len(self.dataset)}")
Datasets Utilizados
- Hateful Memes (Facebook): Deteccion de contenido de odio en memes
- SNLI-VE: Inferencia textual con evidencia visual
- VQA v2: Respuesta a preguntas sobre imagenes
- Custom News Dataset: Clasificacion de noticias chilenas con imagenes
Preprocesamiento
class MultimodalProcessor:
def __init__(self, model_name: str):
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.image_processor = AutoImageProcessor.from_pretrained(model_name)
def process(self, text: str, image: Image) -> Dict:
# Tokenizar texto
text_inputs = self.tokenizer(
text,
max_length=512,
truncation=True,
padding='max_length',
return_tensors='pt'
)
# Procesar imagen
image_inputs = self.image_processor(
image,
return_tensors='pt'
)
return {
'input_ids': text_inputs['input_ids'],
'attention_mask': text_inputs['attention_mask'],
'pixel_values': image_inputs['pixel_values']
}
Optimizaciones CUDA
Mixed Precision Training
from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
for batch in dataloader:
optimizer.zero_grad()
with autocast():
outputs = model(**batch)
loss = outputs.loss
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
Gradient Checkpointing
# Reducir uso de memoria en modelos grandes
model.gradient_checkpointing_enable()
Multi-GPU con DataParallel
if torch.cuda.device_count() > 1:
model = nn.DataParallel(model)
print(f"Using {torch.cuda.device_count()} GPUs")
Resultados
Hateful Memes Dataset
| Modelo | Accuracy | F1 | AUC-ROC |
|---|---|---|---|
| BERT | 62.3% | 0.58 | 0.67 |
| CLIP | 68.7% | 0.65 | 0.74 |
| FLAVA | 71.2% | 0.68 | 0.77 |
| ViLT | 69.5% | 0.66 | 0.75 |
News Classification (Custom)
| Modelo | Accuracy | F1 Macro |
|---|---|---|
| BETO | 87.2% | 0.86 |
| CLIP | 85.4% | 0.84 |
| FLAVA | 86.8% | 0.85 |
Conclusiones
-
Multimodal ayuda cuando la imagen es relevante: En Hateful Memes, donde el significado depende de la combinacion texto-imagen, FLAVA supera a BERT por ~9%.
-
Texto es suficiente en muchos casos: En clasificacion de noticias, donde las imagenes son genericas, BETO iguala o supera a modelos multimodales.
-
Trade-off computacional: Modelos multimodales requieren ~4x mas VRAM y ~3x mas tiempo de entrenamiento.
Recomendacion:
├── Imagen es parte del significado → Multimodal (FLAVA)
├── Imagen es decorativa → Unimodal (BERT/BETO)
└── Recursos limitados → ViLT (mas eficiente)
Codigo y Reproducibilidad
El repositorio incluye: - Scripts de entrenamiento para todos los modelos - Notebooks de analisis de resultados - Configuraciones de hiperparametros - Checkpoints de modelos entrenados
# Entrenar FLAVA en Hateful Memes
python train.py \
--model flava \
--dataset hateful_memes \
--epochs 10 \
--batch_size 16 \
--learning_rate 2e-5