Man0707 commited on
Commit
a7eecd2
·
verified ·
1 Parent(s): 4423c6e

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +239 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,241 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
1
+ Hugging Face's logo
2
+ Hugging Face
3
+ Models
4
+ Datasets
5
+ Spaces
6
+ Community
7
+ Docs
8
+ Pricing
9
+
10
+
11
+ Spaces:
12
+ Man0707
13
+ /
14
+ Wine_Quality
15
+
16
+ private
17
+
18
+ App
19
+ Files
20
+ Community
21
+ Settings
22
+ Wine_Quality
23
+ /
24
+ src
25
+ /
26
+ streamlit_app.py
27
+
28
+ Man0707's picture
29
+ Man0707
30
+ Update src/streamlit_app.py
31
+ efc0150
32
+ verified
33
+ about 3 hours ago
34
+ raw
35
+
36
+ Copy download link
37
+ history
38
+ blame
39
+ edit
40
+ delete
41
+
42
+ 7.46 kB
43
  import streamlit as st
44
+ import pandas as pd
45
+ import numpy as np
46
+ from sklearn.model_selection import train_test_split
47
+ from sklearn.preprocessing import StandardScaler
48
+ from sklearn.ensemble import RandomForestClassifier
49
+ from sklearn.metrics import accuracy_score
50
+
51
+ # -------------------------- Page Config --------------------------
52
+ st.set_page_config(
53
+ page_title="Wine Quality Master 🍷",
54
+ page_icon="🍇",
55
+ layout="centered",
56
+ initial_sidebar_state="expanded"
57
+ )
58
+
59
+ # -------------------------- Custom CSS - Dark Purple Magic --------------------------
60
+ st.markdown("""
61
+ <style>
62
+ .main {background: #0f001a; color: #e6e6fa;}
63
+ .stApp {background: linear-gradient(135deg, #2a0052, #000000);}
64
+ .glass-card {
65
+ background: rgba(138, 43, 226, 0.15);
66
+ backdrop-filter: blur(12px);
67
+ border-radius: 20px;
68
+ border: 1px solid rgba(138, 43, 226, 0.3);
69
+ padding: 2rem;
70
+ box-shadow: 0 8px 32px rgba(138, 43, 226, 0.2);
71
+ margin: 1.5rem 0;
72
+ }
73
+ h1, h2 {background: linear-gradient(90deg, #9b59b6, #e91e63, #ff9800);
74
+ -webkit-background-clip: text; -webkit-text-fill-color: transparent;}
75
+ .wine-red {color: #c0392b;}
76
+ .wine-white {color: #f1c40f;}
77
+ .prediction-good {font-size: 2.5rem; font-weight: bold; text-align: center;
78
+ color: #8e44ad; text-shadow: 0 0 20px #9b59b6;}
79
+ </style>
80
+ """, unsafe_allow_html=True)
81
+
82
+ # -------------------------- Load Full Wine Quality Dataset (Red + White) --------------------------
83
+ @st.cache_data
84
+ def load_wine_data():
85
+ # Red wine
86
+ red = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", sep=";")
87
+ red["type"] = "Red"
88
+
89
+ # White wine
90
+ white = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv", sep=";")
91
+ white["type"] = "White"
92
+
93
+ # Combine
94
+ df = pd.concat([red, white], ignore_index=True)
95
+
96
+ # Binary classification: Good (>=6), Bad (<6)
97
+ df["is_good"] = (df["quality"] >= 6).astype(int)
98
+
99
+ return df
100
+
101
+ df = load_wine_data()
102
+
103
+ # -------------------------- Hero Section --------------------------
104
+ col1, col2, col3 = st.columns([1,3,1])
105
+ with col2:
106
+ st.markdown("<h1 style='text-align:center;'>Wine Quality Master</h1>", unsafe_allow_html=True)
107
+ 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)
108
+
109
+ st.markdown("---")
110
+
111
+ # -------------------------- Dataset Info --------------------------
112
+ with st.container():
113
+ st.markdown("<div class='glass-card'>", unsafe_allow_html=True)
114
+ col1, col2, col3, col4 = st.columns(4)
115
+ with col1:
116
+ st.metric("Total Wines", f"{len(df):,}")
117
+ with col2:
118
+ st.metric("Red Wines", f"{len(df[df['type']=='Red']):,}", "Red Wine")
119
+ with col3:
120
+ st.metric("White Wines", f"{len(df[df['type']=='White']):,}", "White Wine")
121
+ with col4:
122
+ st.metric("Good Wines (≥6)", f"{df['is_good'].sum():,}")
123
+
124
+ st.markdown("<br>", unsafe_allow_html=True)
125
+ st.dataframe(df.head(), use_container_width=True)
126
+ st.markdown("</div>", unsafe_allow_html=True)
127
+
128
+ # -------------------------- Prepare Features --------------------------
129
+ X = df.drop(columns=["quality", "is_good"])
130
+ y = df["is_good"]
131
+
132
+ # One-hot encode wine type (ensures consistent column order)
133
+ X = pd.get_dummies(X, columns=["type"], drop_first=False)
134
+
135
+ # Train-test split
136
+ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
137
+
138
+ # Scale numerical features (preserve exact column order)
139
+ scaler = StandardScaler()
140
+ numerical_cols = [col for col in X.columns if col not in ["type_Red", "type_White"]]
141
+ X_train_num_scaled = scaler.fit_transform(X_train[numerical_cols])
142
+ X_train = pd.concat([
143
+ pd.DataFrame(X_train_num_scaled, columns=numerical_cols, index=X_train.index),
144
+ X_train[["type_Red", "type_White"]]
145
+ ], axis=1)
146
+
147
+ X_test_num_scaled = scaler.transform(X_test[numerical_cols])
148
+ X_test = pd.concat([
149
+ pd.DataFrame(X_test_num_scaled, columns=numerical_cols, index=X_test.index),
150
+ X_test[["type_Red", "type_White"]]
151
+ ], axis=1)
152
+
153
+ # Train model
154
+ @st.cache_resource
155
+ def train_model():
156
+ model = RandomForestClassifier(
157
+ n_estimators=1000,
158
+ max_depth=15,
159
+ random_state=42,
160
+ n_jobs=-1,
161
+ class_weight="balanced"
162
+ )
163
+ model.fit(X_train, y_train)
164
+ return model
165
+
166
+ model = train_model()
167
+
168
+ # Accuracy
169
+ y_pred = model.predict(X_test)
170
+ accuracy = accuracy_score(y_test, y_pred)
171
+
172
+ with st.container():
173
+ st.markdown("<div class='glass-card'>", unsafe_allow_html=True)
174
+ st.success(f"Model Accuracy on Test Set: *{accuracy:.4f}* ({accuracy*100:.2f}%)")
175
+ st.markdown("</div>", unsafe_allow_html=True)
176
+
177
+ # -------------------------- Interactive Prediction --------------------------
178
+ st.markdown("<div class='glass-card'>", unsafe_allow_html=True)
179
+ st.header("Predict Your Wine's Destiny")
180
+
181
+ # Wine type selector
182
+ wine_type = st.selectbox("Choose Wine Type", options=["Red", "White"], index=0)
183
+
184
+ col1, col2 = st.columns(2)
185
+ input_data = {"type_Red": 0, "type_White": 0}
186
+ input_data[f"type_{wine_type}"] = 1
187
+
188
+ features = [col for col in X.columns if col not in ["type_Red", "type_White"]]
189
+
190
+ for i, feature in enumerate(features):
191
+ col = col1 if i % 2 == 0 else col2
192
+ with col:
193
+ min_v, max_v = float(df[feature].min()), float(df[feature].max())
194
+ mean_v = float(df[feature].mean())
195
+ val = st.slider(
196
+ feature.replace("_", " ").title(),
197
+ min_value=min_v,
198
+ max_value=max_v,
199
+ value=mean_v,
200
+ step=0.1,
201
+ format="%.2f"
202
+ )
203
+ input_data[feature] = val
204
+
205
+ if st.button("Reveal the Quality!", use_container_width=True, type="primary"):
206
+ input_df = pd.DataFrame([input_data])
207
+
208
+ # Scale numerical columns (FIX: Reconstruct to match exact column order)
209
+ input_num_scaled = scaler.transform(input_df[numerical_cols])
210
+ input_scaled = pd.concat([
211
+ pd.DataFrame(input_num_scaled, columns=numerical_cols, index=input_df.index),
212
+ input_df[["type_Red", "type_White"]]
213
+ ], axis=1)
214
+
215
+ # Debug: Check column order (remove after testing)
216
+ with st.expander("Debug: Column Check (Remove in Production)"):
217
+ st.write("Input scaled columns:", list(input_scaled.columns))
218
+ st.write("Training columns:", list(X_train.columns))
219
+ st.write("Match?", list(input_scaled.columns) == list(X_train.columns))
220
+
221
+ pred = model.predict(input_scaled)[0]
222
+ prob = model.predict_proba(input_scaled)[0]
223
+
224
+ st.markdown("<br>", unsafe_allow_html=True)
225
+
226
+ if pred == 1:
227
+ st.balloons()
228
+ st.markdown(f"<h2 class='prediction-good'>OUTSTANDING WINE! {wine_type} Wine</h2>", unsafe_allow_html=True)
229
+ st.success(f"Confidence: *{prob[1]:.1%}* – This belongs in a museum... or your glass right now!")
230
+ else:
231
+ st.error(f"Not quite a masterpiece... {wine_type} Wine")
232
+ st.warning(f"Confidence: *{prob[0]:.1%}* – Maybe use it for cooking?")
233
+
234
+ # Feature importance hint
235
+ st.info(f"Pro tip: For {wine_type.lower()} wines, alcohol, sulphates, and volatile acidity matter most!")
236
+
237
+ st.markdown("</div>", unsafe_allow_html=True)
238
 
239
+ # -------------------------- Footer --------------------------
240
+ st.markdown("---")
241
+ st.caption("Made with passion | Dataset: UCI Wine Quality (Red + White) | Model: Random Forest")