File size: 3,971 Bytes
eb2c20c
 
 
 
 
 
ccef639
f5e3de1
c2619eb
f5e3de1
 
 
356232b
8b1cad2
356232b
8b1cad2
eb2c20c
f5e3de1
 
 
eb2c20c
356232b
fa67250
eb2c20c
356232b
 
ccef639
 
 
8b1cad2
356232b
 
 
ccef639
 
356232b
ccef639
356232b
eb2c20c
4783cc7
 
 
 
 
 
 
 
 
f5e3de1
2b84539
f5e3de1
eb2c20c
 
ccef639
 
eb2c20c
ccef639
eb2c20c
 
ccef639
8b1cad2
 
2b84539
eb2c20c
11c0b77
 
eb2c20c
4783cc7
11c0b77
 
 
 
 
4783cc7
 
11c0b77
 
4783cc7
f5e3de1
11c0b77
 
 
 
 
eb2c20c
 
f5e3de1
eb2c20c
 
2b84539
f5e3de1
 
2b84539
f5e3de1
 
2b84539
f5e3de1
2b84539
f5e3de1
 
 
2b84539
f5e3de1
 
 
 
 
2b84539
f5e3de1
2b84539
 
 
 
 
f5e3de1
 
 
 
 
 
 
4783cc7
 
 
f5e3de1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import gradio as gr
import pandas as pd
import numpy as np
from PIL import Image
import os
import time
import cloudpickle
import traceback

# =========================
# Configuration
# =========================
IMAGE_SIZE = (64, 64)
LEADERBOARD_PATH = "leaderboard.csv"
LABEL_FILE = "labels.csv"
TEST_DIR = "test_images"

# =========================
# Helpers
# =========================
def image_to_features(image: Image.Image) -> np.ndarray:
    image = image.resize(IMAGE_SIZE)
    return np.array(image.convert("L")).flatten()

def load_test_data():
    if not os.path.exists(LABEL_FILE) or not os.path.exists(TEST_DIR):
        raise FileNotFoundError("Missing labels.csv or test_images/ folder.")
    df = pd.read_csv(LABEL_FILE)
    X_test, y_test = [], []
    for _, row in df.iterrows():
        img_path = os.path.join(TEST_DIR, row["filename"])
        try:
            img = Image.open(img_path)
            X_test.append(image_to_features(img))
            y_test.append(row["label"])
        except Exception as e:
            print(f"❌ Error loading {img_path}: {e}")
    return np.array(X_test), np.array(y_test)

def load_leaderboard():
    if os.path.exists(LEADERBOARD_PATH):
        df = pd.read_csv(LEADERBOARD_PATH)
        return df.sort_values(by=["Accuracy", "Avg Time (ms)"], ascending=[False, True]).reset_index(drop=True)
    else:
        df = pd.DataFrame(columns=["Name", "Accuracy", "Avg Time (ms)"])
        df.to_csv(LEADERBOARD_PATH, index=False)
        return df

# =========================
# Evaluation Logic
# =========================
def evaluate_model(file, name):
    try:
        with open(file.name, "rb") as f:
            model = cloudpickle.load(f)

        X_test, y_test = load_test_data()
        start = time.time()
        y_pred = model.predict(X_test)
        elapsed = (time.time() - start) * 1000

        if len(y_pred) != len(y_test):
            return "❌ Model output length does not match test set.", load_leaderboard()

        accuracy = round(100.0 * (y_pred == y_test).mean(), 5)
        avg_time = round(elapsed / len(X_test), 5)

        leaderboard = load_leaderboard()

        # Remove existing entries for the same name
        leaderboard = leaderboard[leaderboard["Name"] != name]

        # Add new result
        new_entry = pd.DataFrame([{
            "Name": name,
            "Accuracy": accuracy,
            "Avg Time (ms)": avg_time
        }])
        leaderboard = pd.concat([leaderboard, new_entry], ignore_index=True)

        # Keep only the best score per name
        leaderboard = leaderboard.sort_values(by=["Accuracy", "Avg Time (ms)"], ascending=[False, True])
        leaderboard = leaderboard.drop_duplicates(subset=["Name"], keep="first").reset_index(drop=True)

        leaderboard.to_csv(LEADERBOARD_PATH, index=False)

        return "", leaderboard

    except Exception as e:
        return f"❌ Error:\n{traceback.format_exc()}", load_leaderboard()

# =========================
# UI
# =========================
with gr.Blocks(title="Olive Fly Classifier Leaderboard") as demo:
    gr.Markdown("## Olive Fly Classifier Leaderboard")
    gr.Markdown(
        "Upload your `.cloudpkl` model trained on Olive Fly images. "
        "We'll evaluate it and update the leaderboard."
    )

    with gr.Row():
        with gr.Column(scale=1):
            file_input = gr.File(label="Upload your model")
            name_input = gr.Text(label="Your name or team")
            submit_btn = gr.Button("Submit model")

    error_box = gr.Textbox(label="Output log", visible=True)

    leaderboard_table = gr.Dataframe(
        label="Leaderboard",
        interactive=False,
        wrap=True
    )

    submit_btn.click(
        fn=evaluate_model,
        inputs=[file_input, name_input],
        outputs=[error_box, leaderboard_table]
    )

    # Refresh leaderboard on app launch
    demo.load(fn=load_leaderboard, inputs=[], outputs=[leaderboard_table])

demo.launch()