-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRandom-Forest-Predictivo.py
More file actions
114 lines (91 loc) · 4.72 KB
/
Random-Forest-Predictivo.py
File metadata and controls
114 lines (91 loc) · 4.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import pandas as pd
import numpy as np
import argparse
import joblib
import sys
import os
from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import MinMaxScaler
class HybridRecommender:
def __init__(self):
# RandomForest es robusto y no requiere tanta normalización,
# pero mantenemos el scaler para las entradas del usuario por consistencia.
self.model = RandomForestRegressor(n_estimators=100, random_state=42)
self.cities_df = None
def train(self, cities_path: str, history_path: str, model_out: str):
"""
Entrena cruzando el historial de usuarios con las features de las ciudades.
"""
# 1. Cargar datos
df_cities = pd.read_csv(cities_path)
df_history = pd.read_csv(history_path)
# 2. Feature Engineering: JOIN de tablas
# Unimos el historial con los atributos de la ciudad visitada
# Resultante: [User_F1..F10] + [City_F1..F10] + [Rating]
training_data = pd.merge(df_history, df_cities, left_on='City_Name', right_on='City')
# Separar Features (X) y Target (y)
# Asumimos que las features del usuario son col 0-9 y las de ciudad las siguientes
# Excluimos nombres de ciudades y ratings del set de entrenamiento
feature_cols = [c for c in training_data.columns if c not in ['City_Name', 'City', 'Rating']]
X = training_data[feature_cols]
y = training_data['Rating']
print(f"Entrenando con {len(X)} registros históricos...")
self.model.fit(X, y)
# 3. Guardar todo
artifacts = {
'model': self.model,
'cities_df': df_cities,
'feature_order': feature_cols # Guardamos el orden exacto de columnas
}
joblib.dump(artifacts, model_out)
print(f"Modelo híbrido guardado en: {model_out}")
def predict(self, model_path: str, user_features: list):
"""
Para predecir, simulamos que el usuario viaja a TODAS las ciudades
y el modelo estima qué rating le daría a cada una.
"""
if not os.path.exists(model_path):
raise FileNotFoundError("Modelo no encontrado.")
artifacts = joblib.load(model_path)
model = artifacts['model']
df_cities = artifacts['cities_df']
# Preparamos el batch de predicción
# Creamos un DataFrame donde cada fila es: [User_Features] + [City_Features]
# 1. Replicamos las features del usuario tantas veces como ciudades hay
user_matrix = np.tile(user_features, (len(df_cities), 1))
df_user = pd.DataFrame(user_matrix, columns=[f'User_F{i+1}' for i in range(10)]) # Nombres teóricos
# 2. Obtenemos las features de las ciudades (solo numéricas)
# Nota: Esto asume que el CSV de ciudades tiene formato consistente con el entrenamiento
city_feats = df_cities.select_dtypes(include=[np.number]).reset_index(drop=True)
# 3. Concatenamos horizontalmente
X_predict = pd.concat([df_user, city_feats], axis=1)
# IMPORTANTE: Asegurar que las columnas coincidan con el entrenamiento
# (Aquí simplificamos asumiendo que el orden numérico se mantiene,
# en prod se debe validar por nombre de columna exacto).
# 4. Predicción
predicted_ratings = model.predict(X_predict.values)
# 5. Formatear salida
results = df_cities.copy()
results['Predicted_Rating'] = predicted_ratings.round(2)
return results.sort_values('Predicted_Rating', ascending=False)
def main():
parser = argparse.ArgumentParser(description="Recomendador Supervisado (Historical Data)")
subparsers = parser.add_subparsers(dest='command', required=True)
# Train
p_train = subparsers.add_parser('train')
p_train.add_argument('--cities', required=True, help='CSV de Ciudades')
p_train.add_argument('--history', required=True, help='CSV de Historial')
p_train.add_argument('--out', default='hybrid_model.pkl')
# Predict
p_predict = subparsers.add_parser('predict')
p_predict.add_argument('--model', default='hybrid_model.pkl')
p_predict.add_argument('features', type=float, nargs=10)
args = parser.parse_args()
rec = HybridRecommender()
if args.command == 'train':
rec.train(args.cities, args.history, args.out)
elif args.command == 'predict':
results = rec.predict(args.model, args.features)
print(results[['City', 'Predicted_Rating']].head(5).to_string(index=False))
if __name__ == "__main__":
main()