Spaces:
Sleeping
GUI 1
Browse filesCup Use Type Predictor: Machine Learning Classification
This application provides a user-friendly interface for predicting the intended primary use of a container (cup, mug, or glass)—specifically, whether it is designed for Hot or Cold beverages.
How It Works:
The prediction is powered by a pre-trained AutoGluon machine learning model. This model was trained on a dataset of various containers and learned to distinguish between "Hot" and "Cold" use based purely on physical characteristics.
The model is deployed from the Hugging Face Model Hub and loaded directly into the application environment for real-time inference.
Required Inputs:
To receive a prediction, you must input five distinct physical properties of the container:
• Capacity (ml): The maximum volume the container can hold.
• Height (cm): The overall height of the container.
• Diameter (cm): The width of the container (likely measured at the rim or widest point).
• Weight (g): The mass of the empty container.
• Material: The primary material composition (e.g., Ceramic, Glass, Plastic, or Stainless Steel).
• The application outputs the predicted class (Hot or Cold) and the confidence scores (probabilities) for each outcome.
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import shutil
|
| 3 |
+
import zipfile
|
| 4 |
+
import pathlib
|
| 5 |
+
import pandas as pd
|
| 6 |
+
import gradio as gr
|
| 7 |
+
import huggingface_hub
|
| 8 |
+
import autogluon.tabular as agt
|
| 9 |
+
|
| 10 |
+
# --- Settings and Metadata ---
|
| 11 |
+
MODEL_REPO_ID = "bcueva/2024-24679-tabular-autolguon-predictor"
|
| 12 |
+
ZIP_FILENAME = "autogluon_predictor_dir.zip"
|
| 13 |
+
CACHE_DIR = pathlib.Path("hf_assets")
|
| 14 |
+
EXTRACT_DIR = CACHE_DIR / "predictor_native"
|
| 15 |
+
|
| 16 |
+
# Features for the model
|
| 17 |
+
FEATURE_COLS = [
|
| 18 |
+
"Capacity_ml",
|
| 19 |
+
"Height_cm",
|
| 20 |
+
"Diameter_cm",
|
| 21 |
+
"Weight_g",
|
| 22 |
+
"Material",
|
| 23 |
+
]
|
| 24 |
+
|
| 25 |
+
# The target variable to be predicted
|
| 26 |
+
TARGET_COL = "Use_Type"
|
| 27 |
+
|
| 28 |
+
# Define the possible values for the 'Material' feature
|
| 29 |
+
MATERIAL_LABELS = [
|
| 30 |
+
"Ceramic",
|
| 31 |
+
"Glass",
|
| 32 |
+
"Plastic",
|
| 33 |
+
"Stainless Steel",
|
| 34 |
+
|
| 35 |
+
]
|
| 36 |
+
|
| 37 |
+
# Mapping the integer labels back to human-readable labels for the 'Use_Type' prediction
|
| 38 |
+
# These labels are based on the model's training data.
|
| 39 |
+
OUTCOME_LABELS = {
|
| 40 |
+
0: "Hot",
|
| 41 |
+
1: "Cold",
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
# --- Model Loading ---
|
| 45 |
+
def _prepare_predictor_dir() -> str:
|
| 46 |
+
"""Downloads and extracts the model files from Hugging Face."""
|
| 47 |
+
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
| 48 |
+
local_zip = huggingface_hub.hf_hub_download(
|
| 49 |
+
repo_id=MODEL_REPO_ID,
|
| 50 |
+
filename=ZIP_FILENAME,
|
| 51 |
+
repo_type="model",
|
| 52 |
+
local_dir=str(CACHE_DIR),
|
| 53 |
+
local_dir_use_symlinks=False,
|
| 54 |
+
)
|
| 55 |
+
if EXTRACT_DIR.exists():
|
| 56 |
+
shutil.rmtree(EXTRACT_DIR)
|
| 57 |
+
EXTRACT_DIR.mkdir(parents=True, exist_ok=True)
|
| 58 |
+
with zipfile.ZipFile(local_zip, "r") as zf:
|
| 59 |
+
zf.extractall(str(EXTRACT_DIR))
|
| 60 |
+
contents = list(EXTRACT_DIR.iterdir())
|
| 61 |
+
predictor_root = contents[0] if (len(contents) == 1 and contents[0].is_dir()) else EXTRACT_DIR
|
| 62 |
+
return str(predictor_root)
|
| 63 |
+
|
| 64 |
+
PREDICTOR_DIR = _prepare_predictor_dir()
|
| 65 |
+
PREDICTOR = agt.TabularPredictor.load(PREDICTOR_DIR, require_py_version_match=False)
|
| 66 |
+
|
| 67 |
+
# --- Prediction Function ---
|
| 68 |
+
def _human_label(c):
|
| 69 |
+
"""Maps the model's numerical output to a human-readable label."""
|
| 70 |
+
try:
|
| 71 |
+
ci = int(c)
|
| 72 |
+
if ci in OUTCOME_LABELS:
|
| 73 |
+
return OUTCOME_LABELS[ci]
|
| 74 |
+
except (ValueError, TypeError):
|
| 75 |
+
pass
|
| 76 |
+
if c in OUTCOME_LABELS:
|
| 77 |
+
return OUTCOME_LABELS[c]
|
| 78 |
+
return str(c)
|
| 79 |
+
|
| 80 |
+
def do_predict(capacity_ml, height_cm, diameter_cm, weight_g, material):
|
| 81 |
+
"""
|
| 82 |
+
Takes user input, formats it for the model, and returns a prediction.
|
| 83 |
+
'Cup_ID' is excluded as per the user request.
|
| 84 |
+
"""
|
| 85 |
+
# Create a DataFrame for a single prediction
|
| 86 |
+
# 'Cup_ID' is included as a placeholder with a dummy value (e.g., 0)
|
| 87 |
+
# because the model's training data included it.
|
| 88 |
+
row = {
|
| 89 |
+
"Cup_ID": 0, # Dummy value
|
| 90 |
+
"Capacity_ml": capacity_ml,
|
| 91 |
+
"Height_cm": height_cm,
|
| 92 |
+
"Diameter_cm": diameter_cm,
|
| 93 |
+
"Weight_g": weight_g,
|
| 94 |
+
"Material": material,
|
| 95 |
+
}
|
| 96 |
+
X = pd.DataFrame([row])
|
| 97 |
+
|
| 98 |
+
# Get the raw prediction and its label
|
| 99 |
+
pred_series = PREDICTOR.predict(X)
|
| 100 |
+
raw_pred = pred_series.iloc[0]
|
| 101 |
+
pred_label = _human_label(raw_pred)
|
| 102 |
+
|
| 103 |
+
# Get prediction probabilities
|
| 104 |
+
try:
|
| 105 |
+
proba = PREDICTOR.predict_proba(X)
|
| 106 |
+
if isinstance(proba, pd.Series):
|
| 107 |
+
proba = proba.to_frame().T
|
| 108 |
+
|
| 109 |
+
# Format probabilities into a dictionary for Gradio
|
| 110 |
+
proba_dict = {
|
| 111 |
+
_human_label(cls): float(val) for cls, val in proba.iloc[0].items()
|
| 112 |
+
}
|
| 113 |
+
proba_dict = dict(sorted(proba_dict.items(), key=lambda kv: kv[1], reverse=True))
|
| 114 |
+
|
| 115 |
+
except Exception as e:
|
| 116 |
+
print(f"Could not get probabilities: {e}")
|
| 117 |
+
proba_dict = None
|
| 118 |
+
|
| 119 |
+
return proba_dict
|
| 120 |
+
|
| 121 |
+
# --- Gradio UI ---
|
| 122 |
+
with gr.Blocks(fill_height=True) as demo:
|
| 123 |
+
gr.Markdown("# Cup Use Predictor ☕️")
|
| 124 |
+
gr.Markdown("""
|
| 125 |
+
Enter the physical properties of a cup to predict its intended use type (Hot or Cold).
|
| 126 |
+
This app uses a pre-trained **AutoGluon** model to classify the cup's purpose.
|
| 127 |
+
""")
|
| 128 |
+
|
| 129 |
+
with gr.Column():
|
| 130 |
+
material = gr.Radio(choices=MATERIAL_LABELS, value="Ceramic", label="Material")
|
| 131 |
+
|
| 132 |
+
with gr.Row():
|
| 133 |
+
with gr.Column():
|
| 134 |
+
capacity_ml = gr.Number(value=350, label="Capacity (ml)")
|
| 135 |
+
height_cm = gr.Number(value=10.0, label="Height (cm)")
|
| 136 |
+
|
| 137 |
+
with gr.Column():
|
| 138 |
+
diameter_cm = gr.Number(value=8.0, label="Diameter (cm)")
|
| 139 |
+
weight_g = gr.Number(value=250, label="Weight (g)")
|
| 140 |
+
|
| 141 |
+
predict_btn = gr.Button("Predict Use Type")
|
| 142 |
+
output_label = gr.Label(num_top_classes=2, label="Prediction")
|
| 143 |
+
|
| 144 |
+
inputs = [capacity_ml, height_cm, diameter_cm, weight_g, material]
|
| 145 |
+
|
| 146 |
+
predict_btn.click(fn=do_predict, inputs=inputs, outputs=output_label)
|
| 147 |
+
|
| 148 |
+
gr.Examples(
|
| 149 |
+
examples=[
|
| 150 |
+
[478, 8, 7.7, 315, "Ceramic"], # Example for a coffee mug (likely 'Hot')
|
| 151 |
+
[442, 13.8, 6.4, 155, "Glass"], # Example for a tall drinking glass (likely 'Cold')
|
| 152 |
+
[392, 18, 5.7, 61, "Plastic"], # Example for a small tea cup (likely 'Hot')
|
| 153 |
+
[302, 17.5, 5.5, 783, "Stainless Steel"], # Example for a disposable soda cup (likely 'Cold')
|
| 154 |
+
],
|
| 155 |
+
inputs=inputs,
|
| 156 |
+
label="Representative Examples",
|
| 157 |
+
examples_per_page=5,
|
| 158 |
+
)
|
| 159 |
+
|
| 160 |
+
if __name__ == "__main__":
|
| 161 |
+
demo.launch()
|