Code0ut's picture
Update app.py
aadcdbf verified
Raw
History Blame Contribute Delete
4.65 kB
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()