eta-service / src /components /model_trainer.py
sliitguy
update
09ab88a
import os
import sys
from src.exception.exception import DeliveryTimeException
from src.logging.logger import logging
from src.entity.artifact_entity import DataTransformationArtifact, ModelTrainerArtifact
from src.entity.config_entity import ModelTrainerConfig
from src.utils.ml_utils.model.estimator import DeliveryPredictionModel
from src.utils.main_utils.utils import save_object, load_object
from src.utils.main_utils.utils import load_numpy_array_data, evaluate_models
from src.utils.ml_utils.metric.regression_metric import get_regression_score
import pandas as pd
from xgboost import XGBRegressor
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import RandomizedSearchCV
import os
import joblib
import sys
import mlflow
from dotenv import load_dotenv
load_dotenv()
os.environ["MLFLOW_TRACKING_URI"] = os.getenv("MLFLOW_TRACKING_URI")
os.environ["MLFLOW_TRACKING_USERNAME"] = os.getenv("MLFLOW_TRACKING_USERNAME")
os.environ["MLFLOW_TRACKING_PASSWORD"] = os.getenv("MLFLOW_TRACKING_PASSWORD")
class ModelTrainer:
def __init__(self, model_trainer_config:ModelTrainerConfig, data_transformation_artifact:DataTransformationArtifact):
try:
self.model_trainer_config=model_trainer_config
self.data_transformation_artifact=data_transformation_artifact
# CHANGED: Update feature names to match the pipeline output with scaler
self.model_trainer_config.feature_names=[
'scaler__Distance_km',
'scaler__Courier_Experience_yrs',
'Vehicle_Type_Pickup Truck',
'Vehicle_Type_Scooter',
'Weather_Foggy',
'Weather_Rainy',
'Weather_Snowy',
'Weather_Windy',
'Time_of_Day_Evening',
'Time_of_Day_Morning',
'Time_of_Day_Night',
'Traffic_Level_Low',
'Traffic_Level_Medium'
]
except Exception as e:
raise DeliveryTimeException(e, sys)
def track_mlflow(self, best_model, regressionMetric):
mlflow.set_tracking_uri(os.getenv("MLFLOW_TRACKING_URI"))
with mlflow.start_run():
mlflow.log_metric("r2_score", regressionMetric.r2_score)
mlflow.log_metric("Mean_Absolute_Error", regressionMetric.mean_absolute_error)
mlflow.log_metric("Mean_Squared_Error", regressionMetric.mean_squared_error)
joblib.dump(best_model, "model.joblib")
mlflow.log_artifact("model.joblib", artifact_path="model")
def train_model(self, X_train, y_train, X_test, y_test):
try:
models = {
"XGBoost Regression": XGBRegressor(objective='reg:squarederror', random_state=42, n_jobs=-1),
"RandomForest": RandomForestRegressor(),
"GradientBoostRegressor": GradientBoostingRegressor()
}
params = {
"XGBoost Regression" : {
'n_estimators': [500, 700, 100, 150],
'max_depth': [3, 4, 5],
'learning_rate': [0.01, 0.05],
'subsample': [0.6, 0.8, 1.0],
'colsample_bytree': [0.6, 0.7, 0.8]
},
'GradientBoostRegressor': {
'n_estimators':[1000, 500],
'min_samples_split': [2, 8],
'criterion': ['friedman_mse', 'squared_error'],
'loss': ['squared_error', 'huber'],
'max_depth': [5, None]
},
'RandomForest': {
'n_estimators': [1000],
'min_samples_split': [2],
'max_features': [7],
'max_depth': [None]
}
}
model_report:dict=evaluate_models(X_train=X_train, y_train=y_train, X_test=X_test, y_test=y_test,
models=models, param=params)
best_model_score = max(sorted(model_report.values()))
best_model_name = list(model_report.keys())[
list(model_report.values()).index(best_model_score)
]
best_model = models[best_model_name]
y_train_pred = best_model.predict(X_train)
regression_train_metric=get_regression_score(y_true= y_train, y_pred=y_train_pred)
self.track_mlflow(best_model, regression_train_metric)
y_test_pred = best_model.predict(X_test)
regression_test_metric = get_regression_score(y_true=y_test, y_pred=y_test_pred)
self.track_mlflow(best_model, regression_test_metric)
model_dir_path = os.path.dirname(self.model_trainer_config.trained_model_file_path)
os.makedirs(model_dir_path, exist_ok=True)
Delivery_Prediction_Model=DeliveryPredictionModel(model=best_model)
save_object(self.model_trainer_config.trained_model_file_path, obj=Delivery_Prediction_Model)
# Model Pusher
save_object("final_model/model.pkl", best_model)
model_trainer_artifact=ModelTrainerArtifact(
trained_model_file_path=self.model_trainer_config.trained_model_file_path,
train_metric_artifact=regression_train_metric,
test_metric_artifact=regression_test_metric
)
logging.info(f"Model trainer artifact: {model_trainer_artifact}")
return model_trainer_artifact
except Exception as e:
raise DeliveryTimeException(e, sys)
def initiate_model_trainer(self) -> ModelTrainerArtifact:
try:
train_file_path = self.data_transformation_artifact.transformed_train_file_path
test_file_path = self.data_transformation_artifact.transformed_test_file_path
train_arr = load_numpy_array_data(train_file_path)
test_arr = load_numpy_array_data(test_file_path)
logging.info(f"Shape of training data: {train_arr.shape}")
logging.info(f"Testing array: {test_arr.shape}")
X_train, y_train, X_test, y_test = (
train_arr[:, :-1],
train_arr[:, -1],
test_arr[:, :-1],
test_arr[:, -1]
)
logging.info(f"X_train shape: {X_train.shape}")
logging.info(f"X_test sahpe: {X_test.shape}")
# REMOVED: All the StandardScaler code and DataFrame conversion
# Train directly on the transformed arrays
model_trainer_artifact = self.train_model(X_train, y_train, X_test, y_test)
return model_trainer_artifact
except Exception as e:
raise DeliveryTimeException(e, sys)