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"""

{i+1}. {title}

⭐ Similarity Score: {score}

""" 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()