Este script implementa un sistema de recomendación de ciudades basado en el algoritmo K-Nearest Neighbors (KNN). El sistema utiliza la métrica de distancia coseno para encontrar las ciudades más similares a las preferencias de un usuario, representadas mediante un vector de características numéricas.
El recomendador permite:
- Entrenar un modelo con una base de datos de ciudades y sus características
- Guardar el modelo entrenado para uso posterior
- Generar recomendaciones personalizadas basadas en las preferencias del usuario
El script utiliza KNN (K-Nearest Neighbors) con:
- Métrica: Distancia coseno (similaridad entre vectores)
- Algoritmo: Búsqueda exhaustiva (brute force)
- Normalización: MinMaxScaler para escalar características al rango [0, 1]
La clase CityRecommender encapsula toda la lógica del sistema de recomendación.
-
Modelo KNN (
self.model)- Instancia de
NearestNeighborsde scikit-learn - Configurado con métrica coseno y algoritmo brute force
- Se entrena con los vectores normalizados de las ciudades
- Instancia de
-
Scaler (
self.scaler)- Instancia de
MinMaxScalerpara normalización de características - Normaliza todas las características al rango [0, 1]
- Es crítico usar el mismo scaler entrenado tanto para entrenamiento como para predicción
- Instancia de
-
Base de Datos (
self.cities_df)- DataFrame de pandas que contiene toda la información de las ciudades
- Incluye nombres de ciudades y todas sus características
- Se guarda junto con el modelo para permitir recuperar información completa
Entrenamiento:
CSV → Leer datos → Extraer características numéricas → Normalizar → Entrenar KNN → Guardar modelo
Predicción:
Cargar modelo → Normalizar características usuario → Buscar vecinos más cercanos → Calcular scores → Retornar recomendaciones
Lee un archivo CSV, extrae las características numéricas, entrena el scaler y el modelo KNN.
Proceso:
- Valida que el archivo CSV exista
- Lee el CSV en un DataFrame
- Filtra solo las columnas numéricas (automáticamente detecta las 10 características)
- Entrena el MinMaxScaler con los datos
- Normaliza los vectores de ciudades
- Entrena el modelo KNN con los vectores normalizados
Parámetros:
csv_path: Ruta al archivo CSV con los datos de ciudades
Guarda el estado completo del recomendador en un archivo .pkl usando joblib.
Contenido guardado:
- Modelo KNN entrenado
- Scaler entrenado (con parámetros de normalización)
- Base de datos completa (DataFrame con todas las ciudades)
Parámetros:
filepath: Ruta donde guardar el archivo .pkl
Carga un modelo pre-entrenado desde disco y restaura todo el estado interno.
Parámetros:
filepath: Ruta al archivo .pkl del modelo
Importante: El modelo debe haber sido guardado previamente con save_model().
Genera recomendaciones basadas en las características proporcionadas por el usuario.
Proceso:
- Convierte las características a un vector numpy
- Normaliza el vector usando el scaler entrenado (sin re-entrenar)
- Busca los
n_recommendationsvecinos más cercanos - Calcula el
match_scorecomo (1 - distancia) para obtener un score de similitud - Retorna un DataFrame con las ciudades recomendadas y sus scores
Parámetros:
person_features: Lista de 10 valores numéricos representando las características del usuarion_recommendations: Número de recomendaciones a retornar (por defecto: 3)
Retorna:
- DataFrame con el nombre de la ciudad (primera columna) y el
match_score(0-1, donde 1 es máxima similitud)
El script se ejecuta desde la línea de comandos y soporta dos subcomandos principales.
Entrena el modelo con un archivo CSV y lo guarda en disco.
Sintaxis:
python KNN-recomendation.py train --data <ruta_csv> [--out <archivo_modelo>]Parámetros:
--data(requerido): Ruta al archivo CSV con los datos de ciudades--out(opcional): Nombre del archivo donde guardar el modelo. Por defecto:city_model.pkl
Ejemplo:
python KNN-recomendation.py train --data ciudades.csv --out mi_modelo.pklSalida esperada:
Modelo entrenado exitosamente con 50 ciudades.
Modelo guardado en: mi_modelo.pkl
Carga un modelo pre-entrenado y genera recomendaciones basadas en características de usuario.
Sintaxis:
python KNN-recomendation.py predict [--model <archivo_modelo>] <característica1> <característica2> ... <característica10>Parámetros:
--model(opcional): Ruta al archivo del modelo entrenado. Por defecto:city_model.pklfeatures(requerido): 10 valores numéricos separados por espacios, representando las características del usuario
Ejemplo:
python KNN-recomendation.py predict --model mi_modelo.pkl 8.5 7.2 9.0 6.5 8.0 7.8 9.2 6.0 8.5 7.5Salida esperada:
--- RESULTADOS ---
Ciudad match_score
Barcelona 0.9234
Madrid 0.9012
Valencia 0.8876
El sistema de recomendación está diseñado para ayudar a una persona que busca una ciudad que se ajuste a sus preferencias y necesidades personales. La persona debe definir qué tan importante es cada una de las 10 características para ella, creando así un perfil personalizado que el algoritmo utilizará para encontrar las ciudades más similares.
La persona que busca recomendaciones debe evaluar sus necesidades en cada una de las 10 características. Estas características representan diferentes aspectos que pueden ser importantes al elegir una ciudad para vivir, visitar o considerar como destino.
Proceso de evaluación:
- La persona reflexiona sobre qué tan importante es cada característica para ella
- Asigna un valor numérico a cada característica según su nivel de importancia o necesidad
- El sistema compara estas preferencias con las características reales de las ciudades en la base de datos
- Se recomiendan las ciudades cuyas características se alinean mejor con las preferencias del usuario
Aunque el script acepta cualquier valor numérico, se recomienda usar una escala de 0 a 10 para facilitar la interpretación:
- 0-2: Muy baja importancia / No es relevante para la persona
- 3-4: Baja importancia / Poco relevante
- 5-6: Importancia media / Moderadamente importante
- 7-8: Alta importancia / Muy importante para la persona
- 9-10: Máxima importancia / Crítico o esencial para la persona
Ejemplo de interpretación:
- Si una persona valora mucho la seguridad y la cultura, asignará valores altos (8-10) a esas características
- Si la naturaleza no es prioritaria, asignará un valor bajo (2-4) a esa característica
- Si el transporte público es moderadamente importante, asignará un valor medio (5-6)
Una persona joven que busca oportunidades profesionales y vida social activa:
- Seguridad: 7.0 (importante pero no crítico)
- Transporte: 9.0 (esencial para movilidad)
- Cultura: 8.5 (muy importante para entretenimiento)
- Gastronomía: 8.0 (disfruta de la vida social)
- Naturaleza: 4.0 (poco relevante)
- Entretenimiento: 9.5 (muy importante)
- Educación: 6.0 (moderadamente importante)
- Salud: 7.5 (importante)
- Economía: 9.0 (crítico para oportunidades laborales)
- Calidad de Vida: 8.0 (importante)
Una familia que prioriza seguridad, educación y servicios:
- Seguridad: 10.0 (máxima prioridad)
- Transporte: 7.0 (importante pero no crítico)
- Cultura: 6.5 (moderadamente importante)
- Gastronomía: 6.0 (moderadamente importante)
- Naturaleza: 7.5 (importante para actividades familiares)
- Entretenimiento: 6.0 (moderadamente importante)
- Educación: 10.0 (crítico para los hijos)
- Salud: 9.5 (muy importante)
- Economía: 8.0 (importante para estabilidad)
- Calidad de Vida: 9.0 (muy importante)
Una persona que busca tranquilidad, salud y calidad de vida:
- Seguridad: 9.0 (muy importante)
- Transporte: 6.0 (moderadamente importante)
- Cultura: 7.0 (importante para actividades)
- Gastronomía: 7.5 (importante)
- Naturaleza: 8.5 (muy importante para tranquilidad)
- Entretenimiento: 5.0 (poco relevante)
- Educación: 3.0 (muy poco relevante)
- Salud: 10.0 (máxima prioridad)
- Economía: 6.5 (moderadamente importante)
- Calidad de Vida: 9.5 (muy importante)
Las 10 características representan diferentes dimensiones que una persona puede considerar al evaluar una ciudad:
-
Características de Infraestructura: Transporte, Salud, Economía
- Relacionadas con servicios y facilidades disponibles
-
Características de Calidad de Vida: Seguridad, Calidad de Vida, Naturaleza
- Relacionadas con bienestar personal y entorno
-
Características Culturales y Sociales: Cultura, Gastronomía, Entretenimiento
- Relacionadas con actividades sociales y opciones de ocio
-
Características de Desarrollo Personal: Educación
- Relacionada con oportunidades de crecimiento y formación
Importante: La persona debe evaluar cada característica de forma independiente según sus propias prioridades. No hay características "mejores" o "peores"; cada persona tiene necesidades y preferencias únicas que el sistema respeta al generar recomendaciones personalizadas.
Las características que la persona define como sus preferencias deben corresponder exactamente con las características que están evaluadas en el CSV de ciudades. Es decir:
- Si el CSV tiene columnas:
Seguridad, Transporte, Cultura, Gastronomía, Naturaleza, Entretenimiento, Educación, Salud, Economía, CalidadVida - La persona debe proporcionar sus preferencias en ese mismo orden:
[Seguridad, Transporte, Cultura, Gastronomía, Naturaleza, Entretenimiento, Educación, Salud, Economía, CalidadVida]
El sistema compara las preferencias de la persona con las características reales de cada ciudad para encontrar las mejores coincidencias.
El archivo CSV debe cumplir con la siguiente estructura:
- Primera columna: Nombre de la ciudad (texto)
- Siguientes columnas: Exactamente 10 características numéricas
Estructura esperada:
Ciudad,Caracteristica1,Caracteristica2,Caracteristica3,Caracteristica4,Caracteristica5,Caracteristica6,Caracteristica7,Caracteristica8,Caracteristica9,Caracteristica10
Barcelona,8.5,7.2,9.0,6.5,8.0,7.8,9.2,6.0,8.5,7.5
Madrid,7.8,8.0,8.5,7.2,7.5,8.2,8.0,7.8,7.0,8.5
Valencia,7.0,6.5,7.8,8.0,6.8,7.5,7.2,8.5,6.5,7.8- Tipo: Valores numéricos (int o float)
- Rango: Aunque el script menciona valores 0-10 en el help, acepta cualquier valor numérico
- Cantidad: Exactamente 10 características por ciudad
- Normalización: El script normaliza automáticamente todas las características al rango [0, 1] usando MinMaxScaler
- El CSV debe tener encabezados (nombres de columnas)
- Todas las filas deben tener el mismo número de columnas
- No deben existir valores faltantes (NaN) en las columnas numéricas
- La primera columna puede contener cualquier tipo de dato (se usa como identificador)
- Correspondencia con preferencias del usuario: Las características del CSV deben representar los mismos aspectos que la persona busca. El orden de las columnas en el CSV debe coincidir con el orden en que la persona proporciona sus preferencias
El script requiere las siguientes librerías de Python:
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 (lectura de CSV, DataFrames)
- numpy: Operaciones numéricas y arrays
- scikit-learn: Algoritmos de machine learning (NearestNeighbors, MinMaxScaler)
- joblib: Serialización eficiente de objetos Python (guardado/carga de modelos)
El modelo se guarda en formato .pkl usando la librería joblib, que es más eficiente que pickle para objetos de NumPy y scikit-learn.
El archivo .pkl contiene un diccionario con tres claves:
{
'knn_model': NearestNeighbors, # Modelo KNN entrenado
'scaler': MinMaxScaler, # Scaler con parámetros entrenados
'database': DataFrame # Base de datos completa de ciudades
}Es crítico guardar los tres componentes juntos porque:
- El modelo KNN necesita los vectores normalizados para funcionar correctamente
- El scaler debe ser el mismo usado en entrenamiento para normalizar nuevas características
- La base de datos contiene los nombres y datos completos de las ciudades para generar resultados legibles
Crear un 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.0python KNN-recomendation.py train --data ciudades.csv --out city_model.pklSalida:
Modelo entrenado exitosamente con 5 ciudades.
Modelo guardado en: city_model.pkl
Supongamos que un usuario tiene las siguientes preferencias (en orden):
- Seguridad: 8.5
- Transporte: 9.0
- Cultura: 9.5
- Gastronomía: 9.2
- Naturaleza: 7.0
- Entretenimiento: 8.8
- Educación: 8.5
- Salud: 8.0
- Economía: 7.5
- Calidad de Vida: 8.7
python KNN-recomendation.py predict --model city_model.pkl 8.5 9.0 9.5 9.2 7.0 8.8 8.5 8.0 7.5 8.7Salida:
--- RESULTADOS ---
Ciudad match_score
Barcelona 0.9987
Madrid 0.9856
Valencia 0.9234
- match_score: Valor entre 0 y 1 que indica la similitud entre las preferencias del usuario y la ciudad
- 1.0: Máxima similitud (ciudad perfectamente alineada con preferencias)
- 0.0: Mínima similitud (ciudad muy diferente a las preferencias)
- El score se calcula como
(1 - distancia_coseno), por lo que valores más altos indican mayor similitud - Las ciudades se ordenan de mayor a menor score (mejores recomendaciones primero)
-
Orden de características: Las características deben proporcionarse en el mismo orden que aparecen en el CSV (después de la columna de nombre de ciudad)
-
Normalización automática: No es necesario normalizar manualmente los valores de entrada; el script usa el scaler entrenado para normalizarlos automáticamente
-
Reentrenamiento: Si se modifica el CSV de ciudades, es necesario reentrenar el modelo con el comando
train -
Compatibilidad: El modelo guardado es específico de la versión de scikit-learn usada. Modelos guardados con versiones diferentes pueden no ser compatibles