Spaces:
Sleeping
Sleeping
File size: 6,960 Bytes
a7eecd2 2f1b44f a7eecd2 d130bc1 a7eecd2 994dec4 a7eecd2 994dec4 a7eecd2 5b4d4a5 a7eecd2 2f1b44f a7eecd2 95708f1 | 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 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
# -------------------------- Page Config --------------------------
st.set_page_config(
page_title="Wine Quality Master π·",
page_icon="π",
layout="centered",
initial_sidebar_state="expanded"
)
# -------------------------- Custom CSS - Dark Purple Magic --------------------------
st.markdown("""
<style>
.main {background: #0f001a; color: #e6e6fa;}
.stApp {background: linear-gradient(135deg, #2a0052, #000000);}
h1, h2 {background: linear-gradient(90deg, #9b59b6, #e91e63, #ff9800);
-webkit-background-clip: text; -webkit-text-fill-color: transparent;}
.wine-red {color: #c0392b;}
.wine-white {color: #f1c40f;}
.prediction-good {font-size: 2.5rem; font-weight: bold; text-align: center;
color: #8e44ad; text-shadow: 0 0 20px #9b59b6;}
</style>
""", unsafe_allow_html=True)
# -------------------------- Load Full Wine Quality Dataset (Red + White) --------------------------
@st.cache_data
def load_wine_data():
# Red wine
red = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", sep=";")
red["type"] = "Red"
# White wine
white = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv", sep=";")
white["type"] = "White"
# Combine
df = pd.concat([red, white], ignore_index=True)
# Binary classification: Good (>=6), Bad (<6)
df["is_good"] = (df["quality"] >= 6).astype(int)
return df
df = load_wine_data()
# -------------------------- Hero Section --------------------------
col1, col2, col3 = st.columns([1,3,1])
with col2:
st.markdown("<h1 style='text-align:center;'>Wine Quality Master</h1>", unsafe_allow_html=True)
st.markdown("<h2 style='text-align:center;'>VinoVerdict</h2>", unsafe_allow_html=True)
st.markdown("<p style='text-align:center; font-size:1.4rem; opacity:0.9;'>Red or White β Will it be divine... or declined?</p>", unsafe_allow_html=True)
st.markdown("---")
# -------------------------- Dataset Info --------------------------
with st.container():
st.markdown("<div class='glass-card'>", unsafe_allow_html=True)
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Total Wines", f"{len(df):,}")
with col2:
st.metric("Red Wines", f"{len(df[df['type']=='Red']):,}", "Red Wine")
with col3:
st.metric("White Wines", f"{len(df[df['type']=='White']):,}", "White Wine")
with col4:
st.metric("Good Wines (β₯6)", f"{df['is_good'].sum():,}")
st.markdown("<br>", unsafe_allow_html=True)
st.dataframe(df.head(), use_container_width=True)
st.markdown("</div>", unsafe_allow_html=True)
# -------------------------- Prepare Features --------------------------
X = df.drop(columns=["quality", "is_good"])
y = df["is_good"]
# One-hot encode wine type (ensures consistent column order)
X = pd.get_dummies(X, columns=["type"], drop_first=False)
# Train-test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# Scale numerical features (preserve exact column order)
scaler = StandardScaler()
numerical_cols = [col for col in X.columns if col not in ["type_Red", "type_White"]]
X_train_num_scaled = scaler.fit_transform(X_train[numerical_cols])
X_train = pd.concat([
pd.DataFrame(X_train_num_scaled, columns=numerical_cols, index=X_train.index),
X_train[["type_Red", "type_White"]]
], axis=1)
X_test_num_scaled = scaler.transform(X_test[numerical_cols])
X_test = pd.concat([
pd.DataFrame(X_test_num_scaled, columns=numerical_cols, index=X_test.index),
X_test[["type_Red", "type_White"]]
], axis=1)
# Train model
@st.cache_resource
def train_model():
model = RandomForestClassifier(
n_estimators=1000,
max_depth=15,
random_state=42,
n_jobs=-1,
class_weight="balanced"
)
model.fit(X_train, y_train)
return model
model = train_model()
# Accuracy
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
with st.container():
st.markdown("<div class='glass-card'>", unsafe_allow_html=True)
st.success(f"Model Accuracy on Test Set: *{accuracy:.4f}* ({accuracy*100:.2f}%)")
st.markdown("</div>", unsafe_allow_html=True)
# -------------------------- Interactive Prediction --------------------------
st.markdown("<div class='glass-card'>", unsafe_allow_html=True)
st.header("Predict Your Wine's Destiny")
# Wine type selector
wine_type = st.selectbox("Choose Wine Type", options=["Red", "White"], index=0)
col1, col2 = st.columns(2)
input_data = {"type_Red": 0, "type_White": 0}
input_data[f"type_{wine_type}"] = 1
features = [col for col in X.columns if col not in ["type_Red", "type_White"]]
for i, feature in enumerate(features):
col = col1 if i % 2 == 0 else col2
with col:
min_v, max_v = float(df[feature].min()), float(df[feature].max())
mean_v = float(df[feature].mean())
val = st.slider(
feature.replace("_", " ").title(),
min_value=min_v,
max_value=max_v,
value=mean_v,
step=0.1,
format="%.2f"
)
input_data[feature] = val
if st.button("Reveal the Quality!", use_container_width=True, type="primary"):
input_df = pd.DataFrame([input_data])
# Scale numerical columns (FIX: Reconstruct to match exact column order)
input_num_scaled = scaler.transform(input_df[numerical_cols])
input_scaled = pd.concat([
pd.DataFrame(input_num_scaled, columns=numerical_cols, index=input_df.index),
input_df[["type_Red", "type_White"]]
], axis=1)
pred = model.predict(input_scaled)[0]
prob = model.predict_proba(input_scaled)[0]
st.markdown("<br>", unsafe_allow_html=True)
if pred == 1:
st.balloons()
st.markdown(f"<h2 class='prediction-good'>OUTSTANDING WINE! {wine_type} Wine</h2>", unsafe_allow_html=True)
st.success(f"Confidence: *{prob[1]:.1%}* β This belongs in a museum... or your glass right now!")
else:
st.error(f"Not quite a masterpiece... {wine_type} Wine")
st.warning(f"Confidence: *{prob[0]:.1%}* β Maybe use it for cooking?")
# Feature importance hint
st.info(f"Pro tip: For {wine_type.lower()} wines, alcohol, sulphates, and volatile acidity matter most!")
st.markdown("</div>", unsafe_allow_html=True)
# -------------------------- Footer --------------------------
st.markdown("---")
st.caption("Made with passion | Dataset: UCI Wine Quality (Red + White) | Model: Random Forest |Created by: MAN JETANI")
|