Análisis de Emociones de Ekman en Twitter
En la era de la transformación digital, comprender cómo se sienten los usuarios en redes sociales se ha convertido en un activo estratégico…
Análisis de Emociones de Ekman en Twitter
En la era de la transformación digital, comprender cómo se sienten los usuarios en redes sociales se ha convertido en un activo estratégico para organizaciones y gobiernos. El análisis de sentimientos permite extraer valor a partir de grandes volúmenes de texto no estructurado, facilitando la toma de decisiones basada en datos.
En este proyecto se desarrolla un modelo de clasificación multiclase capaz de identificar emociones en tweets en español, utilizando técnicas avanzadas de procesamiento de lenguaje natural (NLP) y modelos transformers.
— — — — — — — — — — — — — — — — —
🡆 1. Documento Rector
▶ 1.1. Equipo: SENTIMENTAI
▶ 1.2. Miembros del equipo:

Tabla 1. Miembros del equipo SENTIMENTAI
▶ 1.3. Descripción del problema
En la red social X (antes Twitter), los usuarios expresan constantemente emociones, opiniones y reacciones a través de texto. Sin embargo, el gran volumen de información generada dificulta su análisis manual, limitando la capacidad de identificar patrones emocionales relevantes de manera oportuna.
Esta limitación representa un desafío para organizaciones, investigadores y tomadores de decisiones que requieren comprender el comportamiento y percepción de los usuarios, especialmente ante la presencia de emociones negativas o contenido potencialmente sensible.
▶ 1.4. Idea central del proyecto
El proyecto propone el desarrollo de un modelo basado en Deep Learning y procesamiento de lenguaje natural (NLP) capaz de identificar y clasificar automáticamente emociones en tweets escritos en español.
A través del uso de modelos tipo Transformer y técnicas de fine-tuning, se busca detectar patrones emocionales — especialmente negativos — en los textos, permitiendo un análisis más eficiente, escalable y automatizado.
▶ 1.5. Hipótesis
¿En qué medida un modelo de Deep Learning basado en procesamiento de lenguaje natural puede identificar y clasificar automáticamente las emociones expresadas en tweets en español, permitiendo detectar patrones de sentimiento –especialmente negativos– de manera oportuna en usuarios de X?
▶ 1.6. Objetivos
- Objetivo general:
Desarrollar y evaluar un modelo de aprendizaje profundo capaz de clasificar emociones en textos en español provenientes de X.
- Objetivos específicos:
- Entrenar y evaluar un modelo de Deep Learning para clasificar los sentimientos en categorías: alegría, tristeza, ira, miedo, asco, sorpresa y otros , con hincapié en aquellos sentimientos negativos.
- Identificar patrones emocionales en los textos, con énfasis en emociones negativas.
- Evaluar el desempeño del modelo mediante métricas como Accuracy y F1-score.
- Analizar el comportamiento del modelo frente a textos ambiguos o complejos.
▶ 1.7. Justificación
El español es uno de los idiomas más utilizados en redes sociales a nivel global, lo que genera una gran cantidad de datos textuales sin estructurar. Sin embargo, muchas soluciones de análisis de sentimientos están optimizadas principalmente para inglés.
Este proyecto contribuye al desarrollo de herramientas específicas para el idioma español, utilizando modelos avanzados de NLP, lo cual permite mejorar la comprensión del comportamiento digital y apoyar la toma de decisiones basada en datos.
▶ 1.8. Mercado potencial
El mercado potencial incluye:
- Instituciones académicas y centros de investigación
- Empresas de marketing digital
- Equipos de Business Intelligence (BI)
- Organizaciones interesadas en análisis de opinión pública.
▶ 1.9. Clientes y usuarios
- Clientes:
- Científicos de Datos,
- Ingenieros de Datos,
- Analistas de Datos.
- Usuarios finales:
- Equipos de Business Intelligence (BI),
- Gerentes de producto,
- Directores de marketing,
- Analistas de comunicación digital.
▶ 1.10. Fuentes de información
Para el desarrollo del proyecto se utilizará un conjunto de datos de 5000 tweets en español provenientes del corpus TASS 2020, data-set ampliamente utilizado en investigaciones de análisis de sentimiento.
▶ 1.11. Selección del modelo
En este proyecto se trabajó con dos enfoques de modelado: un modelo preentrenado y un modelo entrenado desde cero.
Para el primero, se utilizó una arquitectura Transformer, específicamente BETO (BERT en español), aprovechando su conocimiento previo del lenguaje mediante un proceso de fine-tuning.
En contraste, se implementó un modelo desde cero, con el fin de evaluar las diferencias de rendimiento frente a un modelo previamente entrenado,
▶ 1.12. Descripción de la solución (alcance)
La solución será un análisis multiclase que tomará una muestra aleatoria de 5,000 tweets en español del año 2019.
▶ 1.13. Propuesta de valor
La propuesta de valor radica en ofrecer una herramienta tecnológica capaz de analizar emociones en X en español de manera automática, permitiendo identificar patrones y detectar contenido negativo o potencialmente dañino para la institución.
▶ 1.14. Nombre detallado del proyecto
Sistema de detección temprano de emociones negativas aplicado a tweets en español mediante Deep Learning.
▶ 1.15. Nombre corto
SentimentAI
▶ 1.16. Fuentes
Robertuito-Análisis-sentimental. (2020). https://huggingface.co/pysentimiento/robertuito-sentiment-analysis
TASS 2020. Workshop on Semantic Analysis at SEPLN 2020 http://tass.sepln.org/2020/
— — — — — — — — — — — — —
🡆2. Descripción General del Dataset
▶ 2.1 Estructura del dataset
id: identificador único del tweet
tweet: texto original
label: emoción asociada
El conjunto de datos utilizado corresponde a tweets en español etiquetados según las emociones básicas propuestas por Paul Ekman.
📁 Train: 5.886 registros
📁 Test: 857 registros
▶ 2.2. Variable dependiente
Se consideran 7 categorías basadas en el modelo de Ekman:

