Spaces:
Sleeping
Sleeping
| """ | |
| models.py — Inference Layer | |
| ---------------------------- | |
| Loads the trained ETA regressor and hit classifier from disk once at module | |
| import time. Exposes a single function that accepts a feature dict, converts | |
| it to an ordered numpy array using FEATURE_COLUMNS, runs both models, and | |
| returns ETA in seconds and hit probability as a float. | |
| This module knows nothing about physics, metadata, or decisions. | |
| Its only job is: feature array in, predictions out. | |
| """ | |
| from src.schemas import FEATURE_COLUMNS, MODEL_PATHS | |
| from joblib import load | |
| import numpy as np | |
| # Empty dictionary to hold the active loaded model | |
| loaded_model = {} | |
| # Load the model once in the memory | |
| for model_name, path in MODEL_PATHS.items(): | |
| if model_name in ('eta', 'hit'): | |
| try: | |
| loaded_model[model_name] = load(path) | |
| print(f"Successfully loaded: {model_name} model") | |
| except FileNotFoundError: | |
| print(f"Error: The file at {path} could not be found.") | |
| except Exception as e: | |
| print(f"An error occurred while loading model {model_name}: {e}") | |
| # Function to make predictions using loaded models | |
| def make_predictions(feature_dict): | |
| """ | |
| Converts a feature dict to a numpy array and runs both models. | |
| Args: | |
| feature_dict (dict): 14-feature dict in FEATURE_COLUMNS order, | |
| produced by build_feature_array(). | |
| Returns: | |
| dict: { | |
| "eta_seconds": float, # predicted evasion time, clipped at 0 | |
| "hit_probability": float # probability of hit after evasion (0.0 - 1.0) | |
| } | |
| """ | |
| # Convert the dictionary into ndarray using the order of FEATURE_COLUMNS | |
| feature_values = np.array([feature_dict[col] for col in FEATURE_COLUMNS]) | |
| # Reshape the the feature_values into (1, 14) as a line of table | |
| feature_values = feature_values.reshape(1, -1) | |
| # Performing predictions | |
| for model_name, model in loaded_model.items(): | |
| if model_name == 'eta': | |
| eta_prediction = model.predict(feature_values) | |
| # Clip the negative time value to 0 | |
| eta_prediction = np.maximum(eta_prediction, 0)[0] | |
| else: | |
| hit_prediction = model.predict_proba(feature_values)[0][1] # [probability of miss, probability of hit] | |
| return { | |
| "eta_seconds": float(eta_prediction), | |
| "hit_probability": float(hit_prediction) | |
| } | |