¿Eres realmente introvertido o extrovertido? Descubre tu personalidad con Inteligencia Artificial

 

¿Puede la Inteligencia Artificial predecir tu personalidad?






La personalidad humana ha sido objeto de estudio durante siglos, pero ¿qué pasaría si pudiéramos predecir si alguien es introvertido o extrovertido solo analizando su comportamiento social? 🌍

Con los avances en Machine Learning, ahora es posible descubrir patrones en datos personales que revelan aspectos clave de la personalidad. En este estudio, exploramos cómo los hábitos sociales, el tiempo en solitario y la interacción en eventos pueden ser utilizados por un modelo de Red Neuronal para clasificar con alta precisión si una persona es extrovertida o introvertida.



Test de Personalidad - ¿Introvertido o Extrovertido?

Extrovertido vs. Introvertido: ¿Qué dice la inteligencia artificial sobre ti?

¿Coincidirá la IA con lo que piensas sobre ti mismo? Averígualo aquí



Este análisis no solo tiene aplicaciones en psicología y desarrollo personal, sino también en campos como el marketing, la inteligencia artificial y la interacción social digital. ¿Qué dicen los datos sobre ti? ¡Descubramos juntos los secretos detrás de la personalidad! 


Descubre paso a paso como se ha realizado!


1. Selección del conjunto de datos

Extrovert vs. Introvert Personality Traits Dataset


Puedes encontrar el dataset en Kaggle en el siguiente enlace: Kaggle - Extrovert vs. Introvert Personality Traits Dataset.


Este conjunto de datos ha sido seleccionado porque proporciona una rica fuente de información sobre la relación entre los rasgos de personalidad (introversión y extroversión) y el comportamiento social. La elección se basa en los siguientes aspectos:

  • Relevancia psicológica: Permite analizar tendencias de comportamiento que pueden ser útiles para psicólogos y sociólogos en estudios sobre salud mental y bienestar social.
  • Aplicaciones en machine learning: Puede utilizarse para predecir rasgos de personalidad basándose en patrones de comportamiento social.
  • Fuentes confiables: Kaggle es una plataforma ampliamente utilizada por la comunidad de ciencia de datos, lo que garantiza la calidad del dataset
Consta de 2,900 filas y 8 columnas, proporcionando una muestra suficientemente amplia para generar modelos predictivos y análisis estadísticos. Es útil en múltiples áreas como la psicología y la sociología, especialmente para comprender cómo las diferencias de personalidad influyen en la interacción social.


2. Definición del problema


Predicción de la personalidad (Extrovertido vs. Introvertido) a partir de patrones de comportamiento social

Utilizando los datos recopilados sobre hábitos sociales y niveles de interacción, podemos entrenar un modelo de aprendizaje automático para predecir si una persona es introvertida o extrovertida en función de sus respuestas en las siguientes variables:

  • Time_spent_Alone: ¿Cuánto tiempo pasa sola una persona al día?
  • Social_event_attendance: ¿Con qué frecuencia asiste a eventos sociales?
  • Stage_fear: ¿Tienes miedo escénico?
  • Going_outside: ¿Sale con frecuencia?
  • Post_frequency: ¿Publica contenido en redes sociales regularmente?
  • Friends_circle_size: ¿Tiene un círculo de amigos amplio o reducido?
  • Drained_after_socializing: ¿Siente agotamiento después de socializar?
  • Personality: Variable objetivo, extrovertido o introvertido


Objetivos

  1. Clasificar a los individuos como extrovertidos o introvertidos en función de sus patrones de comportamiento social.
  2. Analizar la influencia de distintas variables en la predicción de la personalidad, identificando los factores más determinantes.
  3. Optimizar el modelo con técnicas de pre procesamiento y validación para mejorar su precisión.

3. Recolección y preparación de datos


3.1 Limpieza de datos

a) Manejo de valores nulos

Para identificar valores faltantes, primero realizamos una exploración del conjunto de datos:

