HW3_Part1 / app.py
emkessle's picture
Update app.py
7aefc0c verified
import os # For filesystem operations
import shutil # For directory cleanup
import zipfile # For extracting model archives
import pathlib # For path manipulations
import pandas # For tabular data handling
import gradio # For interactive UI
import huggingface_hub # For downloading model assets
import autogluon.tabular # For loading and running AutoGluon predictors
# Settings
MODEL_REPO_ID = "its-zion-18/flowers-tabular-autolguon-predictor"
ZIP_FILENAME = "autogluon_predictor_dir.zip"
CACHE_DIR = pathlib.Path("hf_assets")
EXTRACT_DIR = CACHE_DIR / "predictor_native"
# Feature column names and target column names
FEATURE_COLS = [
"flower_diameter_cm",
"petal_length_cm",
"petal_width_cm",
"petal_count",
"stem_height_cm"
]
TARGET_COL = "color"
# Encoding for outcome questions
OUTCOME_LABELS = {
0: "Pink",
1: "Red",
2: "Orange",
3: "White",
4: "Yellow",
5: "Purple",
}
# Download & load the native predictor
def _prepare_predictor_dir() -> str:
CACHE_DIR.mkdir(parents=True, exist_ok=True)
local_zip = huggingface_hub.hf_hub_download(
repo_id=MODEL_REPO_ID,
filename=ZIP_FILENAME,
repo_type="model",
local_dir=str(CACHE_DIR),
local_dir_use_symlinks=False,
)
if EXTRACT_DIR.exists():
shutil.rmtree(EXTRACT_DIR)
EXTRACT_DIR.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(local_zip, "r") as zf:
zf.extractall(str(EXTRACT_DIR))
contents = list(EXTRACT_DIR.iterdir())
predictor_root = contents[0] if (len(contents) == 1 and contents[0].is_dir()) else EXTRACT_DIR
return str(predictor_root)
PREDICTOR_DIR = _prepare_predictor_dir()
PREDICTOR = autogluon.tabular.TabularPredictor.load(PREDICTOR_DIR, require_py_version_match=False)
# A mapping utility to make it easier to encode the variables
def _human_label(c):
try:
ci = int(c)
if ci in OUTCOME_LABELS:
return OUTCOME_LABELS[ci]
except Exception:
pass
if c in OUTCOME_LABELS:
return OUTCOME_LABELS[c]
return str(c)
# This functions takes all of our features,e ncodes this accordingly, and performs a predictions
def do_predict(diameter, length, width, number, height):
row = {
FEATURE_COLS[0]: float(diameter),
FEATURE_COLS[1]: float(length),
FEATURE_COLS[2]: float(width),
FEATURE_COLS[3]: int(number),
FEATURE_COLS[4]: float(height),
}
X = pandas.DataFrame([row], columns=FEATURE_COLS)
pred_series = PREDICTOR.predict(X)
raw_pred = pred_series.iloc[0]
try:
proba = PREDICTOR.predict_proba(X)
if isinstance(proba, pandas.Series):
proba = proba.to_frame().T
except Exception:
proba = None
pred_label = _human_label(raw_pred)
proba_dict = None
if proba is not None:
row0 = proba.iloc[0]
tmp = {}
for cls, val in row0.items():
key = _human_label(cls)
tmp[key] = float(val) + float(tmp.get(key, 0.0))
proba_dict = dict(sorted(tmp.items(), key=lambda kv: kv[1], reverse=True))
df_out = pandas.DataFrame([{
"Predicted outcome": pred_label,
"Confidence (%)": round((proba_dict.get(pred_label, 1.0) if proba_dict else 1.0) * 100, 2),
}])
md = f"**Prediction:** {pred_label}"
if proba_dict:
md += f" \n**Confidence:** {round(proba_dict.get(pred_label, 0.0) * 100, 2)}%"
return proba_dict
# Representative examples
EXAMPLES = [
[3.4, 1.3, 1, 7, 68.7],
[5.7, 3.2, 0.9, 5, 21.2],
[6.9, 3.8, 0.6, 17, 64.2],
[5.6, 1, 1.5, 7, 73.4, ],
[7.7, 1.5, 1.8, 13, 73.8],
]
# Gradio UI
with gradio.Blocks() as demo:
# Provide an introduction
gradio.Markdown("# What Color is the Flower?")
gradio.Markdown("""
This is a simple app that uses the model at its-zion-18/flowers-tabular-autolguon-predictor
to predict the color of a flower based off its characteristics, utilizing data found at
scottymcgee/flowers. To use the interface, make
selections using the interface elements shown below.
""")
with gradio.Row():
diameter = gradio.Slider(3, 10, step=0.1, value=5.0, label=FEATURE_COLS[0])
length = gradio.Slider(1, 5, step=0.1, value=3.0, label=FEATURE_COLS[1])
width = gradio.Slider(0.5, 2, step=0.1, value=1.0, label=FEATURE_COLS[2])
with gradio.Row():
number = gradio.Slider(5, 30, step=1, value=15, label=FEATURE_COLS[3])
height = gradio.Slider(10, 80, step=0.1, value=50.0, label=FEATURE_COLS[4])
proba_pretty = gradio.Label(num_top_classes=5, label="Class probabilities")
inputs = [diameter, length, width, number, height]
for comp in inputs:
comp.change(fn=do_predict, inputs=inputs, outputs=[proba_pretty])
gradio.Examples(
examples=EXAMPLES,
inputs=inputs,
label="Representative examples",
examples_per_page=5,
cache_examples=False,
)
if __name__ == "__main__":
demo.launch()