Spaces:
Runtime error
Runtime error
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
os.environ['OPENBLAS_NUM_THREADS'] = '1'
|
3 |
+
os.environ['MKL_NUM_THREADS'] = '1'
|
4 |
+
os.environ['OMP_NUM_THREADS'] = '1'
|
5 |
+
|
6 |
+
|
7 |
+
import streamlit as st
|
8 |
+
import pandas as pd
|
9 |
+
from sklearn.preprocessing import MinMaxScaler
|
10 |
+
from sklearn.metrics.pairwise import cosine_similarity
|
11 |
+
from sklearn.cluster import KMeans
|
12 |
+
from sklearn.metrics import silhouette_score
|
13 |
+
|
14 |
+
# Set the number of threads for OpenBLAS, MKL, and OpenMP
|
15 |
+
|
16 |
+
|
17 |
+
# Load and preprocess the dataset
|
18 |
+
@st.cache(allow_output_mutation=True)
|
19 |
+
def load_data():
|
20 |
+
data = pd.read_csv('C:/Users/19452/Downloads/tracks_features.csv/tracks_features.csv')
|
21 |
+
|
22 |
+
# Normalize the features
|
23 |
+
features_to_normalize = ['danceability', 'energy', 'valence', 'tempo', 'loudness']
|
24 |
+
scaler = MinMaxScaler()
|
25 |
+
data[features_to_normalize] = scaler.fit_transform(data[features_to_normalize])
|
26 |
+
|
27 |
+
# Apply K-Means clustering
|
28 |
+
kmeans = KMeans(n_clusters=10, n_init=10, random_state=42)
|
29 |
+
data['cluster'] = kmeans.fit_predict(data[features_to_normalize])
|
30 |
+
|
31 |
+
# Calculate evaluation metrics
|
32 |
+
inertia = kmeans.inertia_
|
33 |
+
silhouette = silhouette_score(data[features_to_normalize], data['cluster'])
|
34 |
+
|
35 |
+
return data, kmeans, inertia, silhouette
|
36 |
+
|
37 |
+
data, kmeans_model, inertia, silhouette = load_data()
|
38 |
+
|
39 |
+
# Define mood criteria based on features
|
40 |
+
def filter_songs_by_mood(data, selected_moods):
|
41 |
+
mood_criteria = {
|
42 |
+
"Happy/Upbeat": (data['valence'] > 0.75) & (data['energy'] > 0.75),
|
43 |
+
"Calm/Relaxing": (data['energy'] < 0.25) & (data['tempo'] < 0.5),
|
44 |
+
"Sad/Melancholic": (data['valence'] < 0.25) & (data['energy'] < 0.25),
|
45 |
+
"Energetic/Exciting": (data['tempo'] > 0.75) & (data['energy'] > 0.75)
|
46 |
+
}
|
47 |
+
|
48 |
+
filtered_frames = [data[mood_criteria[mood]] for mood in selected_moods if mood in mood_criteria]
|
49 |
+
filtered_data = pd.concat(filtered_frames).drop_duplicates() if filtered_frames else pd.DataFrame()
|
50 |
+
|
51 |
+
return filtered_data.head(5) # Return only the top 5 results
|
52 |
+
|
53 |
+
# Function to find similar songs
|
54 |
+
def find_similar_songs(favorite_song_name, data, features, n_recommendations=5):
|
55 |
+
favorite_song_index = data.index[data['name'].str.lower() == favorite_song_name.lower()].tolist()
|
56 |
+
|
57 |
+
if not favorite_song_index:
|
58 |
+
return None, "Song not found. Please check the spelling or try another song."
|
59 |
+
|
60 |
+
favorite_song_index = favorite_song_index[0] # take the first match
|
61 |
+
favorite_song_features = data.loc[favorite_song_index, features].values.reshape(1, -1)
|
62 |
+
|
63 |
+
similarity = cosine_similarity(data[features], favorite_song_features).flatten()
|
64 |
+
similar_indices = similarity.argsort()[-n_recommendations-1:-1][::-1]
|
65 |
+
|
66 |
+
return data.loc[similar_indices].head(5), None # Return only the top 5 results
|
67 |
+
|
68 |
+
# Function to recommend songs from the same cluster
|
69 |
+
def recommend_from_cluster(favorite_song_name, data, kmeans, features, n_recommendations=5):
|
70 |
+
song_data = data[data['name'].str.lower() == favorite_song_name.lower()]
|
71 |
+
|
72 |
+
if song_data.empty:
|
73 |
+
return None, "Song not found. Please check the spelling or try another song."
|
74 |
+
|
75 |
+
song_cluster = song_data.iloc[0]['cluster']
|
76 |
+
cluster_songs = data[data['cluster'] == song_cluster]
|
77 |
+
cluster_songs = cluster_songs[cluster_songs['name'].str.lower() != favorite_song_name.lower()]
|
78 |
+
|
79 |
+
return cluster_songs.sample(min(len(cluster_songs), n_recommendations)), None
|
80 |
+
|
81 |
+
# Streamlit app
|
82 |
+
def main():
|
83 |
+
st.title('Music Recommender System')
|
84 |
+
|
85 |
+
# Display the evaluation metrics
|
86 |
+
st.write(f"Inertia: {inertia:.2f}")
|
87 |
+
st.write(f"Silhouette Score: {silhouette:.2f}")
|
88 |
+
|
89 |
+
# User selects moods
|
90 |
+
moods = ["Happy/Upbeat", "Calm/Relaxing", "Sad/Melancholic", "Energetic/Exciting"]
|
91 |
+
selected_moods = st.multiselect('Select your mood:', moods)
|
92 |
+
|
93 |
+
# User inputs their favorite song
|
94 |
+
favorite_song = st.text_input('Enter your favorite song:')
|
95 |
+
|
96 |
+
if selected_moods:
|
97 |
+
recommendations = filter_songs_by_mood(data, selected_moods)
|
98 |
+
if not recommendations.empty:
|
99 |
+
st.subheader('Recommended Songs based on your mood:')
|
100 |
+
st.dataframe(recommendations[['name', 'artists']])
|
101 |
+
else:
|
102 |
+
st.write("No songs match the selected moods. Try selecting different moods.")
|
103 |
+
|
104 |
+
if favorite_song:
|
105 |
+
cluster_songs, error_message = recommend_from_cluster(favorite_song, data, kmeans_model, features=['danceability', 'energy', 'valence', 'tempo', 'loudness'])
|
106 |
+
if cluster_songs is not None:
|
107 |
+
st.subheader('Songs from the same vibe cluster as your favorite:')
|
108 |
+
st.dataframe(cluster_songs[['name', 'artists']])
|
109 |
+
else:
|
110 |
+
st.error(error_message)
|
111 |
+
|
112 |
+
if __name__ == "__main__":
|
113 |
+
main()
|