ESMATUGBA commited on
Commit
61ba4b6
·
verified ·
1 Parent(s): b3891c7

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +81 -40
src/streamlit_app.py CHANGED
@@ -2,68 +2,108 @@ import streamlit as st
2
  import pandas as pd
3
  import joblib
4
  import matplotlib.pyplot as plt
 
5
 
6
  # --------------------------------------
7
- # 1️⃣ Load Files & Data Cleaning / Dosyaları Yükle ve Temizle
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  # --------------------------------------
9
  @st.cache_data
10
  def load_data():
11
- # Kendi kaydettiğin CSV dosyan
12
- df = pd.read_csv("spotify_clustered.csv")
13
-
14
- # Gereksiz/Teknik sütunları temizle (Görünümü güzelleştirir)
15
  unnecessary_cols = ['Unnamed: 0', 'track_id', 'album_name', 'explicit']
16
  df_display = df.drop(columns=[c for c in unnecessary_cols if c in df.columns])
17
-
18
  return df, df_display
19
 
20
- # Dosyaları yükle
 
 
 
 
 
21
  df, df_display = load_data()
22
- model = joblib.load("kmeans_music_model.pkl")
23
- scaler = joblib.load("scaler_music.pkl")
24
 
25
  # --------------------------------------
26
- # 2️⃣ Page Config / Sayfa Ayarları (Titremeyi önlemek için geniş mod)
27
  # --------------------------------------
28
- st.set_page_config(page_title="Spotify Clusters", layout="wide")
29
- st.title("🎵 Spotify Music Clustering / Müzik Kümeleme Analizi")
 
 
 
 
 
 
30
  st.markdown("---")
31
 
32
  # --------------------------------------
33
- # 3️⃣ Dataset Preview / Veri Seti Önizleme
34
  # --------------------------------------
35
  st.subheader("📄 Dataset Preview / Veri Önizleme")
36
- st.write("Cleaned data for analysis / Analiz için temizlenmiş veri:")
37
  st.dataframe(df_display.head(10), use_container_width=True)
38
 
39
  # --------------------------------------
40
- # 4️⃣ Visualizations / Görselleştirmeler (Titremeyi engelleyen yapı)
41
  # --------------------------------------
42
  col1, col2 = st.columns(2)
43
 
44
  with col1:
45
  st.subheader("📊 Cluster Distribution / Küme Dağılımı")
46
- st.bar_chart(df['cluster'].value_counts())
47
 
48
  with col2:
49
  st.subheader("🎯 Feature Analysis / Özellik Analizi")
50
- # Grafiği açıkça tanımlıyoruz ve her seferinde kapatıyoruz
51
- fig, ax = plt.subplots(figsize=(8, 5))
52
- scatter = ax.scatter(df['danceability'], df['energy'], c=df['cluster'], cmap='viridis', alpha=0.6)
 
 
 
 
 
 
 
53
  ax.set_xlabel("Danceability / Dans Edilebilirlik")
54
  ax.set_ylabel("Energy / Enerji")
55
- plt.colorbar(scatter, label="Cluster / Küme")
56
-
57
- # Titremeyi önlemek için clear_figure=True kullanıyoruz
58
  st.pyplot(fig, clear_figure=True)
59
- plt.close(fig) # Belleği boşalt
60
 
61
  # --------------------------------------
62
- # 5️⃣ Prediction Section / Tahmin Bölümü
63
  # --------------------------------------
64
  st.divider()
65
  st.subheader("🤖 Predict New Song Cluster / Yeni Şarkı Tahmini")
66
- st.info("Adjust the sliders to see which cluster a song belongs to / Şarkının hangi kümeye ait olduğunu görmek için sürgüleri ayarlayın.")
67
 
68
  c1, c2, c3 = st.columns(3)
69
 
@@ -78,34 +118,35 @@ with c2:
78
  tempo = st.slider("Tempo / Tempo", 0.0, 250.0, 120.0)
79
 
80
  with c3:
81
- # Kaggle'da eğittiğin 7. özelliği buraya ekledik (Hata almamak için)
82
  speech = st.slider("Speechiness / Konuşma Oranı", 0.0, 1.0, 0.1)
83
 
84
  if st.button("Predict Cluster / Kümeyi Tahmin Et ✨"):
85
- # SIRALAMA: Kaggle'daki modelin beklediği sırayla veriyoruz
86
  new_data = [[pop, dur, dance, energy, loud, tempo, speech]]
87
-
88
  try:
89
  new_data_scaled = scaler.transform(new_data)
90
  res = model.predict(new_data_scaled)[0]
91
-
92
- st.success(f"### Predicted Cluster / Tahmin Edilen Küme: {res}")
93
-
94
- # O kümeden benzer şarkı örnekleri
95
- st.write(f"**Similar songs from this group / Bu gruptaki benzer şarkılar:**")
96
- samples = df[df['cluster'] == res][['track_name', 'artists']].head(5)
97
- st.table(samples)
98
-
99
  except Exception as e:
100
- st.error(f"Prediction Error / Tahmin Hatası: {e}")
 
 
 
 
 
 
101
 
102
  # --------------------------------------
103
- # 6️⃣ Cluster Characteristics / Küme Karakteristikleri
104
  # --------------------------------------
105
  st.divider()
106
- st.subheader("🔍 Cluster Characteristics / Küme Özellikleri (Ortalamalar)")
107
- # Sadece sayısal verileri grupla (Titremeyi önlemek için seçim yapıyoruz)
108
  numeric_only = df.select_dtypes(include=['float64', 'int64'])
 
109
  if 'cluster' in df.columns:
110
  means = numeric_only.groupby(df['cluster']).mean()
111
  st.dataframe(means, use_container_width=True)
 
2
  import pandas as pd