import pandas as pd
# Cargar el conjunto de datos
df = pd.read_csv("extrovert-vs-introvert-behavior.csv")
# Verificar valores nulos
print(df.isnull().sum())





  • Para tratar los valores nulos en las columnas numéricas como Time_spent_Alone o Friends_circle_size, aplicamos imputación usando la mediana, dado que estos valores pueden tener distribuciones sesgadas.
  • Para los valores nulos en columnas categóricas como Drained_after_socializing o Stage_fear, los reemplazaremos por la categoría más frecuente.

 

# Separar las columnas numericas y categoricas
numerical_cols = df.select_dtypes(include=['number']).columns
categorical_cols = df.select_dtypes(include=['object', 'category']).columns

# Rellenar los valores nulos de las columnas numéricas con la mediana
df[numerical_cols] = df[numerical_cols].fillna(df[numerical_cols].median())

# Rellenar los valores nulos de las columnas categóricas con la moda
for col in categorical_cols:
    df[col] = df[col].fillna(df[col].mode()[0])

Comprobación de que no tenemos valores nulos en nuestro conjunto de datos: 

Justificación: La mediana es una mejor opción que la media cuando hay valores extremos, y la moda ayuda a preservar la coherencia en categorías.


b) Eliminación de duplicados

Buscamos registros duplicados para evitar sesgos en el modelo:

print(f"Duplicados antes: {df.duplicated().sum()}")
df.drop_duplicates(inplace=True)
print(f"Duplicados después: {df.duplicated().sum()}")

Justificación: Los datos duplicados pueden sesgar el aprendizaje del modelo al sobre-representar ciertos patrones.


c) Eliminación de columnas irrelevantes

Going_outside:

La premisa de considerar Going_outside como redundante con Social_event_attendance se basa en la posible correlación entre ambas variables. En teoría, una persona que asiste con frecuencia a eventos sociales también sale con regularidad, lo que podría hacer que ambas características midan patrones similares de comportamiento.

Sin embargo, para determinar si realmente es redundante, podemos hacer un análisis de correlación y evaluar su impacto en el modelo.

import numpy as np

correlation = df[['Going_outside', 'Social_event_attendance']].corr(method='pearson')
print(correlation)

El coeficiente de correlación de 0.7189 entre Going_outside y Social_event_attendance indica que hay una fuerte relación entre ambas variables, aunque no son completamente redundantes. En términos generales, un coeficiente mayor a 0.7 sugiere una fuerte asociación, lo que implica que ambas variables están midiendo aspectos similares del comportamiento social.

Stage_fear:

Realizamos un análisis de correlación entre Stage_fear y Personality usando un coeficiente de correlación como Chi-cuadrado (para variables categóricas) o Point-Biserial (cuando una variable es binaria y la otra es categórica):

import scipy.stats as stats

# Prueba de Chi-cuadrado para relación entre Stage_fear y Personality
contingency_table = pd.crosstab(df['Stage_fear'], df['Personality'])
chi2, p, dof, expected = stats.chi2_contingency(contingency_table)

print(f"Chi-cuadrado: {chi2}, p-valor: {p}")

Interpretación: El p-valor de 0.0 indica que hay una relación estadísticamente significativa entre Stage_fear y Personality. Esto significa que el miedo escénico sí está correlacionado con la clasificación de extroversión/introversión, lo que sugiere que no deberíamos eliminar esta columna sin antes analizar su impacto en el modelo.

Podemos visualizar la relación entre Stage_fear y Personality usando gráficos de barras o histogramas para ver si la presencia de miedo escénico influye en la clasificación de extrovertido/introvertido:

import seaborn as sns
import matplotlib.pyplot as plt

sns.countplot(x="Stage_fear", hue="Personality", data=df)
plt.title("Distribución de Stage_fear según Personality")
plt.show()

Una vez analizadas las variables que a priori podíamos suponer que no aportar valor al modelo predictivo, es importante también realizar un análisis general de todas las variables que tenemos, este paso se realizará más adelante, una vez que transformemos todas las variables en el formato adecuado para trabajar con ellas.

Eso significa que, aunque hay algunas correlaciones moderadas entre variables, ninguna alcanza un nivel tan alto como para considerarse completamente redundante. Lo más prudente sería mantenerlas todas por ahora, ya que ninguna supera el umbral de 0.85, que generalmente indica multicolinealidad severa.


3.2 Tranformaciones aplicadas


a) Conversión de variables categóricas a numéricas

