Spaces:
Sleeping
Sleeping
| from sklearn.decomposition import TruncatedSVD | |
| import pandas as pd | |
| from sklearn.feature_extraction.text import TfidfVectorizer | |
| from sklearn.neighbors import NearestNeighbors | |
| from sklearn.cluster import KMeans | |
| from sklearn.metrics.pairwise import cosine_similarity | |
| import gradio as gr | |
| def custom_similarity_by_index(idx1, idx2): | |
| row1 = df.iloc[idx1] | |
| row2 = df.iloc[idx2] | |
| def to_set(text): | |
| if pd.isna(text): | |
| return set() | |
| return set(text.lower().split()) | |
| g1, g2 = to_set(row1["genres"]), to_set(row2["genres"]) | |
| k1, k2 = to_set(row1["keywords"]), to_set(row2["keywords"]) | |
| genre_sim = len(g1 & g2) / len(g1 | g2) if g1 and g2 else 0 | |
| keyword_sim = len(k1 & k2) / len(k1 | k2) if k1 and k2 else 0 | |
| d1 = str(row1["director"]).lower() | |
| d2 = str(row2["director"]).lower() | |
| director_sim = 1 if d1 == d2 else 0 | |
| return 0.4 * genre_sim + 0.4 * keyword_sim + 0.2 * director_sim | |
| # ------------------ LOAD DATA ------------------ | |
| df = pd.read_csv("mov_dataset.csv") | |
| df["title_lower"] = df["title"].str.lower() | |
| tfidf = TfidfVectorizer() | |
| X = tfidf.fit_transform(df["combined_features"]) | |
| # ------------------ SVD ------------------ | |
| svd = TruncatedSVD(n_components=50, random_state=42) | |
| X_svd = svd.fit_transform(X) | |
| # ------------------ MODELS ------------------ | |
| knn = NearestNeighbors(metric='cosine', algorithm='brute') | |
| knn.fit(X_svd) | |
| kmeans = KMeans(n_clusters=10, random_state=42) | |
| clusters = kmeans.fit_predict(X_svd) | |
| cosine_sim = cosine_similarity(X_svd) | |
| # ------------------ RECOMMEND FUNCTION ------------------ | |
| def recommend(movie_name, model_type): | |
| movie_name = movie_name.strip().lower() | |
| if not movie_name: | |
| return ["Please enter a movie name"] | |
| if movie_name not in df["title_lower"].values: | |
| return ["Movie not found"] | |
| idx = df[df["title_lower"] == movie_name].index[0] | |
| if model_type == "KNN": | |
| distances, indices = knn.kneighbors([X_svd[idx]], n_neighbors=6) | |
| results = [] | |
| for i in indices[0][1:]: | |
| score = custom_similarity_by_index(idx, i) | |
| results.append((df.iloc[i]["title"], score)) | |
| return sorted(results, key=lambda x: x[1], reverse=True) | |
| elif model_type == "Cosine": | |
| scores = list(enumerate(cosine_sim[idx])) | |
| scores = sorted(scores, key=lambda x: x[1], reverse=True) | |
| results = [] | |
| for i, _ in scores[1:6]: | |
| score = custom_similarity_by_index(idx, i) | |
| results.append((df.iloc[i]["title"], score)) | |
| return sorted(results, key=lambda x: x[1], reverse=True) | |
| elif model_type == "KMeans": | |
| cluster_id = clusters[idx] | |
| cluster_indices = [i for i in range(len(df)) if clusters[i] == cluster_id and i != idx] | |
| if not cluster_indices: | |
| return ["No similar movies found"] | |
| results = [] | |
| for i in cluster_indices: | |
| score = custom_similarity_by_index(idx, i) | |
| results.append((df.iloc[i]["title"], score)) | |
| results = sorted(results, key=lambda x: x[1], reverse=True) | |
| return results[:5] | |
| # ------------------ CARD STYLE OUTPUT ------------------ | |
| def recommend_ui(movie, model): | |
| results = recommend(movie, model) | |
| if isinstance(results, list) and isinstance(results[0], str): | |
| return f"❌ {results[0]}" | |
| cards = "" | |
| for i, (title, score) in enumerate(results): | |
| cards += f""" | |
| <div style=" | |
| background-color:#1f1f1f; | |
| padding:15px; | |
| margin:10px; | |
| border-radius:10px; | |
| box-shadow:0px 0px 10px rgba(255,0,0,0.3); | |
| "> | |
| <h3 style="color:#E50914;">{i+1}. {title}</h3> | |
| <p style="color:white;">⭐ Similarity Score: <b>{score}</b></p> | |
| </div> | |
| """ | |
| return cards | |
| # ------------------ NETFLIX STYLE UI ------------------ | |
| css = """ | |
| body { | |
| background-color: #141414; | |
| color: white; | |
| } | |
| .gradio-container { | |
| background-color: #141414 !important; | |
| } | |
| h1 { | |
| text-align: center; | |
| color: #E50914; | |
| font-size: 42px; | |
| } | |
| """ | |
| with gr.Blocks(css=css) as demo: | |
| gr.Markdown("# 🎬 Netflix Movie Recommender") | |
| with gr.Row(): | |
| movie_input = gr.Textbox( | |
| label="Enter Movie Name", | |
| placeholder="Try: Avatar" | |
| ) | |
| model_input = gr.Dropdown( | |
| ["KNN", "Cosine", "KMeans"], | |
| value="KNN", | |
| label="Select Model" | |
| ) | |
| btn = gr.Button("🔥 Recommend") | |
| output = gr.HTML() | |
| btn.click(fn=recommend_ui, inputs=[movie_input, model_input], outputs=output) | |
| demo.launch() |