Figura 1. Clasificación multiclase de emociones básicas según el modelo de Paul Ekman
▶ 2.3. Desbalance de clases
Se observa una distribución desigual, donde algunas emociones (como fear o disgust tienen muy pocos ejemplos) están subrepresentadas. Esto influye directamente en la selección de métricas de evaluación.
▶ 2.4. Preprocesamiento de texto
- Eliminación de ruido (URLs, emojis, hashtags, menciones)
- Normalización (minúsculas, eliminación de caracteres especiales)
- Limpieza de espacios y tokens irrelevantes
print("=" * 90)
print("🧹 COMPARACIÓN: ANTES vs DESPUÉS DE LIMPIEZA — 10 registros (DEV)")
print("=" * 90)
# Construimos una tabla lado a lado para comparar visualmente el antes y el después
pd.set_option('display.max_colwidth', 130)
comparacion = pd.DataFrame({
'ID': df_dev['id'].head(10),
'ORIGINAL': df_dev['tweet'].head(10), # Texto original con ruido
'LIMPIO': df_dev['tweet_limpio'].head(10), # Texto procesado y normalizado
'EMOCIÓN': df_dev['label'].head(10)
})
display(comparacion)
# Calculamos estadísticas de la reducción de ruido
long_orig = df_dev['tweet'].str.len().mean() # Longitud media antes
long_limp = df_dev['tweet_limpio'].str.len().mean() # Longitud media después
reduccion = (long_orig - long_limp) / long_orig * 100 # Porcentaje de reducción
print(f"\n📊 ESTADÍSTICAS DE LIMPIEZA (promedio por tweet):")
print(f" Caracteres antes : {long_orig:.0f}")
print(f" Caracteres después: {long_limp:.0f}")
print(f" Reducción de ruido: {reduccion:.1f}%")
print(f" Tweets vacíos (eliminados): {(df_dev['tweet_limpio'].str.len() == 0).sum()}")