Las variables como Drained_after_socializing, Stage_fear y Personality son categóricas. Usamos codificación binaria:

df["Drained_after_socializing"] = df["Drained_after_socializing"].map({"Yes": 1, "No": 0})
df["Stage_fear"] = df["Stage_fear"].map({"Yes": 1, "No": 0})
df["Personality"] = df["Personality"].map({"Extrovert": 1, "Introvert": 0})


Justificación: Un esquema de valores binarios facilita el entrenamiento del modelo sin perder información.

b) Normalización de valores numéricos

Para evitar que variables con escalas más grandes dominen el modelo, aplicamos normalización Min-Max:

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
df[["Time_spent_Alone", "Social_event_attendance", "Friends_circle_size",
"Post_frequency"]] = scaler.fit_transform(df[["Time_spent_Alone",
"Social_event_attendance", "Friends_circle_size", "Post_frequency"]])

Justificación: La normalización garantiza que todas las características tengan la misma escala y evita que variables con valores más altos influyan más en el modelo.


Después de estos pasos, el conjunto de datos está listo para ser utilizado en la construcción del modelo de Machine Learning. Se han eliminado valores faltantes, duplicados y columnas irrelevantes, además de transformar variables categóricas y normalizar valores numéricos para mejorar la calidad del análisis.


4. Análisis Exploratorio de Datos (EDA)

Vamos a realizar el Análisis Exploratorio de Datos (EDA) para identificar patrones y tendencias clave en el conjunto de datos.

4.1. Visualización de la distribución de las características

Para entender la distribución de los valores en cada variable, generamos histogramas:

import matplotlib.pyplot as plt
import seaborn as sns

# Lista de columnas numéricas
numeric_columns = ["Time_spent_Alone", "Social_event_attendance", "Friends_circle_size", "Post_frequency"]

# Crear histogramas
plt.figure(figsize=(12, 8))
for i, col in enumerate(numeric_columns, 1):
    plt.subplot(2, 2, i)
    sns.histplot(df[col], bins=20, kde=True)
    plt.title(f"Distribución de {col}")

plt.tight_layout()
plt.show()


 

Insights obtenidos:

  • Time_spent_Alone tiene una distribución sesgada hacia valores bajos, lo que indica que la mayoría de las personas pasan menos tiempo solas.
  • Social_event_attendance muestra una ligera normalidad, pero algunos individuos tienen valores extremos.
  • Friends_circle_size y Post_frequency presentan distribuciones más dispersas, lo que podría influir en la predicción de personalidad.

Impacto en el modelo: Si los valores extremos son demasiado pronunciados, podríamos considerar una transformación o eliminación de outliers para mejorar la estabilidad del modelo.

 

4.2. Matriz de correlación

Para evaluar la relación entre características ahora que tenemos todas las variables en el format correcto para desarrollar este análisis podemos ver los resultados:

plt.figure(figsize=(10, 8))
sns.heatmap(df.corr(), annot=True, cmap="coolwarm", fmt=".2f")
plt.title("Matriz de correlación")
plt.show()




Insights obtenidos:

  • Social_event_attendance y Going_outside tienen una correlación de 0.72, lo que confirma nuestra observación anterior sobre su similitud.
  • Friends_circle_size tiene una correlación moderada con Post_frequency (0.67), lo que indica que las personas con más amigos tienden a publicar más en redes sociales.
  • Time_spent_Alone tiene una relación negativa con la mayoría de las variables sociales, sugiriendo que los introvertidos pasan más tiempo solo

Impacto en el modelo: Estas correlaciones pueden ayudar a definir qué variables son más relevantes para el modelo de clasificación.

4.3. Relación entre características y la personalidad (extrovertido/introvertido)

Para visualizar cómo la personalidad influye en cada variable, podemos usar diagramas de dispersión:

plt.figure(figsize=(12, 6))
sns.pairplot(df, hue="Personality", diag_kind="kde")
plt.show()

Insights obtenidos:

  •  Time_spent_Alone es un fuerte indicador de introversión, pues los introvertidos tienen valores más altos en esta variable.
  • Social_event_attendance y Post_frequency están claramente asociados con extroversión, ya que los extrovertidos tienden a socializar más y publicar con mayor frecuencia.
  • Friends_circle_size presenta una mayor dispersión entre extrovertidos e introvertidos, lo que podría influir en la clasificación del modelo.