3
  import joblib
4
  import matplotlib.pyplot as plt
5
+ import os
6
 
7
  # --------------------------------------
8
+ # 🎨 PAGE CONFIG
9
+ # --------------------------------------
10
+ st.set_page_config(page_title="Spotify Clustering", layout="wide")
11
+
12
+ # --------------------------------------
13
+ # 🔧 AUTO PATH (LOCAL + CLOUD FIX)
14
+ # --------------------------------------
15
+ def get_path(filename):
16
+ base_dir = os.path.dirname(os.path.abspath(__file__))
17
+
18
+ local_path = os.path.join(base_dir, filename)
19
+ parent_path = os.path.join(base_dir, "..", filename)
20
+
21
+ if os.path.exists(local_path):
22
+ return local_path
23
+ elif os.path.exists(parent_path):
24
+ return parent_path
25
+ else:
26
+ st.error(f"{filename} bulunamadı!")
27
+ st.stop()
28
+
29
+ DATA_PATH = get_path("spotify_clustered.csv")
30
+ MODEL_PATH = get_path("kmeans_music_model.pkl")
31
+ SCALER_PATH = get_path("scaler_music.pkl")
32
+
33
+ # --------------------------------------
34
+ # 📂 LOAD DATA (CACHE)
35
  # --------------------------------------
36
  @st.cache_data
37
  def load_data():
38
+ df = pd.read_csv(DATA_PATH)
39
+
 
 
40
  unnecessary_cols = ['Unnamed: 0', 'track_id', 'album_name', 'explicit']
41
  df_display = df.drop(columns=[c for c in unnecessary_cols if c in df.columns])
42
+
43
  return df, df_display
44
 
45
+ @st.cache_resource
46
+ def load_model():
47
+ model = joblib.load(MODEL_PATH)
48
+ scaler = joblib.load(SCALER_PATH)
49
+ return model, scaler
50
+
51
  df, df_display = load_data()
52
+ model, scaler = load_model()
 
53
 
54
  # --------------------------------------
55
+ # 🧠 SESSION STATE (NO FLICKER)
56
  # --------------------------------------
57
+ if "prediction" not in st.session_state:
58
+ st.session_state.prediction = None
59
+ st.session_state.samples = None
60
+
61
+ # --------------------------------------
62
+ # 🏷️ TITLE
63
+ # --------------------------------------
64
+ st.title("🎵 Spotify Music Clustering / Spotify Müzik Kümeleme")
65
  st.markdown("---")
66
 
67
  # --------------------------------------
68
+ # 📄 DATA PREVIEW
69
  # --------------------------------------
70
  st.subheader("📄 Dataset Preview / Veri Önizleme")
 
71
  st.dataframe(df_display.head(10), use_container_width=True)
72
 
73
  # --------------------------------------
74
+ # 📊 VISUALS
75
  # --------------------------------------
76
  col1, col2 = st.columns(2)
77
 
78
  with col1:
79
  st.subheader("📊 Cluster Distribution / Küme Dağılımı")
80
+ st.bar_chart(df['cluster'].value_counts(), use_container_width=True)
81
 
82
  with col2:
83
  st.subheader("🎯 Feature Analysis / Özellik Analizi")
84
+
85
+ fig, ax = plt.subplots(figsize=(6, 4))
86
+ scatter = ax.scatter(
87
+ df['danceability'],
88
+ df['energy'],
89
+ c=df['cluster'],
90
+ cmap='viridis',
91
+ alpha=0.6
92
+ )
93
+
94
  ax.set_xlabel("Danceability / Dans Edilebilirlik")
95
  ax.set_ylabel("Energy / Enerji")
96
+
97
+ plt.colorbar(scatter, ax=ax)
98
+
99
  st.pyplot(fig, clear_figure=True)
100
+ plt.close(fig)
101
 
102
  # --------------------------------------
103
+ # 🤖 PREDICTION
104
  # --------------------------------------
105
  st.divider()
106
  st.subheader("🤖 Predict New Song Cluster / Yeni Şarkı Tahmini")
 
107
 
108
  c1, c2, c3 = st.columns(3)
109
 
 
118
  tempo = st.slider("Tempo / Tempo", 0.0, 250.0, 120.0)
119
 
120
  with c3:
 
121
  speech = st.slider("Speechiness / Konuşma Oranı", 0.0, 1.0, 0.1)
122
 
123
  if st.button("Predict Cluster / Kümeyi Tahmin Et ✨"):
 
124
  new_data = [[pop, dur, dance, energy, loud, tempo, speech]]
125
+
126
  try:
127
  new_data_scaled = scaler.transform(new_data)
128
  res = model.predict(new_data_scaled)[0]
129
+
130
+ st.session_state.prediction = res
131
+ st.session_state.samples = df[df['cluster'] == res][['track_name', 'artists']].head(5)
132
+
 
 
 
 
133
  except Exception as e:
134
+ st.error(f"Error / Hata: {e}")
135
+
136
+ # SONUÇ (STABLE)
137
+ if st.session_state.prediction is not None:
138
+ st.success(f"### Predicted Cluster / Tahmin Edilen Küme: {st.session_state.prediction}")
139
+ st.write("Similar Songs / Benzer Şarkılar:")
140
+ st.table(st.session_state.samples)
141
 
142
  # --------------------------------------
143
+ # 🔍 CLUSTER ANALYSIS
144
  # --------------------------------------
145
  st.divider()
146
+ st.subheader("🔍 Cluster Characteristics / Küme Özellikleri")
147
+
148
  numeric_only = df.select_dtypes(include=['float64', 'int64'])
149
+
150
  if 'cluster' in df.columns:
151
  means = numeric_only.groupby(df['cluster']).mean()
152
  st.dataframe(means, use_container_width=True)