Figura 2. Antes y después de la limpieza
▶ 2.5. Análisis exploratorio (EDA)
La imagen evidencia la complejidad del análisis de datos en X, donde los textos presentan alto nivel de ruido debido al uso de emojis, símbolos, menciones y variaciones del lenguaje. Esto hace necesario aplicar procesos de limpieza y normalización antes del modelado para asegurar la calidad de los datos.
Además, el gran volumen de publicaciones dificulta su análisis manual, lo que resalta la importancia de utilizar modelos de procesamiento de lenguaje natural, como BETO o LSTM, para identificar patrones, emociones y contenido relevante de forma automatizada.

Figura 3. Distribución de Emociones de Ekman
— — — — — — — — — — —
🡆 3. Modelo Pre-entrenado — Modelo 1
▶ 3.1 Metodología
La metodología adoptada se basa en un enfoque moderno de procesamiento de lenguaje natural orientado a la comprensión contextual del texto, mediante el uso de modelos basados en arquitectura Transformer, específicamente BETO. A diferencia de enfoques secuenciales tradicionales, este modelo analiza cada tweet considerando la relación entre todas las palabras de la secuencia, gracias a su mecanismo de autoatención, lo que le permite capturar matices complejos como ambigüedad, ironía o intensidad emocional.
Su implementación se realiza a partir de un modelo preentrenado (dccuchile/bert-base-spanish-wwm-cased), el cual es adaptado a la tarea de clasificación de emociones mediante un proceso de fine-tuning. Este enfoque permite aprovechar conocimiento lingüístico previamente aprendido y especializarlo en el dominio específico del proyecto.
▶3.2. Definición de hiperparámetros
Los hiperparámetros fueron definidos considerando buenas prácticas para el fine-tuning de modelos Transformer, las características del dataset y las limitaciones computacionales del entorno (CPU). Se buscó un equilibrio entre eficiencia, estabilidad y capacidad de generalización del modelo. A continuación se presenta el código con los hiperparámetros utilizados:
# ════════════════════════════════════════════════════════════════════════
# HIPERPARÁMETROS — ajustados para CPU i5 (sin GPU)
# ════════════════════════════════════════════════════════════════════════
# Longitud máxima de tokens por tweet
# Los tweets tienen un máximo de 280 caracteres → 96 tokens es suficiente
# Bajar de 128 a 96 reduce la memoria RAM y el tiempo por paso en ~25%
# La atención cuadrática de BERT es O(n²): pasar de 128 a 96 es 56% menos cómputo
MAX_LENGTH = 96
# Tamaño del batch por paso
# En CPU con 8GB RAM, batch=8 usa ~1.5GB → deja margen para el sistema operativo
# Batch más grande = más preciso pero más lento y más RAM
BATCH_SIZE = 8
# Acumulación de gradientes
# Acumular 4 pasos de batch=8 simula un batch efectivo de 32
# Batch grande estabiliza el gradiente → mejor convergencia
# Sin necesidad de más RAM porque los pasos individuales siguen siendo de 8
GRAD_ACCUM = 4 # batch efectivo = BATCH_SIZE × GRAD_ACCUM = 8 × 4 = 32
# Número de épocas
# 3 épocas es suficiente para fine-tuning de BERT/RoBERTa en datasets medianos
# Más épocas → mayor riesgo de overfitting y mucho más tiempo en CPU
NUM_EPOCHS = 3
# Tasa de aprendizaje inicial para el optimizador AdamW
# Rango estándar para fine-tuning de Transformers: 1e-5 a 5e-5
# 2e-5 es el punto de equilibrio entre velocidad de convergencia y estabilidad
LEARNING_RATE = 2e-5
# Regularización L2: penaliza pesos muy grandes para reducir el overfitting
WEIGHT_DECAY = 0.01
# Pasos de calentamiento (warmup)
# El LR sube gradualmente de 0 a LEARNING_RATE durante los primeros 100 pasos
# Evita que el modelo "rompa" los pesos preentrenados al inicio del entrenamiento
WARMUP_STEPS = 100
# Cada cuántos pasos evaluamos y posiblemente guardamos un checkpoint
# Con 5886 muestras y batch=8 → ~736 pasos/época
# Evaluar cada 200 pasos = ~3.6 evaluaciones por época (suficiente granularidad)
EVAL_STEPS = 200
# Directorio raíz donde se guardarán los checkpoints de ambos modelos
CHECKPOINT_DIR = './checkpoints'
🡆 3.3. Justificación de la arquitectura
El uso de modelos basados en arquitectura Transformer responde a su capacidad para capturar relaciones semánticas complejas dentro del texto, sin depender de la secuencialidad estricta de los datos. Esto permite manejar de mejor manera fenómenos como ambigüedad lingüística, variaciones contextuales y expresiones propias del lenguaje en redes sociales.
Además, este tipo de modelos reduce significativamente la necesidad de ingeniería manual de características, ya que aprende representaciones directamente desde los datos, lo que resulta especialmente útil en tareas de análisis de sentimientos.
▶ 3.4. Modelado
Para la etapa de modelado se utilizó un enfoque de fine-tuning sobre el modelo preentrenado BETO, implementado mediante la librería Hugging Face Transformers. Este modelo fue cargado y adaptado a la tarea de clasificación mediante la especificación del número de clases (NUM_LABELS), incorporando una capa de salida adecuada para el problema.
mdl_beto = AutoModelForSequenceClassification.from_pretrained(
'dccuchile/bert-base-spanish-wwm-cased',
num_labels=NUM_LABELS
).to(DEVICE)
🡆 3.5. Entrenamiento y Validación
▶ El entrenamiento del modelo se llevó a cabo utilizando la clase Trainer de la librería Hugging Face Transformers, incorporando una implementación personalizada de la función de pérdida basada en CrossEntropyLoss. La configuración incluyó la evaluación al final de cada época (eval_strategy='epoch'), el guardado automático de checkpoints por época y la selección del mejor modelo en función del F1-score macro, priorizando un rendimiento equilibrado entre clases. Adicionalmente, se implementó un mecanismo de early stopping con una paciencia de dos épocas sin mejora, lo que permitió monitorear el desempeño del modelo de forma continua, prevenir el sobreajuste y garantizar la selección automática del mejor punto de entrenamiento.
trainer_beto = TrainerCELoss(
model=mdl_beto,
args=args_beto,
train_dataset=train_ds_beto,
eval_dataset=dev_ds_beto,
compute_metrics=compute_metrics,
callbacks=[EarlyStoppingCallback(early_stopping_patience=2)]
)
🡆 3.6. 📊Resultados
▶ 📈Hallazgos principales:
- El modelo Transformer (BETO) funcionó efectivamente.
- Mejor desempeño en emociones frecuentes (joy, others)
- Menor desempeño en clases minoritarias (fear, disgust)