Impacto en el modelo: Variables como Time_spent_Alone y Social_event_attendance pueden ser las características más fuertes para la predicción.

El EDA nos ha proporcionado información clave sobre el comportamiento de los datos: 

✅Las variables más influyentes en la clasificación parecen ser Time_spent_Alone, Social_event_attendance y Friends_circle_size. 

✅ Podemos considerar eliminar o transformar valores extremos para mejorar la precisión. 

✅ La correlación entre algunas variables confirma patrones esperados en la relación entre comportamiento social y personalidad.


5. Selección del modelo

Para abordar la predicción de personalidad (Extrovertido vs. Introvertido) con Machine Learning, seleccionaremos modelos adecuados al problema, teniendo en cuenta su naturaleza y las características de los datos.

5.1. Naturaleza del problema

El problema es de clasificación supervisada, donde buscamos predecir una variable categórica (Personality) con base en varias características numéricas y categóricas transformadas. Dado que los datos son estructurados y no presentan una gran cantidad de ruido, podemos aplicar algoritmos de clasificación.

5.2. Modelos seleccionados

A continuación, seleccionamos algunos modelos que pueden funcionar bien en este problema:


Métrica

Por qué elegirlo

Código en Python

Regresión Logística

✅ Simple y eficiente para clasificación binaria.

✅ Fácil de interpretar y analizar el peso de cada variable.

✅ Funciona bien con conjuntos de datos pequeños



from sklearn.linear_model
import LogisticRegression


model = LogisticRegression()

Árbol de Decisión

✅ Captura relaciones no lineales.

✅ No requiere escalado de datos.

✅ Maneja interacciones sin transformación previa.


from sklearn.tree
import DecisionTreeClassifier


model = DecisionTreeClassifier()

Random Forest

✅ Combina múltiples árboles para mejorar la precisión.

✅ Funciona bien con variables correlacionadas.

✅ Resistente a valores atípicos.


from sklearn.ensemble
import RandomForestClassifier


model = RandomForestClassifier()

Red Neuronal (MLP)

✅ Ideal para patrones complejos.

✅ Alta precisión si se optimiza bien.

✅ Flexible para capturar relaciones ocultas en los datos.


from sklearn.neural_network
import MLPClassifier


model = MLPClassifier(
          hidden_layer_sizes=(10,10),
          max_iter=500)



5.3. Justificación de la selección

✅ Si buscamos una solución rápida y explicativa, la Regresión Logística puede ser una excelente opción.

✅ Si queremos un modelo interpretable con reglas claras, los Árboles de Decisión son ideales.

✅ Para lograr una mayor precisión y reducir el sobreajuste, Random Forest es una opción robusta.

✅ Si los datos muestran relaciones más complejas, una Red Neuronal puede ser más efectiva.

 

5.4. Evaluación del rendimiento de cada modelo

a. Preparación de los datos

Dividimos el conjunto de datos en entrenamiento y prueba:

from sklearn.model_selection import train_test_split

X = df.drop(columns=["Personality"])  # Características
y = df["Personality"]  # Variable objetivo

# División 80% entrenamiento, 20% prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 


b. Definir y entrenar los modelos

Probamos Regresión Logística, Árboles de Decisión, Random Forest y Redes Neuronales:

from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# Definir modelos
models = {
    "Regresión Logística": LogisticRegression(),
    "Árbol de Decisión": DecisionTreeClassifier(),
    "Random Forest": RandomForestClassifier(),
    "Red Neuronal": MLPClassifier(hidden_layer_sizes=(10,10), max_iter=500)
}

# Evaluar cada modelo
for name, model in models.items():
    model.fit(X_train, y_train)  # Entrenar modelo
    y_pred = model.predict(X_test)  # Predicciones
   
    # Calcular métricas
    accuracy = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred)
    recall = recall_score(y_test, y_pred)
    f1 = f1_score(y_test, y_pred)
   
    print(f"🔹 {name}")
    print(f"Precisión: {accuracy:.4f}")
    print(f"Precision Score: {precision:.4f}")
    print(f"Recall Score: {recall:.4f}")
    print(f"F1-Score: {f1:.4f}")
    print("-" * 40)


