import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold, GridSearchCV, cross_val_predict
from sklearn.metrics import roc_auc_score, accuracy_score, confusion_matrix
from tqdm import tqdm
# Load the dataset
# LAB
file_path = '/Users/rachitbisht/Desktop/research/data/BC_Machine_Learning/datasets/LAB_30.xlsx'
# TN
#file_path = '/Users/rachitbisht/Desktop/research/data/BC_Machine_Learning/datasets/TN_30.xlsx'
data = pd.read_excel(file_path)
def perform_grid_search(data, comparison_groups, target_group, feature_names):
# Adjust binary labeling: '1' for target group (LAB), '0' for comparison groups (TN, Control)
data['Binary_Label'] = data['Type'].apply(lambda x: 1 if x == target_group else 0 if x in comparison_groups else None)
# Filter data to include only the relevant groups and features
data_filtered = data[data['Type'].isin(comparison_groups + [target_group])].copy()
# Use only the selected features
X = data_filtered[feature_names]
y = data_filtered['Binary_Label']
# Initialize the Random Forest classifier with class_weight='balanced'
rf_clf = RandomForestClassifier(random_state=42, class_weight='balanced')
param_grid = {
'n_estimators': [300, 350, 400, 450, 500],
'min_samples_split': [2, 3, 4],
'min_samples_leaf': [1, 2, 3, 4],
'max_features': ['sqrt', 'log2'],
'bootstrap': [True],
'max_depth': [4, 12, 20, None]
}
# Setup stratified cross-validation
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# Perform grid search with cross-validation
grid_search = GridSearchCV(estimator=rf_clf, param_grid=param_grid, cv=cv, scoring='roc_auc', n_jobs=-1, return_train_score=False)
grid_search.fit(X, y)
# Extract results into a pandas DataFrame
results = pd.DataFrame(grid_search.cv_results_)
# Add accuracy, AUC scores, FPR, and False Positives for each combination with a progress bar
all_results = []
total_combinations = len(grid_search.cv_results_['params'])
for idx, (params, mean_test_score) in enumerate(tqdm(zip(grid_search.cv_results_['params'], grid_search.cv_results_['mean_test_score']), total=total_combinations, desc="Grid Search Progress")):
# Train the model for each parameter set
best_rf_clf = RandomForestClassifier(random_state=42, class_weight='balanced', **params)
best_rf_clf.fit(X, y)
# Get cross-validated predictions for accuracy
y_pred = cross_val_predict(best_rf_clf, X, y, cv=cv)
accuracy = accuracy_score(y, y_pred)
# Calculate the confusion matrix
cm = confusion_matrix(y, y_pred)
# Extract TN, FP, FN, TP from confusion matrix
tn, fp, fn, tp = cm.ravel()
# Compute False Positive Rate (FPR)
fpr = fp / (fp + tn)
# Store the result, including false positives for TN
all_results.append({
'params': params,
'AUC Score': mean_test_score,
'Accuracy': accuracy,
'FPR (TN)': fpr, # Minimizing this to optimize for TN
'False Positives (TN)': fp # Number of false positives for TN
})
# Convert the list of results to a DataFrame
df_results = pd.DataFrame(all_results)
# Save the DataFrame to an Excel file
output_file = 'grid_search_results_with_fpr_and_fp_for_lab.xlsx'
df_results.to_excel(output_file, index=False)
print(f"Results saved to {output_file}")
return df_results
# List of selected features without numeric suffixes
#TN features
# selected_features = [
# "Q06187|BTK_Phospho_STGDPQGVIR_1",
# "Q06187|BTK_Phospho_STGDPQGVIR_2",
# "Q99501|GA2L1_Phospho_VSPTTSPRPASPVPGSER_2",
# "Q9Y3Q8|T22D4_Phospho_SPDPFGAVAAQK",
# "P78324|SHPS1_Glyco_GTANLSETIR",
# "P01133|EGF_Glyco_VFLNGSR",
# "Q6WCQ1|MPRIP_Phospho_SNPDFLK"
# ]
#LAB features
selected_features = [
"Q14517|FAT1_Glyco_TGALTVQNTTQLR",
"O95772|STR3N_Phospho_LLIVQDASER",
"P50851|LRBA_Phospho_SPVDIVTGGISPVR",
"Q15942|ZYX_Phospho_SPGAPGPLTLK",
"O75326|SEM7A_Glyco_NPEAPLNVSR",
"P01137|TGFB1_Glyco_YSNNSWR",
"Q6WCQ1|MPRIP_Phospho_SNPDFLK"
]
# Perform the grid search for LAB vs TN and Control using the specified features
df_results = perform_grid_search(data, ['TN', 'Control'], 'LAB', selected_features)