Figura 4. Análisis Visual Métricas
— — — — — — — — — — — — —
🡆4. Modelo Desde Cero — Modelo 2
▶ 4.1. Metodología:
La metodología implementada sigue un enfoque estructurado de procesamiento de lenguaje natural para la clasificación de emociones en tweets, a través de un modelo LSTM (Long Short-Term Memory) se implementa mediante la clase nn.LSTM de PyTorch, configurada como bidireccional y multicapa, permitiendo procesar secuencias de texto y capturar dependencias contextuales para la clasificación de emociones.
▶ 4.2. Definición de hiperparámetros
Se implementó un modelo basado en una arquitectura LSTM bidireccional multicapa (2 capas, 128 unidades ocultas), capaz de capturar dependencias contextuales en los tweets. Se aplicó dropout (0.5) para reducir el sobreajuste y una capa densa final para la clasificación. Como función de pérdida se utilizó Focal Loss, permitiendo manejar el desbalance de clases al priorizar ejemplos difíciles. La optimización se realizó con Adam y un scheduler ReduceLROnPlateau, lo que favorece una convergencia más estable durante el entrenamiento.
modelo = LSTMClasificador(
embedding_matrix=embedding_matrix,
hidden_dim= 128,
num_clases=NUM_CLASES,
num_layers=2,
dropout=0.5,
fc_dim=64,
).to(DEVICE)
# Criterio: Focal Loss en lugar de CrossEntropyLoss
# criterio = nn.CrossEntropyLoss()
criterio = FocalLoss(
gamma=1,
alpha=None#alpha_tensor, # pesos de clase calculados arriba
)
optimizer = torch.optim.Adam(modelo.parameters(), lr=5e-4, weight_decay=1e-4)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=4)#, factor=0.5, min_lr=1e-6)
🡆 4.3. Justificación de la arquitectura
Para el modelado, se implementa una red neuronal basada en una arquitectura LSTM (Long Short-Term Memory) bidireccional, la cual procesa las secuencias de texto y captura dependencias contextuales en ambas direcciones. La capa de embeddings es inicializada con los vectores de FastText y posteriormente descongelada para permitir fine-tuning. El entrenamiento del modelo se realiza utilizando el optimizador Adam, incorporando regularización mediante dropout y control de gradientes. Asimismo, se emplea la función de pérdida Focal Loss para abordar el desbalance de clases, enfocando el aprendizaje en ejemplos difíciles. Finalmente, el modelo es evaluado sobre los conjuntos de validación y prueba, generando métricas de desempeño y reportes de clasificación que permiten analizar su capacidad para identificar emociones en textos reales.
class LSTMClasificador(nn.Module):
def __init__(self, embedding_matrix, hidden_dim, num_clases,
num_layers=2, dropout=0.3, bidireccional=True,
fc_dim=64):
super().__init__()
vocab_size, emb_dim = embedding_matrix.shape
# Capa de embeddings inicializada con FastText — se puede fine-tunear
self.embedding = nn.Embedding.from_pretrained(
embedding_matrix,
freeze=True, # True = congela los pesos FastText
padding_idx=0 # PAD no contribuye al gradiente
)
self.lstm = nn.LSTM(
input_size=emb_dim,
hidden_size=hidden_dim,
num_layers=num_layers,
batch_first=True,
dropout=dropout,
bidirectional=bidireccional
)
self.dropout = nn.Dropout(dropout)
# Si es bidireccional el hidden es hidden_dim * 2
lstm_out_dim = hidden_dim * 2 if bidireccional else hidden_dim
self.clasificador = nn.Sequential(
nn.Linear(lstm_out_dim, fc_dim),
nn.ReLU(),
nn.Dropout(dropout),
nn.Linear(fc_dim, num_clases)
)
def forward(self, x):
# x: (batch, max_len)
emb = self.dropout(self.embedding(x)) # (batch, max_len, 300)
out, (hn, _) = self.lstm(emb) # out: (batch, max_len, hidden*2)
# Concatenar último estado oculto de ambas direcciones
hn = torch.cat([hn[-2], hn[-1]], dim=1) # (batch, hidden*2)
hn = self.dropout(hn)
return self.clasificador(hn) # (batch, num_clases)
class FocalLoss(nn.Module):
"""
Focal Loss para clasificación multiclase.
gamma: factor de enfoque. 0 = CrossEntropyLoss estándar.
Valores típicos: 1.0 – 3.0. Empieza con 2.0.
alpha: tensor de pesos por clase (opcional). Si None,
todas las clases tienen igual peso base.
"""
def __init__(self, gamma=2.0, alpha=None, reduction='mean'):
super().__init__()
self.gamma = gamma
self.alpha = alpha # tensor (num_clases,) o None
self.reduction = reduction
def forward(self, logits, targets):
# Probabilidades por clase via softmax
probs = torch.softmax(logits, dim=1) # (B, C)
# Probabilidad de la clase verdadera para cada muestra
pt = probs.gather(1, targets.unsqueeze(1)).squeeze(1) # (B,)
# Término focal: penaliza menos los ejemplos fáciles (pt alto)
focal_w = (1 - pt) ** self.gamma # (B,)
# Cross-entropy base (por muestra, sin reducción)
ce_loss = nn.functional.cross_entropy(
logits, targets, weight=self.alpha, reduction='none'
) # (B,)
loss = focal_w * ce_loss # (B,)
if self.reduction == 'mean':
return loss.mean()
elif self.reduction == 'sum':
return loss.sum()
return loss # 'none'
🡆 4.4. Entrenamiento y Validación
Se implementa un proceso de entrenamiento para un modelo LSTM que incorpora manejo del desbalance de clases mediante pesos inversamente proporcionales y el uso de Focal Loss. La optimización se realiza con Adam y un scheduler ReduceLROnPlateau para ajustar dinámicamente la tasa de aprendizaje. Durante el entrenamiento se aplican técnicas como gradient clipping para estabilidad y fine-tuning progresivo al descongelar embeddings en etapas posteriores. Finalmente, se selecciona y guarda automáticamente el mejor modelo según la pérdida de validación.
# Calcular pesos de clase inversamente proporcionales a su frecuencia
# Usar SOLO los datos de entrenamiento (y_train), nunca todo el dataset
clases, conteos = np.unique(y_train, return_counts=True)
alpha_np = 1.0 / conteos.astype(float)
alpha_np = alpha_np / alpha_np.sum() # normalizar a suma = 1
alpha_tensor = torch.tensor(alpha_np, dtype=torch.float32).to(DEVICE)
print("Pesos alpha por clase:")
for cls, w in zip(le.classes_, alpha_np):
print(f" {cls:12} → {w:.4f}")
modelo = LSTMClasificador(
embedding_matrix=embedding_matrix,
hidden_dim= 128,
num_clases=NUM_CLASES,
num_layers=2,
dropout=0.5,
fc_dim=64,
).to(DEVICE)
# Criterio: Focal Loss en lugar de CrossEntropyLoss
# criterio = nn.CrossEntropyLoss()
criterio = FocalLoss(
gamma=1,
alpha=None#alpha_tensor, # pesos de clase calculados arriba
)
optimizer = torch.optim.Adam(modelo.parameters(), lr=5e-4, weight_decay=1e-4)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=4)#, factor=0.5, min_lr=1e-6)
def entrenar_epoca(modelo, dl, criterio, optimizer):
modelo.train()
total_loss = 0
for X_batch, y_batch in dl:
X_batch, y_batch = X_batch.to(DEVICE), y_batch.to(DEVICE)
optimizer.zero_grad()
logits = modelo(X_batch)
loss = criterio(logits, y_batch)
loss.backward()
nn.utils.clip_grad_norm_(modelo.parameters(), max_norm=1.0) # evita exploding gradients
optimizer.step()
total_loss += loss.item() * X_batch.size(0) # multiplicamos por el tamaño del batch para acumular la pérdida total en lugar de la media del batch (des-promediando el batch)
return total_loss / len(dl.dataset) # dividimos por el número total de muestras para obtener la pérdida promedio por muestra
def evaluar(modelo, dl, criterio):
modelo.eval()
total_loss, preds, trues = 0, [], []
with torch.no_grad():
for X_batch, y_batch in dl:
X_batch, y_batch = X_batch.to(DEVICE), y_batch.to(DEVICE)
logits = modelo(X_batch)
total_loss += criterio(logits, y_batch).item() * X_batch.size(0)
preds.extend(logits.argmax(dim=1).cpu().tolist())
trues.extend(y_batch.cpu().tolist())
return total_loss / len(dl.dataset), preds, trues
# ── Loop de entrenamiento ─────────────────────────────────────────
EPOCHS = 50
UNFREEZE_EPOCH = 5 # a partir de qué época descongelar embeddings
valid_loss_min = np.inf # track change in validation loss
train_losses, valid_losses = [], []
for epoch in range(1, EPOCHS + 1):
# ── Descongelar embeddings tras UNFREEZE_EPOCH épocas ──────────
if epoch == UNFREEZE_EPOCH:
modelo.embedding.weight.requires_grad = True
print(f"\n[Época {epoch}] Embeddings descongelados — fine-tuning activo\n")
loss_train = entrenar_epoca(modelo, train_dl, criterio, optimizer)
loss_val, preds, trues = evaluar(modelo, val_dl, criterio)
train_losses.append(loss_train)
valid_losses.append(loss_val)
scheduler.step(loss_val)
print(f"Época {epoch:02d} │ loss_train: {loss_train:.4f} │ loss_val: {loss_val:.4f}")
# save model if validation loss has decreased
if loss_val <= valid_loss_min:
print('Validation loss decreased ({:.6f} --> {:.6f}). Saving model ...'.format(
valid_loss_min,
loss_val))
torch.save(modelo.state_dict(), 'modelo_sent_lstm_v6_II.pth')
valid_loss_min = loss_val