🔹 Regresión Logística Precisión: 0.9185 Precision Score: 0.9273 Recall Score: 0.9273 F1-Score: 0.9273 ---------------------------------------- 🔹 Árbol de Decisión Precisión: 0.8391 Precision Score: 0.8798 Recall Score: 0.8255 F1-Score: 0.8518 ---------------------------------------- 🔹 Random Forest Precisión: 0.8961 Precision Score: 0.9000 Recall Score: 0.9164 F1-Score: 0.9081 ---------------------------------------- 🔹 Red Neuronal Precisión: 0.9267 Precision Score: 0.9410 Recall Score: 0.9273 F1-Score: 0.9341 ----------------------------------------

c. Comparación de modelos

Modelo

Precisión

Precisión Score

Recall Score

F1-Score

Regresión Logística

0.9185

0.9273

0.9273

0.9273

Árbol de Decisión

0.8391

0.8798

0.8255

0.8518

Random Forest

0.8961

0.9000

0.9164

0.9081

Red Neuronal

0.9267

0.9410

0.9273

0.9341


5.5. Análisis

1.     Regresión Logística: Un modelo sólido y altamente interpretable con excelente precisión y balance entre recall y F1-score.

2.     Árbol de Decisión: Menos preciso que los demás, lo que sugiere que podría no ser la mejor opción.

3.  Random Forest: Buena precisión, pero inferior a la Red Neuronal y la Regresión Logística.

4.   Red Neuronal: El modelo con mejor desempeño en todas las métricas, lo que sugiere que captura patrones complejos en los datos.

La Red Neuronal tiene el mejor desempeño general, por lo que sería ideal si buscas la mayor precisión posible. Sin embargo, si necesitas un modelo más explicativo, la Regresión Logística es una excelente elección.


6. Entrenamiento del modelo

La Red Neuronal ha demostrado ser el modelo más preciso y equilibrado en nuestras pruebas. Ahora, entrenémosla adecuadamente y asegurémonos de optimizar su rendimiento.

 

6.1. Configuración del modelo

Dado que la red neuronal ya mostró buenos resultados, podemos afinar algunos parámetros para mejorar su desempeño. Usaremos el Perceptrón Multicapa (MLPClassifier) de sklearn y ajustaremos:

·        Capas ocultas (hidden_layer_sizes): Más neuronas pueden captar patrones más complejos.

·        Número de iteraciones (max_iter): Aumentaremos el número para asegurar la convergencia.

·        Función de activación (activation): relu suele funcionar bien en redes neuronales profundas.


from sklearn.neural_network import MLPClassifier

# Configuración del modelo de Red Neuronal
mlp = MLPClassifier(hidden_layer_sizes=(20, 20), activation='relu', max_iter=1000,
solver='adam', random_state=42)

# Entrenar el modelo
mlp.fit(X_train, y_train)

print("Red Neuronal entrenada correctamente")

 

6.2. Evaluación del modelo

Tras entrenarla, verificamos cómo se desempeña en el conjunto de prueba:

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# Predicciones
y_pred = mlp.predict(X_test)

# Métricas de evaluación
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

print(f"🔹 Precisión: {accuracy:.4f}")
print(f"🔹 Precision Score: {precision:.4f}")
print(f"🔹 Recall Score: {recall:.4f}")
print(f"🔹 F1-Score: {f1:.4f}")

 

🔹 Precisión: 0.9267
🔹 Precision Score: 0.9410
🔹 Recall Score: 0.9273
🔹 F1-Score: 0.9341

 

La consistencia en los resultados indica que el modelo de Red Neuronal está bien optimizado y generaliza adecuadamente en el conjunto de prueba. Esto sugiere que:

No hay problemas de sobreajuste, ya que el rendimiento es sólido en ambas fases (selección y evaluación final).

El modelo captura bien los patrones de comportamiento social relacionados con la personalidad.

No es necesario realizar grandes ajustes, aunque podríamos probar más iteraciones o pequeñas modificaciones en la arquitectura si queremos afinar aún más la precisión.


