Este script implementa un predictor de satisfacción que utiliza un modelo KNN (K-Nearest Neighbors) pre-entrenado para evaluar qué tan satisfecho estaría un usuario con diferentes ciudades basándose en sus preferencias personales.
El script Predict-satisfaction.py permite:
- Cargar un modelo KNN pre-entrenado desde un archivo
.pkl - Evaluar la compatibilidad entre las preferencias de un usuario y todas las ciudades en la base de datos
- Calcular probabilidades de satisfacción (0-100%) para cada ciudad
- Generar veredictos cualitativos que facilitan la interpretación de los resultados
- Mostrar las top 5 ciudades con mejor compatibilidad
Mientras que KNN-recomendation.py se enfoca en recomendar las ciudades más similares (top N), Predict-satisfaction.py se enfoca en predecir la satisfacción del usuario con todas las ciudades, proporcionando:
- Probabilidades de satisfacción en porcentaje (0-100%)
- Veredictos cualitativos (Match Perfecto, Muy Alta, Alta, Media, Baja)
- Evaluación completa de todas las ciudades (no solo las top N)
El script requiere un modelo pre-entrenado generado por KNN-recomendation.py usando el comando train. Este modelo contiene:
- El modelo KNN entrenado
- El scaler (normalizador) entrenado
- La base de datos completa de ciudades
La clase SatisfactionPredictor encapsula toda la lógica del sistema de predicción de satisfacción.
-
Modelo KNN (
self.model)- Modelo KNN pre-entrenado cargado desde el archivo
.pkl - Configurado con métrica coseno y algoritmo brute force
- Utilizado para calcular distancias entre el perfil del usuario y todas las ciudades
- Modelo KNN pre-entrenado cargado desde el archivo
-
Scaler (
self.scaler)- MinMaxScaler pre-entrenado cargado desde el archivo
.pkl - Normaliza las características del usuario usando los mismos parámetros del entrenamiento
- Es crítico usar el mismo scaler para mantener la consistencia
- MinMaxScaler pre-entrenado cargado desde el archivo
-
Base de Datos (
self.cities_df)- DataFrame de pandas con toda la información de las ciudades
- Incluye nombres de ciudades y todas sus características
- Se utiliza para generar resultados legibles con información completa
Cargar modelo → Normalizar preferencias usuario → Calcular distancias con todas las ciudades →
Convertir distancias a probabilidades → Generar veredictos cualitativos → Mostrar top 5
Inicializa el predictor cargando el modelo pre-entrenado desde disco.
Proceso:
- Valida que el archivo
.pklexista - Carga el diccionario con
joblib.load() - Extrae y asigna el modelo KNN, el scaler y la base de datos
Parámetros:
model_path: Ruta al archivo.pkldel modelo pre-entrenado
Excepciones:
FileNotFoundError: Si el archivo del modelo no existe
Calcula la similitud entre las preferencias del usuario y todas las ciudades, traduciéndola a probabilidad de satisfacción.
Proceso:
- Convierte las características del usuario a un vector numpy
- Normaliza el vector usando el scaler pre-entrenado (sin re-entrenar)
- Calcula distancias con todas las ciudades en la base de datos
- Convierte distancias (0 a ~1.41) en similitud (0 a 1) usando
1 - distancia - Convierte similitud a probabilidad de satisfacción en porcentaje (0-100%)
- Recorta valores negativos si hubiera ruido numérico
Parámetros:
person_features: Lista o array de 10 valores numéricos representando las preferencias del usuario (0-10)
Retorna:
- DataFrame con todas las ciudades ordenadas por probabilidad de satisfacción descendente
- Incluye todas las columnas originales de la base de datos
- Añade la columna
satisfaction_probcon el porcentaje de satisfacción (0-100%)
Nota: En producción real, se podría usar n_neighbors=5 o 10 para eficiencia, pero el script actual evalúa todas las ciudades para proporcionar un panorama completo.
Traduce el porcentaje numérico de satisfacción a un veredicto cualitativo en lenguaje natural.
Parámetros:
prob: Porcentaje de satisfacción (0-100)
Retorna:
- String con el veredicto cualitativo según rangos:
prob >= 95: "⭐⭐⭐⭐⭐ Match Perfecto (Te encantará)"prob >= 85: "⭐⭐⭐⭐ Muy Alta (Apuesta segura)"prob >= 70: "⭐⭐⭐ Alta (Buena opción)"prob >= 50: "⭐⭐ Media (Tiene pros y contras)"prob < 50: "⚠️ Baja (No recomendado)"
El script requiere un modelo pre-entrenado generado por KNN-recomendation.py.
Requisitos:
- El archivo debe existir en la ruta especificada
- Debe contener un diccionario con las claves:
'knn_model': Modelo NearestNeighbors entrenado'scaler': MinMaxScaler entrenado'database': DataFrame de pandas con las ciudades
Generación del modelo:
python KNN-recomendation.py train --data ciudades.csv --out city_model.pklEl script requiere exactamente 10 características numéricas que representan las preferencias del usuario.
Formato:
- 10 valores numéricos (float) separados por espacios
- Cada valor representa una preferencia en una escala de 0 a 10
- El orden debe coincidir con el orden de las características en el CSV usado para entrenar
Interpretación de valores (recomendada):
- 0-2: Muy baja importancia / No es relevante
- 3-4: Baja importancia / Poco relevante
- 5-6: Importancia media / Moderadamente importante
- 7-8: Alta importancia / Muy importante
- 9-10: Máxima importancia / Crítico o esencial
Ejemplo de características:
8.5 7.2 9.0 6.5 8.0 7.8 9.2 6.0 8.5 7.5
Estas características deben corresponder exactamente con las columnas numéricas del CSV usado para entrenar el modelo (excluyendo la primera columna que es el nombre de la ciudad).
El script carga el archivo .pkl y extrae los tres componentes necesarios:
- Modelo KNN entrenado
- Scaler con parámetros de normalización
- Base de datos completa de ciudades
Las preferencias del usuario se normalizan usando el mismo scaler que se usó durante el entrenamiento:
person_vector = np.array([person_features])
person_scaled = self.scaler.transform(person_vector)Importante: Se usa transform() y no fit_transform() para mantener la consistencia con los datos de entrenamiento.
El modelo KNN calcula las distancias coseno entre el perfil normalizado del usuario y todas las ciudades:
distances, indices = self.model.kneighbors(person_scaled, n_neighbors=len(self.cities_df))Esto proporciona:
distances: Array con las distancias coseno (0 = idéntico, valores mayores = más diferentes)indices: Array con los índices de las ciudades ordenadas por similitud
La distancia se convierte en similitud y luego en probabilidad de satisfacción:
similarity = 1 - distances[0] # Convierte distancia a similitud (0-1)
satisfaction_prob = (similarity * 100).round(2).clip(min=0) # Convierte a porcentaje (0-100%)Fórmula:
- Similitud = 1 - Distancia coseno
- Probabilidad de satisfacción (%) = Similitud × 100
Cada probabilidad se traduce a un veredicto cualitativo usando el método analyze_match() para facilitar la interpretación.
El método predict() retorna un DataFrame con:
- Todas las ciudades de la base de datos
- Todas las columnas originales del CSV
- Columna adicional
satisfaction_prob: Porcentaje de satisfacción (0-100%) - Ordenadas por probabilidad descendente (mejores matches primero)
El script muestra en consola las top 5 ciudades con mejor compatibilidad, incluyendo:
- Nombre de la ciudad (primera columna del DataFrame)
- Probabilidad de satisfacción (
satisfaction_prob): Porcentaje de 0 a 100% - Veredicto cualitativo: Descripción en lenguaje natural
Formato de salida:
PREDICCIÓN DE SATISFACCIÓN:
Ciudad satisfaction_prob veredicto
Barcelona 95.23 ⭐⭐⭐⭐⭐ Match Perfecto (Te encantará)
Madrid 88.45 ⭐⭐⭐⭐ Muy Alta (Apuesta segura)
Valencia 75.67 ⭐⭐⭐ Alta (Buena opción)
Sevilla 68.23 ⭐⭐⭐ Alta (Buena opción)
Bilbao 62.45 ⭐⭐ Media (Tiene pros y contras)
- satisfaction_prob >= 95%: Match perfecto, la ciudad se alinea casi perfectamente con las preferencias
- satisfaction_prob >= 85%: Muy alta compatibilidad, apuesta segura
- satisfaction_prob >= 70%: Alta compatibilidad, buena opción a considerar
- satisfaction_prob >= 50%: Compatibilidad media, tiene pros y contras
- satisfaction_prob < 50%: Baja compatibilidad, no recomendado según las preferencias
python Predict-satisfaction.py [--model <archivo_modelo>] <característica1> <característica2> ... <característica10>- Tipo: String
- Descripción: Ruta al archivo del modelo pre-entrenado (
.pkl) - Valor por defecto:
city_model.pkl - Ejemplo:
--model mi_modelo.pkl
- Tipo: 10 valores float
- Descripción: Las 10 características/preferencias del usuario (valores 0-10)
- Cantidad: Exactamente 10 valores separados por espacios
- Ejemplo:
8.5 7.2 9.0 6.5 8.0 7.8 9.2 6.0 8.5 7.5
python Predict-satisfaction.py 8.5 7.2 9.0 6.5 8.0 7.8 9.2 6.0 8.5 7.5Este comando:
- Usa el modelo
city_model.pkl(por defecto) - Evalúa las preferencias del usuario proporcionadas
python Predict-satisfaction.py --model modelos/ciudades_europa.pkl 9.0 8.5 7.5 8.0 6.5 7.8 8.2 7.0 8.5 9.2Este comando:
- Usa el modelo especificado en
modelos/ciudades_europa.pkl - Evalúa las preferencias del usuario proporcionadas
python Predict-satisfaction.py --model city_model.pkl 7.0 9.0 8.5 8.0 4.0 9.5 6.0 7.5 9.0 8.0Características:
- Seguridad: 7.0
- Transporte: 9.0
- Cultura: 8.5
- Gastronomía: 8.0
- Naturaleza: 4.0
- Entretenimiento: 9.5
- Educación: 6.0
- Salud: 7.5
- Economía: 9.0
- Calidad de Vida: 8.0
argparse: Manejo de argumentos de línea de comandossys: Funciones del sistemaos: Operaciones del sistema de archivos
Instalar con pip:
pip install pandas numpy scikit-learn joblibDependencias:
- pandas: Manipulación y análisis de datos (DataFrames)
- numpy: Operaciones numéricas y arrays
- scikit-learn: Algoritmos de machine learning (el modelo KNN usa esta librería)
- joblib: Serialización eficiente de objetos Python (carga del modelo
.pkl)
- Python 3.7 o superior
- pandas >= 1.0.0
- numpy >= 1.18.0
- scikit-learn >= 0.22.0
- joblib >= 0.14.0
Primero, es necesario entrenar el modelo usando KNN-recomendation.py:
Archivo ciudades.csv:
Ciudad,Seguridad,Transporte,Cultura,Gastronomia,Naturaleza,Entretenimiento,Educacion,Salud,Economia,CalidadVida
Barcelona,8.5,9.0,9.5,9.2,7.0,8.8,8.5,8.0,7.5,8.7
Madrid,8.0,9.2,9.0,8.8,6.5,9.0,9.2,8.5,8.0,8.5
Valencia,7.5,7.8,7.5,8.5,8.0,7.5,7.8,8.2,7.0,7.8
Sevilla,7.0,7.5,8.5,9.0,7.5,8.0,7.5,7.8,6.5,7.5
Bilbao,8.0,7.2,8.0,8.2,8.5,7.2,8.0,8.5,7.8,8.0Entrenar el modelo:
python KNN-recomendation.py train --data ciudades.csv --out city_model.pklSalida esperada:
Modelo entrenado exitosamente con 5 ciudades.
Modelo guardado en: city_model.pkl
Supongamos que un usuario tiene las siguientes preferencias:
- Seguridad: 8.5 (muy importante)
- Transporte: 9.0 (esencial)
- Cultura: 9.5 (muy importante)
- Gastronomía: 9.2 (muy importante)
- Naturaleza: 7.0 (importante)
- Entretenimiento: 8.8 (muy importante)
- Educación: 8.5 (muy importante)
- Salud: 8.0 (importante)
- Economía: 7.5 (importante)
- Calidad de Vida: 8.7 (muy importante)
Ejecutar predicción:
python Predict-satisfaction.py --model city_model.pkl 8.5 9.0 9.5 9.2 7.0 8.8 8.5 8.0 7.5 8.7Salida esperada:
--- Analizando compatibilidad para perfil: [8.5, 9.0, 9.5, 9.2, 7.0, 8.8, 8.5, 8.0, 7.5, 8.7] ---
PREDICCIÓN DE SATISFACCIÓN:
Ciudad satisfaction_prob veredicto
Barcelona 98.45 ⭐⭐⭐⭐⭐ Match Perfecto (Te encantará)
Madrid 94.23 ⭐⭐⭐⭐⭐ Match Perfecto (Te encantará)
Valencia 87.67 ⭐⭐⭐⭐ Muy Alta (Apuesta segura)
Sevilla 82.34 ⭐⭐⭐⭐ Muy Alta (Apuesta segura)
Bilbao 78.56 ⭐⭐⭐ Alta (Buena opción)
-
Barcelona (98.45%): Match casi perfecto. Las características de Barcelona se alinean casi perfectamente con las preferencias del usuario. Es la mejor opción.
-
Madrid (94.23%): También un match excelente. Ofrece características muy similares a las preferencias del usuario.
-
Valencia (87.67%): Muy alta compatibilidad. Es una apuesta segura aunque ligeramente menos alineada que las dos anteriores.
-
Sevilla (82.34%): Muy alta compatibilidad. Buena opción a considerar.
-
Bilbao (78.56%): Alta compatibilidad. Es una buena opción pero con algunas diferencias respecto a las preferencias.
-
Orden de características: Las características deben proporcionarse en el mismo orden que aparecen en el CSV usado para entrenar (después de la columna de nombre de ciudad).
-
Modelo pre-entrenado requerido: El script requiere un modelo pre-entrenado. Si el modelo no existe, el script lanzará un error indicando que debe entrenarse primero.
-
Normalización automática: No es necesario normalizar manualmente los valores de entrada; el script usa el scaler entrenado para normalizarlos automáticamente.
-
Evaluación completa: El script evalúa todas las ciudades en la base de datos, no solo las top N, proporcionando un panorama completo de compatibilidad.
-
Consistencia del modelo: El modelo debe haber sido entrenado con el mismo formato de datos que se usará para las predicciones. Cambios en el CSV requieren reentrenar el modelo.
-
Compatibilidad de versiones: El modelo guardado es específico de la versión de scikit-learn usada. Modelos guardados con versiones diferentes pueden no ser compatibles.
FileNotFoundError: Modelo no encontrado: city_model.pkl. Entrena primero.
Solución: Entrenar el modelo primero usando KNN-recomendation.py train.
error: the following arguments are required: features
Solución: Proporcionar exactamente 10 valores numéricos como características.
ValueError: could not convert string to float: 'abc'
Solución: Asegurarse de que todos los valores sean numéricos (float o int).
El script realiza las siguientes validaciones:
- Verifica que el archivo del modelo exista antes de cargarlo
- Valida que se proporcionen exactamente 10 características
- Maneja errores de carga del modelo y muestra mensajes descriptivos
El script actual evalúa todas las ciudades en la base de datos para proporcionar un panorama completo. Esto es útil para análisis exhaustivos pero puede ser lento con bases de datos muy grandes.
Para bases de datos grandes:
- En producción, se podría modificar el código para usar
n_neighbors=10o20en lugar delen(self.cities_df) - Esto limitaría el cálculo a las ciudades más relevantes, mejorando el rendimiento