Figura 5. Entrenamiento y Validación
🡆 4. 5. Resultados 📊
- Uno de los principales desafíos del modelo fue el marcado desbalance de clases presente en el conjunto de datos, lo cual impactó directamente en su capacidad de aprendizaje. A pesar de aplicar estrategias para mitigar este problema, el rendimiento obtenido no fue homogéneo entre las distintas categorías.
- En particular, las métricas de evaluación muestran un desempeño significativamente bajo en clases como anger, disgust y surprise, donde los valores de precision, recall y f1-score son prácticamente nulos, evidenciando dificultades para identificar estas emociones. En conjunto, estos resultados reflejan limitaciones en la capacidad de generalización del modelo y confirman que el desbalance de clases continúa siendo un factor crítico que condiciona su desempeño.

Figura 5. Métricas de Evaluación
— — — — — — — — — — — — — — — — 5. Conclusiones
- Los resultados evidencian una clara ventaja del modelo preentrenado BETO, que alcanza un accuracy del 71%, frente al 51% obtenido por el modelo LSTM entrenado desde cero. Esta diferencia refleja el valor del conocimiento previo incorporado en modelos basados en arquitectura Transformer, especialmente en tareas de procesamiento de lenguaje natural en español.
- Asimismo, en escenarios con desbalance de clases, BETO demuestra un desempeño más robusto y estable, logrando una mejor generalización. Esto se debe, en gran medida, a que los modelos preentrenados han sido expuestos a grandes volúmenes de datos, a diferencia del LSTM, cuyo aprendizaje depende únicamente de un conjunto de datos más limitado, lo que restringe su capacidad de representación y rendimiento.
메타데이터
- post_id
- ecf48fc6a519
- slug
- análisis-de-emociones-de-ekman-en-twitter-ecf48fc6a519
- url
- https://medium.com/@jarelly.sampedro/an%C3%A1lisis-de-emociones-de-ekman-en-twitter-ecf48fc6a519
- canonical_url
- https://medium.com/@jarelly.sampedro/an%C3%A1lisis-de-emociones-de-ekman-en-twitter-ecf48fc6a519
- author_url
- https://medium.com/@jarelly.sampedro
- status
- ok
- fetched_at
- 2026-06-09 15:37:30