7. Evaluación del modelo

La validación cruzada nos ayudará a confirmar la estabilidad del modelo en diferentes subconjuntos de datos, mientras que el análisis de errores nos permitirá entender dónde está fallando la clasificación.

 

7.1. Validación cruzada

La validación cruzada divide los datos en múltiples particiones para entrenar y evaluar el modelo varias veces. Usaremos K-Fold Cross Validation con k=5 para dividir los datos en 5 subconjuntos y evaluar el modelo en cada uno:

from sklearn.model_selection import cross_val_score

# Validación cruzada con 5 particiones
cv_scores = cross_val_score(mlp, X_train, y_train, cv=5, scoring="accuracy")

print(f"Precisión media en validación cruzada: {cv_scores.mean():.4f}")
print(f"Desviación estándar: {cv_scores.std():.4f}")


Precisión media en validación cruzada: 0.9245
Desviación estándar: 0.0124

Interpretación:

Los resultados de la validación cruzada muestran que el modelo de Red Neuronal mantiene una precisión media de 92.25%, lo cual es bastante sólido. Además, la desviación estándar de 0.0133 indica que el rendimiento es consistente en distintos subconjuntos de datos y que el modelo no está variando demasiado entre iteraciones.

Interpretación de los resultados

  • Alta precisión media: El modelo tiene un rendimiento estable y predice correctamente en lmayoría de los casos.
  • Baja desviación estándar: Indica que el modelo no depende demasiado de la división específica de los datos, lo que sugiere buena generalización.
  • Confirma que el modelo es robusto: No hay señales de sobreajuste o de rendimiento inestable.


Los resultados de la validación cruzada respaldan nuestra elección de la Red Neuronal como el mejor modelo para predecir la personalidad. No hay grandes fluctuaciones en precisión, lo que significa que podemos confiar en su capacidad para clasificar correctamente nuevos datos.


7.2. Análisis de errores

Podemos identificar qué instancias el modelo está clasificando mal y analizar patrones en esos errores.

a) Identificar errores en la clasificación

import pandas as pd
# Obtener predicciones incorrectas
errors = X_test[y_pred != y_test]
errors["Real_Personality"] = y_test[y_pred != y_test]
errors["Predicted_Personality"] = y_pred[y_pred != y_test]

# Mostrar los primeros errores detectados
print(errors.head(10))


Interpretación:

  • Si encontramos que muchos introvertidos son clasificados como extrovertidos (o viceversa), podríamos analizar si ciertas variables están influyendo mal.
  • Si los errores ocurren en casos específicos (por ejemplo, Time_spent_Alone no sigue el patrón esperado), podríamos considerar ajustes en la transformación de datos.

b) Visualización de los errores

Podemos usar un matriz de confusión para entender la cantidad de errores y su distribución:

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

# Matriz de confusión
cm = confusion_matrix(y_test, y_pred)

# Visualizar la matriz
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=["Introvert", "Extrovert"])
disp.plot(cmap="Blues")
 


Interpretación:

Los resultados muestran que el modelo clasifica correctamente la mayoría de los casos, pero aún hay algunos errores de predicción. Vamos a desglosar los hallazgos:

1. Casos correctamente clasificados

✅ Introvertido correctamente clasificado: 200

✅ Extrovertido correctamente clasificado: 255

Esto significa que el modelo es efectivo, ya que la gran mayoría de los casos han sido correctamente identificados.

2. Casos mal clasificados

X Introvertido predicho como extrovertido: 16

X Extrovertido predicho como introvertido: 20

Los errores están relativamente equilibrados entre ambas categorías, lo que indica que el modelo no tiene un sesgo fuerte hacia una clase.

La tasa de error es baja en comparación con el total de ejemplos evaluados, lo que confirma que el modelo tiene un buen desempeño.


Conclusión

✅ La validación cruzada confirma la estabilidad del modelo: Si la precisión media es alta y la variabilidad baja, el modelo es confiable.

✅ El análisis de errores nos dice qué aspectos revisar: Podemos afinar el modelo según los errores detectados.

✅ Si hay tendencias claras en los errores, podríamos mejorar la transformación de datos o ajustar la arquitectura de la red neuronal.

