Wine_Quality / src /streamlit_app.py
jalesummak's picture
Build quality and price prediction hub
27f9837 verified
Raw
History Blame Contribute Delete
5.22 kB
import os
import joblib
import numpy as np
import pandas as pd
import streamlit as st
st.set_page_config(page_title="Quality & Price Prediction", page_icon="💎", layout="wide")
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@st.cache_resource
def load_models():
return {
"wine": joblib.load(os.path.join(ROOT, "wine_model.pkl")),
"wine_columns": joblib.load(os.path.join(ROOT, "feature_columns.pkl")),
"diamond": joblib.load(os.path.join(ROOT, "diamond_bundle.pkl")),
"tips": joblib.load(os.path.join(ROOT, "waiter_tip_bundle.joblib")),
}
models = load_models()
st.title("💎 Quality & Price Prediction Hub")
st.caption("Three trained regression and classification projects with practical input forms.")
wine_tab, diamond_tab, tip_tab = st.tabs(["Wine Quality", "Diamond Price", "Waiter Tip"])
with wine_tab:
st.subheader("Predict wine quality from laboratory measurements")
a, b, c = st.columns(3)
wine_values = {
"fixed acidity": a.number_input("Fixed acidity", 3.0, 20.0, 8.0, .1),
"volatile acidity": a.number_input("Volatile acidity", 0.0, 2.0, .5, .01),
"citric acid": a.number_input("Citric acid", 0.0, 2.0, .3, .01),
"residual sugar": a.number_input("Residual sugar", 0.0, 70.0, 2.5, .1),
"chlorides": b.number_input("Chlorides", 0.0, 1.0, .08, .005, format="%.3f"),
"free sulfur dioxide": b.number_input("Free sulfur dioxide", 0.0, 300.0, 15.0, 1.0),
"total sulfur dioxide": b.number_input("Total sulfur dioxide", 0.0, 500.0, 46.0, 1.0),
"density": b.number_input("Density", .98, 1.05, .9968, .0001, format="%.4f"),
"pH": c.number_input("pH", 2.0, 5.0, 3.3, .01),
"sulphates": c.number_input("Sulphates", 0.0, 3.0, .65, .01),
"alcohol": c.number_input("Alcohol (%)", 5.0, 25.0, 10.5, .1),
}
if st.button("Predict wine quality", type="primary"):
row = pd.DataFrame([{**{"Id": 0}, **wine_values}]).reindex(columns=models["wine_columns"], fill_value=0)
quality = int(models["wine"].predict(row)[0])
st.metric("Predicted quality", f"{quality} / 10")
st.success("High-quality profile") if quality >= 7 else st.info("Typical-quality profile" if quality >= 5 else "Lower-quality profile")
with diamond_tab:
st.subheader("Estimate a diamond's price in US dollars")
cut_map = {"Fair": 1, "Good": 2, "Very Good": 3, "Premium": 4, "Ideal": 5}
color_map = {"J": 1, "I": 2, "H": 3, "G": 4, "F": 5, "E": 6, "D": 7}
clarity_map = {"I1": 1, "SI2": 2, "SI1": 3, "VS2": 4, "VS1": 5, "VVS2": 6, "VVS1": 7, "IF": 8}
a, b, c = st.columns(3)
carat = a.number_input("Carat", .1, 6.0, 1.0, .05)
depth = a.number_input("Depth (%)", 40.0, 80.0, 61.5, .1)
table = a.number_input("Table (%)", 40.0, 100.0, 57.0, .1)
x = b.number_input("Length x (mm)", 1.0, 15.0, 6.4, .1)
y = b.number_input("Width y (mm)", 1.0, 15.0, 6.4, .1)
z = b.number_input("Depth z (mm)", .5, 10.0, 4.0, .1)
cut = c.selectbox("Cut", list(cut_map), index=4)
color = c.selectbox("Color", list(color_map), index=3)
clarity = c.selectbox("Clarity", list(clarity_map), index=3)
if st.button("Estimate diamond price", type="primary"):
values = {"carat": carat, "depth": depth, "table": table, "x": x, "y": y, "z": z, "volume": x*y*z, "color_ord": color_map[color], "clarity_ord": clarity_map[clarity], "cut_ord": cut_map[cut]}
row = pd.DataFrame([values], columns=models["diamond"]["columns"])
price = max(0.0, float(models["diamond"]["model"].predict(row)[0]))
st.metric("Estimated price", f"${price:,.0f}")
st.caption("Educational estimate based on the training dataset; laboratory certification and market conditions also affect real prices.")
with tip_tab:
st.subheader("Estimate a restaurant tip")
a, b = st.columns(2)
bill = a.number_input("Total bill ($)", 1.0, 500.0, 35.0, 1.0)
party = a.slider("Party size", 1, 10, 2)
sex = a.selectbox("Customer sex (dataset field)", ["Female", "Male"])
smoker = b.selectbox("Smoking table", ["No", "Yes"])
day = b.selectbox("Day", ["Thursday", "Friday", "Saturday", "Sunday"])
meal = b.selectbox("Meal", ["Dinner", "Lunch"])
if st.button("Estimate tip", type="primary"):
day_code = {"Friday": 0, "Saturday": 1, "Sunday": 2, "Thursday": 3}[day]
weekend = int(day in ["Friday", "Saturday", "Sunday"])
smoker_code = int(smoker == "Yes")
values = {"total_bill": bill, "sex": int(sex == "Male"), "smoker": smoker_code, "day": day_code, "time": int(meal == "Lunch"), "size": party, "is_weekend": weekend, "is_smoker": smoker_code, "is_dinner": int(meal == "Dinner"), "bill_x_size": bill*party, "smoker_weekend": smoker_code*weekend}
row = pd.DataFrame([values], columns=models["tips"]["features"])
tip = max(0.0, float(models["tips"]["model"].predict(row)[0]))
st.metric("Estimated tip", f"${tip:.2f}", f"{tip/bill:.1%} of bill")
st.caption("Model validation MAE: approximately $0.75 on the small 244-row tips dataset.")
st.divider()
st.caption("Portfolio of Jale Summak · Educational machine-learning estimates")