IsabellaM's picture
Update app.py
254070e verified
Raw
History Blame Contribute Delete
18.8 kB
import pandas as pd
from scipy.stats import ttest_rel
# Load results
df = pd.read_csv("THE_MODEL_RESULTS.csv")
# Define individual models
tree_models = ["RandomForest", "DecisionTree"]
non_tree_models = ["KNN", "SVM", "LogisticRegression", "PyTorchNN"]
print("="*80)
print("REPLICATION: Uddin & Lu (2024) - Pairwise Model Comparisons")
print("="*80)
# Store all results
all_results = []
# For each metric
for metric in ["accuracy", "precision", "recall", "f1_score"]:
print(f"\n({metric.upper()})")
print("-"*80)
print(f"{'#':<3} {'Tree Model':<20} {'Non-Tree Model':<20} {'Mean 1':<10} {'Mean 2':<10} {'t':<8} {'p-value':<10} {'Sig.'}")
print("-"*80)
comparison_num = 1
# Compare each tree model with each non-tree model
for tree_model in tree_models:
for non_tree_model in non_tree_models:
# Get data for both models across all datasets
tree_data = df[df['model'] == tree_model].set_index('dataset')[metric]
non_tree_data = df[df['model'] == non_tree_model].set_index('dataset')[metric]
# Align datasets (inner join - only datasets present for both models)
combined = pd.DataFrame({
'tree': tree_data,
'non_tree': non_tree_data
}).dropna()
if len(combined) < 2:
print(f"{comparison_num:<3} {tree_model:<20} {non_tree_model:<20} Insufficient data")
comparison_num += 1
continue
# Paired t-test
t_stat, p_val = ttest_rel(combined['tree'], combined['non_tree'])
# Calculate means and stds
mean1 = combined['tree'].mean()
mean2 = combined['non_tree'].mean()
std1 = combined['tree'].std()
std2 = combined['non_tree'].std()
n = len(combined)
sig = "< 0.001" if p_val < 0.001 else f"{p_val:.3f}"
print(f"{comparison_num:<3} {tree_model:<20} {non_tree_model:<20} {mean1:<10.5f} {mean2:<10.5f} {t_stat:<8.2f} {sig:<10} {'True' if p_val < 0.05 else 'False'}")
all_results.append({
'metric': metric,
'tree_model': tree_model,
'non_tree_model': non_tree_model,
'tree_mean': mean1,
'non_tree_mean': mean2,
'tree_std': std1,
'non_tree_std': std2,
'n_datasets': n,
't_statistic': t_stat,
'p_value': p_val
})
comparison_num += 1
# Summary
print("\n" + "="*80)
print("SUMMARY")
print("="*80)
results_df = pd.DataFrame(all_results)
significant_count = (results_df['p_value'] < 0.05).sum()
total_count = len(results_df)
print(f"\nSignificant comparisons (p < 0.05): {significant_count}/{total_count}")
print(f"Tree models won in: {(results_df['tree_mean'] > results_df['non_tree_mean']).sum()} comparisons")
# Save detailed results
results_df.to_csv('FINAL_COMPARISON_RESULTS.csv', index=False)
import gradio as gr
import pandas as pd
from scipy.stats import ttest_rel
#import matplotlib.pyplot as plt
#import seaborn as sns
import numpy as np
import plotly.express as px
# DATASET_CATEGORIES is assumed to be defined globally or in an earlier cell
DATASET_CATEGORIES = {
"Medical & Healthcare": {
"D1": "Heart Disease (Comprehensive)",
"D2": "Heart attack possibility",
"D3": "Heart Disease Dataset",
"D4": "Liver Disorders",
"D5": "Diabetes Prediction",
"D9": "Chronic Kidney Disease",
"D10": "Breast Cancer Prediction",
"D11": "Stroke Prediction",
"D12": "Lung Cancer Prediction",
"D13": "Hepatitis",
"D15": "Thyroid Disease",
"D16": "Heart Failure Prediction",
"D17": "Parkinson's",
"D18": "Indian Liver Patient",
"D19": "COVID-19 Effect on Liver Cancer",
"D20": "Liver Dataset",
"D21": "Specht Heart",
"D22": "Early-stage Diabetes",
"D23": "Diabetic Retinopathy",
"D24": "Breast Cancer Coimbra",
"D25": "Chronic Kidney Disease",
"D26": "Kidney Stone",
"D28": "Echocardiogram",
"D29": "Bladder Cancer Recurrence",
"D31": "Prostate Cancer",
"D46": "Real Breast Cancer Data",
"D47": "Breast Cancer (Royston)",
"D48": "Lung Cancer Dataset",
"D52": "Cervical Cancer Risk",
"D53": "Breast Cancer Wisconsin",
"D61": "Breast Cancer Prediction",
"D62": "Thyroid Disease",
"D68": "Lung Cancer",
"D69": "Cancer Patients Data",
"D70": "Labor Relations",
"D71": "Glioma Grading",
"D74": "Post-Operative Patient",
"D80": "Heart Rate Stress Monitoring",
"D82": "Diabetes 2019",
"D87": "Personal Heart Disease Indicators",
"D92": "Heart Disease (Logistic)",
"D95": "Diabetes Prediction",
"D97": "Cardiovascular Disease",
"D98": "Diabetes 130 US Hospitals",
"D99": "Heart Disease Dataset",
"D181": "HCV Data",
"D184": "Cardiotocography",
"D189": "Mammographic Mass",
"D199": "Easiest Diabetes",
"D200": "Monkey-Pox Patients",
"D54": "Breast Cancer Wisconsin",
"D63": "Sick-euthyroid",
"D64": "Ann-test",
"D65": "Ann-train",
"D66": "Hypothyroid",
"D67": "New-thyroid",
"D72": "Glioma Grading"
},
"Gaming & Sports": {
"D27": "Chess King-Rook",
"D36": "Tic-Tac-Toe",
"D40": "IPL 2022 Matches",
"D41": "League of Legends",
"D55": "League of Legends Diamond",
"D56": "Chess Game Dataset",
"D57": "Game of Thrones",
"D73": "Connect-4",
"D75": "FIFA 2018",
"D76": "Dota 2 Matches",
"D77": "IPL Match Analysis",
"D78": "CS:GO Professional",
"D79": "IPL 2008-2022",
"D114": "Video Games",
"D115": "Video Games Sales",
"D117": "Sacred Games",
"D118": "PC Games Sales",
"D119": "Popular Video Games",
"D120": "Olympic Games 2021",
"D121": "Video Games ESRB",
"D122": "Top Play Store Games",
"D123": "Steam Games",
"D124": "PS4 Games",
"D116": "Video Games Sales"
},
"Education & Students": {
"D43": "Student Marks",
"D44": "Student 2nd Year Result",
"D45": "Student Mat Pass/Fail",
"D103": "Academic Performance",
"D104": "Student Academic Analysis",
"D105": "Student Dropout Prediction",
"D106": "Electronic Gadgets Impact",
"D107": "Campus Recruitment",
"D108": "End-Semester Performance",
"D109": "Fitbits and Grades",
"D110": "Student Time Management",
"D111": "Student Feedback",
"D112": "Depression & Performance",
"D113": "University Rankings",
"D126": "University Ranking CWUR",
"D127": "University Ranking CWUR 2013-2014",
"D128": "University Ranking CWUR 2014-2015",
"D129": "University Ranking CWUR 2015-2016",
"D130": "University Ranking CWUR 2016-2017",
"D131": "University Ranking CWUR 2017-2018",
"D132": "University Ranking CWUR 2018-2019",
"D133": "University Ranking CWUR 2019-2020",
"D134": "University Ranking CWUR 2020-2021",
"D135": "University Ranking CWUR 2021-2022",
"D136": "University Ranking CWUR 2022-2023",
"D137": "University Ranking GM 2016",
"D138": "University Ranking GM 2017",
"D139": "University Ranking GM 2018",
"D140": "University Ranking GM 2019",
"D141": "University Ranking GM 2020",
"D142": "University Ranking GM 2021",
"D143": "University Ranking GM 2022",
"D144": "University Ranking Webometric 2012",
"D145": "University Ranking Webometric 2013",
"D146": "University Ranking Webometric 2014",
"D147": "University Ranking Webometric 2015",
"D148": "University Ranking Webometric 2016",
"D149": "University Ranking Webometric 2017",
"D150": "University Ranking Webometric 2018",
"D151": "University Ranking Webometric 2019",
"D152": "University Ranking Webometric 2020",
"D153": "University Ranking Webometric 2021",
"D154": "University Ranking Webometric 2022",
"D155": "University Ranking Webometric 2023",
"D156": "University Ranking URAP 2018-2019",
"D157": "University Ranking URAP 2019-2020",
"D158": "University Ranking URAP 2020-2021",
"D159": "University Ranking URAP 2021-2022",
"D160": "University Ranking URAP 2022-2023",
"D161": "University Ranking THE 2011",
"D162": "University Ranking THE 2012",
"D163": "University Ranking THE 2013",
"D164": "University Ranking THE 2014",
"D165": "University Ranking THE 2015",
"D166": "University Ranking THE 2016",
"D167": "University Ranking THE 2017",
"D168": "University Ranking THE 2018",
"D169": "University Ranking THE 2019",
"D170": "University Ranking THE 2020",
"D171": "University Ranking THE 2021",
"D172": "University Ranking THE 2022",
"D173": "University Ranking THE 2023",
"D174": "University Ranking QS 2022",
"D190": "Student Academics Performance"
},
"Banking & Finance": {
"D6": "Bank Marketing 1",
"D7": "Bank Marketing 2",
"D30": "Adult Income",
"D32": "Telco Customer Churn",
"D35": "Credit Approval",
"D50": "Term Deposit Prediction",
"D96": "Credit Card Fraud",
"D188": "South German Credit",
"D193": "Credit Risk Classification",
"D195": "Credit Score Classification",
"D196": "Banking Classification"
},
"Science & Engineering": {
"D8": "Mushroom",
"D14": "Ionosphere",
"D33": "EEG Eye State",
"D37": "Steel Plates Faults",
"D39": "Fertility",
"D51": "Darwin",
"D58": "EEG Emotions",
"D81": "Predictive Maintenance",
"D84": "Oranges vs Grapefruit",
"D90": "Crystal System Li-ion",
"D183": "Drug Consumption",
"D49": "Air Pressure System Failures",
"D93": "Air Pressure System Failures",
"D185": "Toxicity",
"D186": "Toxicity"
},
"Social & Lifestyle": {
"D38": "Online Shoppers",
"D59": "Red Wine Quality",
"D60": "White Wine Quality",
"D88": "Airline Passenger Satisfaction",
"D94": "Go Emotions Google",
"D100": "Spotify East Asian",
"D125": "Suicide Rates",
"D182": "Obesity Levels",
"D187": "Blood Transfusion",
"D191": "Obesity Classification",
"D192": "Gender Classification",
"D194": "Happiness Classification",
"D42": "Airline customer Holiday Booking dataset"
},
"ML Benchmarks & Synthetic": {
"D34": "Spambase",
"D85": "Synthetic Binary",
"D89": "Naive Bayes Data",
"D175": "Monk's Problems 1",
"D176": "Monk's Problems 2",
"D177": "Monk's Problems 3",
"D178": "Monk's Problems 4",
"D179": "Monk's Problems 5",
"D180": "Monk's Problems 6"
},
"Other": {
"D83": "Paris Housing",
"D91": "Fake Bills",
"D197": "Star Classification"
}
}
try:
df = pd.read_csv("THE_MODEL_RESULTS.csv")
except FileNotFoundError:
raise FileNotFoundError("THE_MODEL_RESULTS.csv not found. Please run the previous steps to generate it.")
#models and accuracy
available_models = df['model'].unique().tolist()
available_metrics = ["accuracy", "precision", "recall", "f1_score"]
# Helper functions
def update_datasets_choices(category, select_all):
if category not in DATASET_CATEGORIES:
return gr.update(choices=[], value=[])
items = DATASET_CATEGORIES[category]
options = [f"{key}: {value}" for key, value in items.items()]
if select_all:
return gr.update(choices=options, value=options)
else:
return gr.update(choices=options, value=options[:1])
def update_metrics_choices(select_all):
if select_all:
return gr.update(value=available_metrics)
else:
return gr.update(value=["accuracy"])
def update_models_choices(select_all):
if select_all:
return gr.update(value=available_models)
else:
return gr.update(value=available_models[:2]) # default: first two models
def run_evaluation(selected_datasets, models, primary_metrics):
if not selected_datasets:
return ["Select at least one dataset"] + [None]*4 + [pd.DataFrame()]
if not models or not primary_metrics:
return ["Please select models and metrics"] + [None]*4 + [pd.DataFrame()]
if not isinstance(primary_metrics, list):
primary_metrics = [primary_metrics]
dataset_ids = [d.split(":")[0].strip() for d in selected_datasets]
# Map dataset ids to names
dataset_name_map = {key: name for cat, datasets in DATASET_CATEGORIES.items() for key, name in datasets.items()}
#only include rows that exist in both the selected datasets and selected models.
filtered = df[df['dataset'].isin(dataset_ids) & df['model'].isin(models)].copy()
if filtered.empty:
return ["No data available for selected datasets/models."] + [None]*4 + [pd.DataFrame()]
filtered['dataset_name'] = filtered['dataset'].map(lambda x: dataset_name_map.get(x, x))
figs = {}
num_datasets = len(dataset_ids)
for metric in primary_metrics:
if num_datasets <= 3:
fig = px.bar(
filtered,
x='dataset_name',
y=metric,
color='model',
barmode='group',
text=filtered[metric].round(3),
labels={'dataset_name': 'Dataset', metric: metric},
title=f"Model Performance: {metric}"
)
fig.update_yaxes(autorange=True)
fig.update_xaxes(autorange=True)
else:
pivot_table = filtered.pivot_table(index='dataset_name', columns='model', values=metric).round(3)
fig = px.imshow(
pivot_table,
text_auto=True,
labels={"color": metric},
title=f"Model Performance Heatmap: {metric}"
)
fig.update_xaxes(autorange=True)
fig.update_yaxes(autorange=True)
fig.update_traces(zmin=None, zmax=None)
figs[metric] = fig
test_results = []
for metric in primary_metrics:
for i, m1 in enumerate(models):
for j, m2 in enumerate(models):
if j <= i:
continue
scores1 = filtered[filtered['model'] == m1][metric].values
scores2 = filtered[filtered['model'] == m2][metric].values
if len(scores1) == 0 or len(scores2) == 0:
continue
t_stat, p_val = ttest_rel(scores1, scores2)
test_results.append({
"metric": metric,
"model A": m1,
"model B": m2,
"mean(A)": round(scores1.mean(), 4),
"mean(B)": round(scores2.mean(), 4),
"mean diff": round(scores1.mean() - scores2.mean(), 4),
"t-statistic": round(t_stat, 4),
"p-value": round(p_val, 4)
})
results_df = pd.DataFrame(test_results)
return [f"Generated {len(primary_metrics)} chart(s).",
figs.get("accuracy"), figs.get("precision"), figs.get("recall"), figs.get("f1_score"),
results_df]
# Build Gradio app
"""theme = Soft(
primary_hue="blue",
secondary_hue="pink",
font="poppins"
)"""
with gr.Blocks(title="Model Evaluation Platform") as demo:
gr.Markdown("## Model Evaluation Platform")
# Dataset selection
with gr.Group():
gr.Markdown("### 1. Select Datasets")
category_dropdown = gr.Dropdown(
choices=list(DATASET_CATEGORIES.keys()),
value=list(DATASET_CATEGORIES.keys())[0],
label="Category"
)
select_all_box = gr.Checkbox(label="Select ALL datasets in this category", value=False)
datasets_in_category = gr.CheckboxGroup(choices=[], label="Datasets", interactive=True)
# Model & metrics selection
with gr.Group():
gr.Markdown("### 2. Select Models & Metrics")
select_all_models = gr.Checkbox(label="Select ALL models", value=False)
models_input = gr.CheckboxGroup(choices=available_models, value=["RandomForest", "KNN"], label="Models")
select_all_metrics = gr.Checkbox(label="Select ALL metrics", value=False)
metric_input = gr.CheckboxGroup(choices=available_metrics, value=["accuracy"], label="Metrics")
run_button = gr.Button("Run Evaluation", variant="primary")
# Outputs
gr.Markdown(
"### Test Results Explanation\n"
"- **Mean(A)**: average metric score for Model A over the selected datasets\n"
"- **Mean(B)**: average metric score for Model B over the selected datasets\n"
"- **Mean Diff**: difference between Model A and Model B\n"
"- **t-statistic / p-value**: results of pairwise t-test"
)
with gr.Group():
gr.Markdown("### 3. Outputs")
output_text = gr.Textbox(label="Status")
with gr.Tabs() as output_tabs:
with gr.Tab("Accuracy"):
plot_accuracy = gr.Plot()
with gr.Tab("Precision"):
plot_precision = gr.Plot()
with gr.Tab("Recall"):
plot_recall = gr.Plot()
with gr.Tab("F1 Score"):
plot_f1 = gr.Plot()
output_table = gr.Dataframe(label="Test Results (t-test, p-values)", wrap=True)
category_dropdown.change(
fn=update_datasets_choices,
inputs=[category_dropdown, select_all_box],
outputs=datasets_in_category)
select_all_box.change(
fn=update_datasets_choices,
inputs=[category_dropdown, select_all_box],
outputs=datasets_in_category)
select_all_models.change(
fn=update_models_choices,
inputs=[select_all_models],
outputs=[models_input]
)
select_all_metrics.change(
fn=update_metrics_choices,
inputs=[select_all_metrics],
outputs=[metric_input])
run_button.click(fn=run_evaluation,
inputs=[datasets_in_category, models_input, metric_input],
outputs=[output_text, plot_accuracy, plot_precision, plot_recall, plot_f1, output_table])
demo.launch(debug=True)