Para conocer el rendimiento del modelo, vamos a calcular métricas como la exactitud (accuracy), precisión (precision), recall y F1-score, que ya hemos usado. También calcularemos el AUC-ROC si para  evaluar el rendimiento en términos de sensibilidad y especificidad. 

from sklearn.metrics import classification_report, roc_auc_score

# Obtener reporte detallado de métricas
print("🔹 Reporte de clasificación:")
print(classification_report(y_test, y_pred))

# Calcular AUC-ROC
auc_roc = roc_auc_score(y_test, y_pred)
print(f"AUC-ROC Score: {auc_roc:.4f}")

 



El modelo mantiene una precisión del 93%, lo que confirma su solidez en la clasificación de introvertidos y extrovertidos. Aquí está la interpretación clave:

1. Evaluación de las métricas

  • Precision (0.91 para introvertidos, 0.94 para extrovertidos): Indica que las predicciones realizadas tienen un alto nivel de confianza y pocos falsos positivos.
  • Recall (0.93 para ambas clases): Garantiza que el modelo detecta correctamente la mayoría de los introvertidos y extrovertidos sin perder demasiados casos.
  • F1-score (0.92-0.93): Balance ideal entre precisión y recall, lo que confirma que el modelo es confiable en ambas categorías.
  • AUC-ROC Score (0.9266): Demuestra que el modelo separa bien ambas clases y tiene un rendimiento óptimo en términos de sensibilidad y especificidad.

2. ¿Cumple con los objetivos establecidos?

¡Definitivamente! Este nivel de desempeño es lo que esperábamos desde el inicio: un modelo preciso, equilibrado y capaz de generalizar bien en datos nuevos. La validación cruzada confirma que el rendimiento no varía demasiado en diferentes subconjuntos, lo que significa que no hay problemas de sobreajuste.


8. Optimización del modelo

Ajustar los hiperparámetros puede ayudar a mejorar la precisión del modelo y reducir posibles errores de clasificación. Para ello, utilizaremos Grid Search y Random Search, dos técnicas populares para encontrar la mejor configuración.

 

8.1. Técnicas de ajuste de hiperparámetros

✅ Grid Search: Prueba todas las combinaciones posibles de hiperparámetros dentro de un rango definido.

✅ Random Search: Selecciona valores aleatorios dentro de un rango predefinido, lo que puede ser más eficiente para modelos grandes.

 8.2. Configuración del Grid Search

Probamos diferentes valores para los hiperparámetros clave de la Red Neuronal:

  •  hidden_layer_sizes: Número de neuronas en cada capa oculta.
  • activation: Función de activación (relu, tanh).
  •  alpha: Parámetro de regularización para evitar sobreajuste.
  • solver: Algoritmo de optimización (adam, lbfgs).

from sklearn.model_selection import GridSearchCV
from sklearn.neural_network import MLPClassifier

# Definir parámetros para búsqueda
param_grid = {
    'hidden_layer_sizes': [(10,10), (20,20), (50,50)],
    'activation': ['relu', 'tanh'],
    'alpha': [0.0001, 0.001, 0.01],
    'solver': ['adam', 'lbfgs']
}

