From 26298704a91ef3fe9c86d584f4f5c76924dc32c3 Mon Sep 17 00:00:00 2001 From: acgm8 Date: Fri, 29 Aug 2025 15:54:42 +0200 Subject: [PATCH] Add files via upload --- scripts/DecisionTree.py | 72 +++++++++++++++++++++++++++++++++++++++++ scripts/Imputing.py | 59 ++++++++++++++++----------------- scripts/Scaling.py | 71 ++++++++++++++++++++++------------------ 3 files changed, 142 insertions(+), 60 deletions(-) create mode 100644 scripts/DecisionTree.py diff --git a/scripts/DecisionTree.py b/scripts/DecisionTree.py new file mode 100644 index 0000000..578ae09 --- /dev/null +++ b/scripts/DecisionTree.py @@ -0,0 +1,72 @@ +from sklearn.ensemble import RandomForestRegressor +from sklearn.experimental import enable_halving_search_cv +from sklearn.model_selection import train_test_split, HalvingGridSearchCV, learning_curve +from sklearn.feature_selection import SelectFromModel +from sklearn.tree import DecisionTreeRegressor +from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error + + + +def decision_tree(X_train, y_train, X_test, y_test, test_size=0.3, random_state=42): + + # Let's define the model (so our DecisionTreeRegressor) and do a HalvingGridSearchCV to find the best hyperparameters + dt = DecisionTreeRegressor(random_state=random_state) + + param_grid = { + "max_depth": [None, 5, 10, 20, 30], + "min_samples_split": [0.001, 0.01, 0.1], + "min_samples_leaf": [0.001, 0.01, 0.1], + } + + halving_search = HalvingGridSearchCV( + dt, + param_grid, + cv=5, + factor=2, + scoring="neg_root_mean_squared_error" + ) + + halving_search.fit(X_train, y_train) + best_dt = halving_search.best_estimator_ + + #Visualization + + train_sizes, train_scores, val_scores = learning_curve(best_dt, X_train, y_train, cv=5, scoring="neg_root_mean_squared_error", train_sizes=np.linspace(0.1,1.0,20)) + + # Average scores across folds + train_rmse = -train_scores.mean(axis=1) + val_rmse = -val_scores.mean(axis=1) + + # Let's visualize the loss curve + plt.figure(figsize=(6, 4)) + plt.plot(train_sizes, train_rmse, "o-", label="Training RMSE") + plt.plot(train_sizes, val_rmse, "o-", label="Validation RMSE") + plt.xlabel("Training set size") + plt.ylabel("RMSE") + plt.title("Learning Curve (Decision Tree)") + plt.legend() + plt.grid(True) + plt.show() + + #predict on the test dataset + y_pred = best_dt.predict(X_test) + mse = mean_squared_error(y_test, y_pred) + rmse = np.sqrt(mse) + mae = mean_absolute_error(y_test, y_pred) + r2 = r2_score(y_test, y_pred) + + metrics = { + "RMSE": rmse, + "MSE": mse, + "MAE": mae, + "R2": r2, + } + + print(f"Best parameters: {halving_search.best_params_}") + for k, v in metrics.items(): + print(f"{k}: {v:.4f}") + + return best_dt, y_pred, metrics + +# #How to use this +# results_dt = decision_tree(X_train, y_train, X_test, y_test) \ No newline at end of file diff --git a/scripts/Imputing.py b/scripts/Imputing.py index d9d4cce..aaf0a43 100644 --- a/scripts/Imputing.py +++ b/scripts/Imputing.py @@ -1,29 +1,30 @@ - -import pandas as pd -import numpy as np -from sklearn.impute import KNNImputer -#this function imputes missing values from any df with KNNImputer -def knn_impute_numeric(df, n_neighbors=5): - - #select only the numerical variables to do the imputer - numeric_cols = df.select_dtypes(include=['float','int']) - print(f": shape of df with only numeric features={numeric_cols.shape}") - - #Impute the numerical variables - imputer = KNNImputer(missing_values=np.nan, n_neighbors=n_neighbors, keep_empty_features=True) - imputed_numeric_data = imputer.fit_transform(numeric_cols) - - # Create a new DataFrame with the imputed numeric data - imputed_numeric_df = pd.DataFrame(imputed_numeric_data, columns=numeric_cols.columns, index=df.index) - - # Combine the imputed numeric columns with the non-numeric columns to ensure that we keep them - non_numeric_cols = df.select_dtypes(exclude=['float','int']) - imputed_df = pd.concat([imputed_numeric_df, non_numeric_cols], axis=1) - - # Ensure the column order is the same as the original dataframe - imputed_df = imputed_df[df.columns] - - return imputed_df - -#imputed_df = knn_impute_numeric(filtered_df, n_neighbors=5) -#imputed_df.head() + +import pandas as pd +import numpy as np +from sklearn.impute import KNNImputer +#this function imputes missing values from any df with KNNImputer +def knn_impute_numeric(df_train, df_test, n_neighbors=5): + + #select only the numerical variables to do the imputer + numeric_cols = df_train.select_dtypes(include=['float', 'int']).columns + print(f"Numeric features for imputation: {len(numeric_cols)} columns") + + # Fit imputer on training data + imputer = KNNImputer(n_neighbors=n_neighbors, missing_values=np.nan, keep_empty_features=True) + imputed_train = imputer.fit_transform(df_train[numeric_cols]) + imputed_train_df = pd.DataFrame(imputed_train, columns=numeric_cols, index=df_train.index) + + # Transform test data + imputed_test = imputer.transform(df_test[numeric_cols]) + imputed_test_df = pd.DataFrame(imputed_test, columns=numeric_cols, index=df_test.index) + + # Keep non-numeric columns unchanged + non_numeric_cols = df_train.select_dtypes(exclude=['float', 'int']).columns + imputed_train_df = pd.concat([imputed_train_df, df_train[non_numeric_cols]], axis=1)[df_train.columns] + imputed_test_df = pd.concat([imputed_test_df, df_test[non_numeric_cols]], axis=1)[df_test.columns] + + return imputed_train_df, imputed_test_df, imputer + +#How to use +# imputed_train_df, imputed_test_df, imputer = knn_impute_numeric(X_train, X_test, n_neighbors=5) + diff --git a/scripts/Scaling.py b/scripts/Scaling.py index cc12510..cdca08f 100644 --- a/scripts/Scaling.py +++ b/scripts/Scaling.py @@ -1,31 +1,40 @@ - -#This function scales numerical values -from sklearn.preprocessing import RobustScaler -import pandas as pd -def scaler_numeric(df, target_col=''): - - #separate the nutriscore and the rest of the values to do the scaling - X = df.drop([target_col], axis = 1) - y = df[target_col] - - #select only the numerical variables to do the scaling - X_numeric = X.select_dtypes(include=['float','int']) - print(f": shape of df with only numeric features={X_numeric.shape}") - - #scale the numerical values and put the scaled numerical data into a dataframe - scaler = RobustScaler() - X_scaled = scaler.fit_transform(X_numeric) - X_scaled_df = pd.DataFrame(X_scaled, columns=X_numeric.columns, index=X_numeric.index) - - #combine the scaled df with the nutriscore - X_non_numeric = X.select_dtypes(exclude=['float','int']) - X_processed = pd.concat([X_scaled_df, X_non_numeric], axis=1) - scaled_df = pd.concat([X_processed, y], axis=1) - - # Ensure the column order is the same as the original dataframe - scaled_df = scaled_df[df.columns] - - return scaled_df - -#scaled_df = scaler_numeric(imputed_df, target_col='nutriscore_score') -#scaled_df.head() + +#This function scales numerical values +from sklearn.preprocessing import RobustScaler +import pandas as pd +def robust_scaler(df_train, df_test, target_col): + + #Separate train and test set + + X_train = df_train.drop([target_col], axis=1) + X_test = df_test.drop([target_col], axis=1) + y_train = df_train[target_col] + y_test = df_test[target_col] + + # Select numeric columns + numeric_cols = X_train.select_dtypes(include=['float','int']).columns + + # Fit the scaler on the numeric columns of the train dataset + scaler = RobustScaler() + X_train_scaled = scaler.fit_transform(X_train[numeric_cols]) + X_train_scaled_df = pd.DataFrame(X_train_scaled, columns=numeric_cols, index=X_train.index) + + # Apply the scaling on the numeric columns of the test datset + X_test_scaled = scaler.transform(X_test[numeric_cols]) + X_test_scaled_df = pd.DataFrame(X_test_scaled, columns=numeric_cols, index=X_test.index) + + # Combine the numeric with the non-numeric columns for both datasets + non_numeric_cols = X_train.select_dtypes(exclude=['float','int']) + scaled_train_df = pd.concat([X_train_scaled_df, X_train[non_numeric_cols]], axis=1)[X_train.columns] + scaled_test_df = pd.concat([X_test_scaled_df, X_test[non_numeric_cols]], axis=1)[X_test.columns] + + scaled_train_df[target_col] = y_train + scaled_test_df[target_col] = y_test + # Ensure original column order + scaled_train_df = scaled_train_df[df_train.columns] + scaled_test_df = scaled_test_df[df_test.columns] + + return scaled_train_df, scaled_test_df, scaler + +#scaled_train_df, scaled_test_df, scaler = robust_scaler(X_train, X_test, target_col='nutriscore_score') +#scaled_df.head()