Spaces:
Build error
Build error
Improve model controls and TabFM visibility
Browse files
README.md
CHANGED
|
@@ -42,7 +42,9 @@ The built-in catalog uses real open datasets where possible:
|
|
| 42 |
|
| 43 |
TabFM is loaded through the public Google Research package when available. The app keeps graceful fallbacks so the Space still works on CPU-only or dependency-constrained runtimes. Live TabFM runs are opt-in because the model weights are large and CPU-only inference can be slow.
|
| 44 |
|
| 45 |
-
Model choices include Logistic
|
|
|
|
|
|
|
| 46 |
|
| 47 |
Note: TabFM's weights use their own non-commercial license. Review the upstream model license before using this Space commercially.
|
| 48 |
|
|
|
|
| 42 |
|
| 43 |
TabFM is loaded through the public Google Research package when available. The app keeps graceful fallbacks so the Space still works on CPU-only or dependency-constrained runtimes. Live TabFM runs are opt-in because the model weights are large and CPU-only inference can be slow.
|
| 44 |
|
| 45 |
+
Model choices include Logistic, Linear Regression, Ridge, Bayesian Ridge, RandomForest, ExtraTrees, GradientBoosting, HistGradientBoosting, AdaBoost, KNN, SVC/SVR, XGBoost, LightGBM, Dummy, and optional live TabFM.
|
| 46 |
+
|
| 47 |
+
TabFM is always represented in the leaderboard: it appears as skipped until **Run TabFM live** is enabled, then reports live metrics when the run completes.
|
| 48 |
|
| 49 |
Note: TabFM's weights use their own non-commercial license. Review the upstream model license before using this Space commercially.
|
| 50 |
|
app.py
CHANGED
|
@@ -31,7 +31,7 @@ from sklearn.ensemble import (
|
|
| 31 |
RandomForestRegressor,
|
| 32 |
)
|
| 33 |
from sklearn.impute import SimpleImputer
|
| 34 |
-
from sklearn.linear_model import LogisticRegression, Ridge
|
| 35 |
from sklearn.metrics import (
|
| 36 |
accuracy_score,
|
| 37 |
f1_score,
|
|
@@ -734,19 +734,21 @@ def available_baselines(task: str) -> dict[str, object]:
|
|
| 734 |
"HistGradientBoosting": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", HistGradientBoostingClassifier(max_iter=120, random_state=RANDOM_STATE))]),
|
| 735 |
"AdaBoost": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", AdaBoostClassifier(n_estimators=80, learning_rate=0.08, random_state=RANDOM_STATE))]),
|
| 736 |
"KNN": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", KNeighborsClassifier(n_neighbors=7))]),
|
| 737 |
-
"
|
| 738 |
"Dummy": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", DummyClassifier(strategy="most_frequent"))]),
|
| 739 |
}
|
| 740 |
else:
|
| 741 |
models = {
|
|
|
|
| 742 |
"Ridge": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", Ridge(alpha=1.0))]),
|
|
|
|
| 743 |
"RandomForest": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", RandomForestRegressor(n_estimators=80, min_samples_leaf=2, n_jobs=-1, random_state=RANDOM_STATE))]),
|
| 744 |
"ExtraTrees": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", ExtraTreesRegressor(n_estimators=120, min_samples_leaf=2, n_jobs=-1, random_state=RANDOM_STATE))]),
|
| 745 |
"GradientBoosting": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", GradientBoostingRegressor(n_estimators=100, learning_rate=0.06, random_state=RANDOM_STATE))]),
|
| 746 |
"HistGradientBoosting": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", HistGradientBoostingRegressor(max_iter=120, random_state=RANDOM_STATE))]),
|
| 747 |
"AdaBoost": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", AdaBoostRegressor(n_estimators=80, learning_rate=0.08, random_state=RANDOM_STATE))]),
|
| 748 |
"KNN": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", KNeighborsRegressor(n_neighbors=7))]),
|
| 749 |
-
"
|
| 750 |
"Dummy": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", DummyRegressor(strategy="median"))]),
|
| 751 |
}
|
| 752 |
if importlib.util.find_spec("xgboost"):
|
|
@@ -889,6 +891,7 @@ def benchmark_frame(
|
|
| 889 |
|
| 890 |
rows: list[dict[str, object]] = []
|
| 891 |
notes: list[str] = []
|
|
|
|
| 892 |
models = available_baselines(task)
|
| 893 |
for name, model in models.items():
|
| 894 |
if name not in selected_models:
|
|
@@ -905,7 +908,7 @@ def benchmark_frame(
|
|
| 905 |
rows.append({"model": name, "status": f"failed: {exc}", "seconds": time.perf_counter() - start})
|
| 906 |
for name in selected_models:
|
| 907 |
if name not in models:
|
| 908 |
-
rows.append({"model": name, "status": "
|
| 909 |
|
| 910 |
if include_tabfm:
|
| 911 |
start = time.perf_counter()
|
|
@@ -931,6 +934,7 @@ def benchmark_frame(
|
|
| 931 |
notes.append(f"TabFM did not run in this environment. On Spaces, keep Python 3.11 and allow the GitHub dependency plus model download for `{TABFM_MODEL_ID}`.")
|
| 932 |
else:
|
| 933 |
rows.append({"model": "TabFM", "status": "skipped - enable Run TabFM live", "seconds": 0.0, "rank_score": np.nan})
|
|
|
|
| 934 |
|
| 935 |
results = pd.DataFrame(rows)
|
| 936 |
metric_cols = [c for c in ["accuracy", "f1_weighted", "roc_auc", "rmse", "mae", "r2", "rank_score", "seconds"] if c in results.columns]
|
|
@@ -1173,14 +1177,17 @@ def catalog_table() -> pd.DataFrame:
|
|
| 1173 |
|
| 1174 |
DEFAULT_MODELS = [
|
| 1175 |
"Logistic",
|
|
|
|
| 1176 |
"Ridge",
|
|
|
|
| 1177 |
"RandomForest",
|
| 1178 |
"ExtraTrees",
|
| 1179 |
"GradientBoosting",
|
| 1180 |
"HistGradientBoosting",
|
| 1181 |
"AdaBoost",
|
| 1182 |
"KNN",
|
| 1183 |
-
"
|
|
|
|
| 1184 |
"XGBoost",
|
| 1185 |
"LightGBM",
|
| 1186 |
"Dummy",
|
|
@@ -1200,7 +1207,14 @@ def build_app() -> gr.Blocks:
|
|
| 1200 |
.stat-card .value { font-size: 28px; font-weight: 760; margin-top: 12px; }
|
| 1201 |
.stat-card .trend { display: inline-block; margin-left: 8px; font-size: 12px; color: #027a48; background: #ecfdf3; border-radius: 999px; padding: 2px 8px; }
|
| 1202 |
.panel { background: #fff; border: 1px solid #edf0f5; border-radius: 14px; padding: 14px; box-shadow: 0 12px 35px rgba(15, 23, 42, 0.04); }
|
| 1203 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1204 |
footer { display: none !important; }
|
| 1205 |
"""
|
| 1206 |
with gr.Blocks(title=APP_TITLE, css=css, theme=gr.themes.Soft(primary_hue="orange", secondary_hue="violet")) as demo:
|
|
@@ -1220,14 +1234,14 @@ def build_app() -> gr.Blocks:
|
|
| 1220 |
with gr.Tabs():
|
| 1221 |
with gr.Tab("Arena"):
|
| 1222 |
with gr.Row():
|
| 1223 |
-
with gr.Column(scale=1, elem_classes=["panel"]):
|
| 1224 |
dataset = gr.Dropdown(dataset_names(), value="Titanic Survival", label="Dataset")
|
| 1225 |
sample = gr.Slider(100, 50000, value=1000, step=100, label="Sample size")
|
| 1226 |
test_pct = gr.Slider(10, 40, value=25, step=5, label="Test split (%)")
|
| 1227 |
seed = gr.Number(value=42, precision=0, label="Random seed")
|
| 1228 |
-
models = gr.
|
| 1229 |
include_tabfm = gr.Checkbox(value=False, label="Run TabFM live (adds TabFM row)")
|
| 1230 |
-
metric_toggles = gr.
|
| 1231 |
chart_style = gr.Radio(["Line", "Radar"], value="Line", label="Chart style")
|
| 1232 |
with gr.Accordion("TabFM tuning", open=False):
|
| 1233 |
tabfm_preset = gr.Dropdown(list(TABFM_PRESETS.keys()) + ["Custom"], value="Fast", label="Preset")
|
|
@@ -1275,16 +1289,16 @@ def build_app() -> gr.Blocks:
|
|
| 1275 |
demo.load(run_catalog, run_inputs, run_outputs)
|
| 1276 |
with gr.Tab("Upload Dataset"):
|
| 1277 |
with gr.Row():
|
| 1278 |
-
with gr.Column(scale=1, elem_classes=["panel"]):
|
| 1279 |
file = gr.File(label="CSV file", file_types=[".csv"])
|
| 1280 |
target = gr.Textbox(label="Target column")
|
| 1281 |
task = gr.Radio(["Auto", "Classification", "Regression"], value="Auto", label="Task")
|
| 1282 |
upload_sample = gr.Slider(100, 50000, value=1000, step=100, label="Sample size")
|
| 1283 |
upload_test_pct = gr.Slider(10, 40, value=25, step=5, label="Test split (%)")
|
| 1284 |
upload_seed = gr.Number(value=42, precision=0, label="Random seed")
|
| 1285 |
-
upload_models = gr.
|
| 1286 |
upload_tabfm = gr.Checkbox(value=False, label="Run TabFM live (adds TabFM row)")
|
| 1287 |
-
upload_metric_toggles = gr.
|
| 1288 |
upload_chart_style = gr.Radio(["Line", "Radar"], value="Line", label="Chart style")
|
| 1289 |
with gr.Accordion("TabFM tuning", open=False):
|
| 1290 |
upload_tabfm_preset = gr.Dropdown(list(TABFM_PRESETS.keys()) + ["Custom"], value="Fast", label="Preset")
|
|
|
|
| 31 |
RandomForestRegressor,
|
| 32 |
)
|
| 33 |
from sklearn.impute import SimpleImputer
|
| 34 |
+
from sklearn.linear_model import BayesianRidge, LinearRegression, LogisticRegression, Ridge
|
| 35 |
from sklearn.metrics import (
|
| 36 |
accuracy_score,
|
| 37 |
f1_score,
|
|
|
|
| 734 |
"HistGradientBoosting": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", HistGradientBoostingClassifier(max_iter=120, random_state=RANDOM_STATE))]),
|
| 735 |
"AdaBoost": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", AdaBoostClassifier(n_estimators=80, learning_rate=0.08, random_state=RANDOM_STATE))]),
|
| 736 |
"KNN": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", KNeighborsClassifier(n_neighbors=7))]),
|
| 737 |
+
"SVC": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", SVC(C=1.0, probability=True, random_state=RANDOM_STATE))]),
|
| 738 |
"Dummy": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", DummyClassifier(strategy="most_frequent"))]),
|
| 739 |
}
|
| 740 |
else:
|
| 741 |
models = {
|
| 742 |
+
"LinearRegression": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", LinearRegression())]),
|
| 743 |
"Ridge": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", Ridge(alpha=1.0))]),
|
| 744 |
+
"BayesianRidge": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", BayesianRidge())]),
|
| 745 |
"RandomForest": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", RandomForestRegressor(n_estimators=80, min_samples_leaf=2, n_jobs=-1, random_state=RANDOM_STATE))]),
|
| 746 |
"ExtraTrees": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", ExtraTreesRegressor(n_estimators=120, min_samples_leaf=2, n_jobs=-1, random_state=RANDOM_STATE))]),
|
| 747 |
"GradientBoosting": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", GradientBoostingRegressor(n_estimators=100, learning_rate=0.06, random_state=RANDOM_STATE))]),
|
| 748 |
"HistGradientBoosting": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", HistGradientBoostingRegressor(max_iter=120, random_state=RANDOM_STATE))]),
|
| 749 |
"AdaBoost": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", AdaBoostRegressor(n_estimators=80, learning_rate=0.08, random_state=RANDOM_STATE))]),
|
| 750 |
"KNN": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", KNeighborsRegressor(n_neighbors=7))]),
|
| 751 |
+
"SVR": Pipeline([("prep", make_preprocessor(pd.DataFrame(), True)), ("model", SVR(C=1.0))]),
|
| 752 |
"Dummy": Pipeline([("prep", make_preprocessor(pd.DataFrame())), ("model", DummyRegressor(strategy="median"))]),
|
| 753 |
}
|
| 754 |
if importlib.util.find_spec("xgboost"):
|
|
|
|
| 891 |
|
| 892 |
rows: list[dict[str, object]] = []
|
| 893 |
notes: list[str] = []
|
| 894 |
+
selected_models = selected_models or []
|
| 895 |
models = available_baselines(task)
|
| 896 |
for name, model in models.items():
|
| 897 |
if name not in selected_models:
|
|
|
|
| 908 |
rows.append({"model": name, "status": f"failed: {exc}", "seconds": time.perf_counter() - start})
|
| 909 |
for name in selected_models:
|
| 910 |
if name not in models:
|
| 911 |
+
rows.append({"model": name, "status": f"not compatible with {task} or unavailable", "seconds": 0.0, "rank_score": np.nan})
|
| 912 |
|
| 913 |
if include_tabfm:
|
| 914 |
start = time.perf_counter()
|
|
|
|
| 934 |
notes.append(f"TabFM did not run in this environment. On Spaces, keep Python 3.11 and allow the GitHub dependency plus model download for `{TABFM_MODEL_ID}`.")
|
| 935 |
else:
|
| 936 |
rows.append({"model": "TabFM", "status": "skipped - enable Run TabFM live", "seconds": 0.0, "rank_score": np.nan})
|
| 937 |
+
notes.append("TabFM is listed as skipped because **Run TabFM live** is off. Enable it to benchmark TabFM; the first run may download large model weights.")
|
| 938 |
|
| 939 |
results = pd.DataFrame(rows)
|
| 940 |
metric_cols = [c for c in ["accuracy", "f1_weighted", "roc_auc", "rmse", "mae", "r2", "rank_score", "seconds"] if c in results.columns]
|
|
|
|
| 1177 |
|
| 1178 |
DEFAULT_MODELS = [
|
| 1179 |
"Logistic",
|
| 1180 |
+
"LinearRegression",
|
| 1181 |
"Ridge",
|
| 1182 |
+
"BayesianRidge",
|
| 1183 |
"RandomForest",
|
| 1184 |
"ExtraTrees",
|
| 1185 |
"GradientBoosting",
|
| 1186 |
"HistGradientBoosting",
|
| 1187 |
"AdaBoost",
|
| 1188 |
"KNN",
|
| 1189 |
+
"SVC",
|
| 1190 |
+
"SVR",
|
| 1191 |
"XGBoost",
|
| 1192 |
"LightGBM",
|
| 1193 |
"Dummy",
|
|
|
|
| 1207 |
.stat-card .value { font-size: 28px; font-weight: 760; margin-top: 12px; }
|
| 1208 |
.stat-card .trend { display: inline-block; margin-left: 8px; font-size: 12px; color: #027a48; background: #ecfdf3; border-radius: 999px; padding: 2px 8px; }
|
| 1209 |
.panel { background: #fff; border: 1px solid #edf0f5; border-radius: 14px; padding: 14px; box-shadow: 0 12px 35px rgba(15, 23, 42, 0.04); }
|
| 1210 |
+
.control-panel { background: linear-gradient(180deg, #ffffff 0%, #fbfcff 100%); border-top: 4px solid #f97316; }
|
| 1211 |
+
.control-panel label span { color: #344054; font-weight: 720; }
|
| 1212 |
+
.control-panel input, .control-panel textarea, .control-panel select { border-radius: 10px !important; }
|
| 1213 |
+
.control-panel .wrap { gap: 9px !important; }
|
| 1214 |
+
.control-panel .token, .control-panel [data-testid="token"] { background: #fff7ed !important; color: #c2410c !important; border: 1px solid #fed7aa !important; border-radius: 999px !important; }
|
| 1215 |
+
.control-panel .checkbox label { border-radius: 999px !important; }
|
| 1216 |
+
.gr-button-primary { background: linear-gradient(135deg, #f97316, #ea4335) !important; border-color: #f97316 !important; box-shadow: 0 12px 24px rgba(249, 115, 22, 0.25) !important; border-radius: 12px !important; min-height: 46px !important; font-weight: 760 !important; }
|
| 1217 |
+
.plot-container, .table-wrap { border-radius: 14px !important; overflow: hidden; }
|
| 1218 |
footer { display: none !important; }
|
| 1219 |
"""
|
| 1220 |
with gr.Blocks(title=APP_TITLE, css=css, theme=gr.themes.Soft(primary_hue="orange", secondary_hue="violet")) as demo:
|
|
|
|
| 1234 |
with gr.Tabs():
|
| 1235 |
with gr.Tab("Arena"):
|
| 1236 |
with gr.Row():
|
| 1237 |
+
with gr.Column(scale=1, elem_classes=["panel", "control-panel"]):
|
| 1238 |
dataset = gr.Dropdown(dataset_names(), value="Titanic Survival", label="Dataset")
|
| 1239 |
sample = gr.Slider(100, 50000, value=1000, step=100, label="Sample size")
|
| 1240 |
test_pct = gr.Slider(10, 40, value=25, step=5, label="Test split (%)")
|
| 1241 |
seed = gr.Number(value=42, precision=0, label="Random seed")
|
| 1242 |
+
models = gr.Dropdown(DEFAULT_MODELS, value=DEFAULT_SELECTED_MODELS, multiselect=True, label="Models")
|
| 1243 |
include_tabfm = gr.Checkbox(value=False, label="Run TabFM live (adds TabFM row)")
|
| 1244 |
+
metric_toggles = gr.Dropdown(METRIC_CHOICES, value=["rmse", "mae", "r2", "accuracy", "f1_weighted", "roc_auc"], multiselect=True, label="Chart metrics")
|
| 1245 |
chart_style = gr.Radio(["Line", "Radar"], value="Line", label="Chart style")
|
| 1246 |
with gr.Accordion("TabFM tuning", open=False):
|
| 1247 |
tabfm_preset = gr.Dropdown(list(TABFM_PRESETS.keys()) + ["Custom"], value="Fast", label="Preset")
|
|
|
|
| 1289 |
demo.load(run_catalog, run_inputs, run_outputs)
|
| 1290 |
with gr.Tab("Upload Dataset"):
|
| 1291 |
with gr.Row():
|
| 1292 |
+
with gr.Column(scale=1, elem_classes=["panel", "control-panel"]):
|
| 1293 |
file = gr.File(label="CSV file", file_types=[".csv"])
|
| 1294 |
target = gr.Textbox(label="Target column")
|
| 1295 |
task = gr.Radio(["Auto", "Classification", "Regression"], value="Auto", label="Task")
|
| 1296 |
upload_sample = gr.Slider(100, 50000, value=1000, step=100, label="Sample size")
|
| 1297 |
upload_test_pct = gr.Slider(10, 40, value=25, step=5, label="Test split (%)")
|
| 1298 |
upload_seed = gr.Number(value=42, precision=0, label="Random seed")
|
| 1299 |
+
upload_models = gr.Dropdown(DEFAULT_MODELS, value=DEFAULT_SELECTED_MODELS, multiselect=True, label="Models")
|
| 1300 |
upload_tabfm = gr.Checkbox(value=False, label="Run TabFM live (adds TabFM row)")
|
| 1301 |
+
upload_metric_toggles = gr.Dropdown(METRIC_CHOICES, value=["rmse", "mae", "r2", "accuracy", "f1_weighted", "roc_auc"], multiselect=True, label="Chart metrics")
|
| 1302 |
upload_chart_style = gr.Radio(["Line", "Radar"], value="Line", label="Chart style")
|
| 1303 |
with gr.Accordion("TabFM tuning", open=False):
|
| 1304 |
upload_tabfm_preset = gr.Dropdown(list(TABFM_PRESETS.keys()) + ["Custom"], value="Fast", label="Preset")
|