
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from sklearn.feature_selection import SelectKBest, mutual_info_regression, RFE
import joblib

df = pd.read_csv('kidney_disease.csv')
print(df.info())

label_encoder = LabelEncoder()
for column in df.select_dtypes(include=['object']).columns:
    df[column] = label_encoder.fit_transform(df[column])

for column in df.columns:
    df[column] = pd.to_numeric(df[column], errors='coerce')

df.fillna(df.mean(), inplace=True)
df.to_csv('Chronic_Kidney_Disease_data_cleaned.csv', index=False)
print("File saved as Chronic_Kidney_Disease_data_cleaned.csv")

X = df.drop('classification', axis=1)
y = df['classification']

scaler = StandardScaler()
X = scaler.fit_transform(X)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)

select_feature = SelectKBest(mutual_info_regression, k=8).fit(X_train, y_train)
X_train_selected = select_feature.transform(X_train)
X_test_selected = select_feature.transform(X_test)

rfe_selector = RFE(estimator=RandomForestRegressor(random_state=42), n_features_to_select=8, step=1)
X_train_selected_rfe = rfe_selector.fit_transform(X_train, y_train)
X_test_selected_rfe = rfe_selector.transform(X_test)

def evaluate_model(model_name, y_true, y_pred):
    mae = mean_absolute_error(y_true, y_pred)
    mse = mean_squared_error(y_true, y_pred)
    rmse = np.sqrt(mse)
    r2 = r2_score(y_true, y_pred)
    results = {
        "Model Name": model_name,
        "Mean Absolute Error (MAE)": mae,
        "Mean Squared Error (MSE)": mse,
        "Root Mean Squared Error (RMSE)": rmse,
        "R^2 Score": r2
    }
    return results

models = {
    "RandomForestRegressor": RandomForestRegressor(random_state=42),
    "DecisionTreeRegressor": DecisionTreeRegressor(random_state=42),
    "SVR": SVR(),
    "GradientBoostingRegressor": GradientBoostingRegressor(random_state=42),
    "KNeighborsRegressor": KNeighborsRegressor()
}

param_grids = {
    "RandomForestRegressor": {
        'n_estimators': [100, 200, 300],
        'max_depth': [None, 10, 20, 30],
        'min_samples_split': [2, 5, 10],
        'min_samples_leaf': [1, 2, 4]
    },
    "DecisionTreeRegressor": {
        'max_depth': [None, 10, 20, 30],
        'min_samples_split': [2, 5, 10],
        'min_samples_leaf': [1, 2, 4]
    },
    "SVR": {
        'kernel': ['linear', 'poly', 'rbf', 'sigmoid'],
        'C': [0.1, 1, 10, 100],
        'epsilon': [0.1, 0.2, 0.5, 1],
        'gamma': ['scale', 'auto']
    },
    "GradientBoostingRegressor": {
        'n_estimators': [100, 200, 300],
        'learning_rate': [0.01, 0.1, 0.2],
        'max_depth': [3, 5, 7],
        'min_samples_split': [2, 5, 10],
        'min_samples_leaf': [1, 2, 4]
    },
    "KNeighborsRegressor": {
        'n_neighbors': [3, 5, 7, 10],
        'weights': ['uniform', 'distance'],
        'metric': ['euclidean', 'manhattan', 'minkowski']
    }
}

best_models = {}
for model_name, model in models.items():
    grid_search = GridSearchCV(estimator=model, param_grid=param_grids[model_name], cv=5, scoring='neg_root_mean_squared_error', verbose=2, n_jobs=-1)
    grid_search.fit(X_train_selected_rfe, y_train)
    best_model = grid_search.best_estimator_
    best_models[model_name] = best_model
    y_pred = best_model.predict(X_test_selected_rfe)
    evaluation_results = evaluate_model(model_name, y_test, y_pred)
    print(f"\nEvaluation results for {model_name}:")
    for key, value in evaluation_results.items():
        print(f"{key}: {value:.4f}" if isinstance(value, float) else f"{key}: \n{value}")
    print(f"Best parameters for {model_name}: {grid_search.best_params_}")

joblib.dump(best_models, 'amjaad2_models.pkl')
df.to_csv('amjaad2.csv', index=False)
print("Models and cleaned dataset saved.")
