Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| import joblib | |
| import pandas as pd | |
| from sklearn.pipeline import Pipeline | |
| from sklearn.preprocessing import FunctionTransformer, StandardScaler, OneHotEncoder | |
| from sklearn.compose import ColumnTransformer | |
| from sklearn.ensemble import RandomForestClassifier | |
| from custom_transformers import FeatureExtractor, cyclical_features | |
| def resource_path(relative_path): | |
| return os.path.join(getattr(sys, '_MEIPASS', os.path.abspath(".")), relative_path) | |
| MODEL_PATH = resource_path("model.pkl") | |
| _model = None | |
| _pipeline = None | |
| _last_model_mtime = None | |
| def build_pipeline(): | |
| cyclical_transform = FunctionTransformer(cyclical_features) | |
| preprocessor = ColumnTransformer([ | |
| ("num", StandardScaler(), ["price", "rating", "smart_score", "review_count"]), | |
| ("cat", OneHotEncoder(handle_unknown="ignore"), ["name"]) | |
| ], remainder="passthrough") | |
| pipeline = Pipeline([ | |
| ("extract", FeatureExtractor()), | |
| ("cyclical", cyclical_transform), | |
| ("preprocess", preprocessor) | |
| ]) | |
| return pipeline | |
| def load_model(): | |
| global _model, _last_model_mtime | |
| if not os.path.exists(MODEL_PATH): | |
| raise FileNotFoundError(f"Model file not found: {MODEL_PATH}") | |
| mtime = os.path.getmtime(MODEL_PATH) | |
| if _model is None or mtime > (_last_model_mtime or 0): | |
| _model = joblib.load(MODEL_PATH) | |
| _last_model_mtime = mtime | |
| def inference(input_df): | |
| global _pipeline | |
| load_model() | |
| if _pipeline is None: | |
| if not os.path.exists(PIPELINE_PATH): | |
| raise FileNotFoundError("Missing saved preprocessing pipeline (pipeline.pkl)") | |
| _pipeline = joblib.load(PIPELINE_PATH) | |
| processed = _pipeline.transform(input_df) # Only transform (no fit) | |
| return _model.predict(processed) | |
| PIPELINE_PATH = resource_path("pipeline.pkl") | |
| def retrain_model(df, target_col="decision"): | |
| global _pipeline | |
| pipeline = build_pipeline() | |
| _pipeline = pipeline # Save for reuse | |
| X = pipeline.fit_transform(df) | |
| y = df[target_col].map({"buy": 0, "wait": 1}).astype(int) | |
| model = RandomForestClassifier( | |
| n_estimators=100, random_state=42, | |
| max_depth=3, max_leaf_nodes=2, | |
| min_samples_split=3, min_samples_leaf=2, n_jobs=-1 | |
| ) | |
| model.fit(X, y) | |
| joblib.dump(model, MODEL_PATH) | |
| joblib.dump(pipeline, PIPELINE_PATH) | |
| print("✅ Model and pipeline saved.") | |
| if __name__ == "__main__": | |
| # dummy data | |
| data = { | |
| "name": ["Product A", "Product B", "Product C"], | |
| "price": [1000, 1500, 2000], | |
| "rating": [4.5, 4.0, 3.5], | |
| "smart_score": [0.05, 0.03, 0.02], | |
| "review_count": [100, 50, 30], | |
| "datetime": ["2023-10-01 12:00:00", "2023-10-02 13:00:00", "2023-10-03 14:00:00"], | |
| "decision": ["buy", "wait", "buy"] | |
| } | |
| df = pd.DataFrame(data) | |
| required_cols = [ | |
| "name", "price", "rating", "smart_score", "review_count", "datetime", | |
| ] | |
| if not all(col in df.columns for col in required_cols): | |
| raise ValueError("Missing required columns") | |
| df["date"] = df["datetime"] # match training format | |
| print("---- Retraining ----") | |
| retrain_model(df) | |
| print("Model and pipeline updated.") | |
| print("---- Inference ----") | |
| predictions = inference(df) | |
| print("Predictions:", predictions) | |