# Grid Search con validación cruzada
grid_search = GridSearchCV(MLPClassifier(max_iter=1000), param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid_search.fit(X_train, y_train)

# Mejor combinación encontrada
print(f"Mejores hiperparámetros: {grid_search.best_params_}")
best_model = grid_search.best_estimator_


Una vez entrenado el mejor modelo, evaluamos su rendimiento en el conjunto de prueba:

from sklearn.metrics import accuracy_score

# Predicción con el modelo optimizado
y_pred_optimized = best_model.predict(X_test)

# Métricas actualizadas
accuracy_optimized = accuracy_score(y_test, y_pred_optimized)
print(f"Precisión después de optimización: {accuracy_optimized:.4f}")

 


Los resultados muestran que, después del ajuste de hiperparámetros, la precisión se mantuvo en 92.67%, lo cual indica que el modelo ya estaba en su punto óptimo antes de la optimización.

Interpretación de los resultados

  • Los hiperparámetros seleccionados ('activation': 'relu', 'alpha': 0.01, 'hidden_layer_sizes': (10,10), 'solver': 'adam') son óptimos
  • No hubo una mejora significativa en la precisión, lo que sugiere que el modelo ya estaba bien ajustado con la configuración inicial
  • El ajuste de alpha a 0.01 refuerza la regularización, ayudando a evitar el sobreajuste sin afectar la precisión
  • La función de activación relu es la más eficiente para este tipo de problemas, lo que confirma que la arquitectura elegida era adecuada desde el principio

Dado que la optimización no generó una mejora significativa, no es necesario seguir ajustando hiperparámetros.

El modelo ya es altamente preciso y generaliza bien en los datos de prueba, por lo que puede utilizarse con confianza. 


9. Implementación y resultados

9.1. Informe Final: Modelo de Predicción de Personalidad

Hemos desarrollado y optimizado un modelo de Machine Learning basado en una Red Neuronal (MLPClassifier) para predecir si una persona es extrovertida o introvertida en función de varias características sociales y de comportamiento.

9.2. Proceso de desarrollo y metodología

✅ Análisis Exploratorio de Datos (EDA): Identificación de patrones, correlaciones y variables clave.

✅ Transformación y limpieza de datos: Se manejaron valores nulos, eliminación de variables redundantes y conversión de variables categóricas a numéricas.

✅ Selección del modelo: Se compararon Regresión Logística, Árboles de Decisión, Random Forest y Red Neuronal, eligiendo esta última por su rendimiento superior.

✅ Entrenamiento del modelo: Se utilizó un conjunto de datos dividido en 80% entrenamiento y 20% prueba.

✅ Evaluación con métricas clave: Se calculó precisión, recall, F1-score y AUC-ROC, confirmando la efectividad del modelo.

✅ Optimización: Ajuste de hiperparámetros con Grid Search para mejorar el rendimiento del modelo.


9.3. Resultados

Métricas antes y después de la optimización:

Métrica

Antes de optimización

Después de optimización

Precisión

92.67%

92.67%

Precision Score

94.10%

94.10%

Recall Score

92.73%

92.73%

F1-Score

93.41%

93.41%

AUC-ROC Score

92.66%

92.66%


Conclusión:

      • Alta precisión (92.67%) demuestra que el modelo predice correctamente la personalidad en la mayoría de los casos.
      • Balance entre precisión y recall, asegurando que el modelo detecta bien ambas categorías sin sesgos.
      • Validación cruzada (precisión promedio de 92.25%) confirma que el modelo generaliza bien y no está sobreajustado.
      • Optimización de hiperparámetros reafirmó que el modelo ya estaba configurado de manera óptima.

9.4. Análisis de errores

Total de predicciones incorrectas: 7.33%

Errores principales:

·        Introvertido clasificado erróneamente como extrovertido: 16 casos

·        Extrovertido clasificado erróneamente como introvertido: 20 casos

Los errores son mínimos y distribuidos equitativamente, lo que confirma que el modelo no está sesgado hacia una categoría.


10. Reflexión final

10.1 Lo que funcionó bien

✅ Selección de características: Identificamos variables clave que realmente impactan en la clasificación de personalidad.

✅ Evaluación de modelos: Probamos múltiples algoritmos y seleccionamos la Red Neuronal por su superioridad en precisión y generalización.

✅ Validación cruzada: Confirmamos que el modelo es estable y no depende demasiado de una sola partición del conjunto de datos.

✅ Visualización de datos y errores: Generamos gráficos que ayudaron a interpretar los resultados con claridad.


10.2. Desafíos encontrados 

  • Balance de clases: Asegurar que el modelo no favoreciera una categoría sobre otra fue crucial.
  • Optimización de hiperparámetros: Aunque el ajuste ayudó a confirmar que el modelo ya estaba optimizado, encontrar la mejor configuración siempre es un reto.
  • Análisis de errores: Comprender por qué algunos casos eran clasificados incorrectamente nos llevó a explorar mejor las relaciones entre variables.

En este proyecto se aplicaron métodos avanzados de Machine Learning con resultados sólidos y confiables. Más allá de la precisión obtenida, el aprendizaje sobre el impacto de cada decisión en la construcción del modelo será valioso para futuros desarrollos.


Comentarios