| |
| import gradio as gr |
| from datasets import load_dataset |
| import random |
| import pandas as pd |
| import faiss |
| import numpy as np |
| from sentence_transformers import SentenceTransformer, InputExample, losses |
| from torch.utils.data import DataLoader |
|
|
| |
| |
| |
| movies = load_dataset("AiresPucrs/movielens-movies", split="train") |
| ratings = load_dataset("AiresPucrs/movielens-user-ratings", split="train") |
|
|
| |
| movies_list = [dict(m) for m in movies] |
| movie_titles = [m['title'] for m in movies_list] |
|
|
| |
| movie_texts = [f"{m['title']} — {m['genres']}" for m in movies_list] |
|
|
| |
| df_ratings = pd.DataFrame(ratings) |
|
|
| |
| movieId_to_title = {m['movieId']: m['title'] for m in movies_list} |
|
|
| |
| |
| |
| triplets = [] |
|
|
| for m in movies_list: |
| genres = set(m['genres'].split("|")) |
| |
| |
| same_genre = [x for x in movies_list if x != m and len(set(x['genres'].split("|")).intersection(genres)) > 0] |
| if not same_genre: |
| continue |
| pos = random.choice(same_genre) |
| |
| |
| diff_genre = [x for x in movies_list if len(set(x['genres'].split("|")).intersection(genres)) == 0] |
| if not diff_genre: |
| continue |
| neg = random.choice(diff_genre) |
| |
| triplets.append(( |
| f"{m['title']} — {m['genres']}", |
| f"{pos['title']} — {pos['genres']}", |
| f"{neg['title']} — {neg['genres']}" |
| )) |
|
|
| |
| |
| |
| model = SentenceTransformer('all-MiniLM-L6-v2') |
| train_examples = [InputExample(texts=[a,p,n]) for a,p,n in triplets] |
| train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16) |
| train_loss = losses.TripletLoss(model=model) |
|
|
| |
| model.fit(train_objectives=[(train_dataloader, train_loss)], epochs=1, warmup_steps=50) |
|
|
| |
| |
| |
| movie_embeddings = model.encode(movie_texts, show_progress_bar=True) |
| movie_embeddings = np.array(movie_embeddings).astype("float32") |
| dim = movie_embeddings.shape[1] |
| index = faiss.IndexFlatL2(dim) |
| index.add(movie_embeddings) |
|
|
| |
| |
| |
| def recommend_similar_movies(query_title, top_k=5): |
| movie_row = [m for m in movies_list if m['title'] == query_title] |
| if len(movie_row) == 0: |
| return ["Movie not found"] |
| |
| query_text = f"{movie_row[0]['title']} — {movie_row[0]['genres']}" |
| q_emb = model.encode([query_text]).astype("float32") |
| |
| |
| D, I = index.search(q_emb, top_k * 2) |
| |
| recommendations = [] |
| for idx in I[0]: |
| title = movie_titles[int(idx)] |
| if title != query_title and title not in recommendations: |
| recommendations.append(title) |
| if len(recommendations) >= top_k: |
| break |
| |
| return recommendations |
|
|
| def recommend_for_user(user_id, top_k=5): |
| user_rated = df_ratings[df_ratings["userId"] == user_id] |
| liked = user_rated[user_rated["rating"] >= 4]["movieId"].tolist() |
| |
| similar_users = df_ratings[df_ratings["movieId"].isin(liked)]["userId"].unique() |
| recs = df_ratings[ |
| (df_ratings["userId"].isin(similar_users)) & |
| (~df_ratings["movieId"].isin(liked)) & |
| (df_ratings["rating"] >= 4) |
| ]["movieId"] |
| |
| top_recs = recs.value_counts().head(top_k).index.tolist() |
| recommended_titles = [movieId_to_title[m] for m in top_recs if m in movieId_to_title] |
| return recommended_titles if recommended_titles else ["No recommendations available"] |
|
|
| |
| |
| |
| def gradio_recommend(input_type, value, top_k=5): |
| if input_type == "Movie Title": |
| return recommend_similar_movies(value, top_k) |
| elif input_type == "User ID": |
| try: |
| user_id = int(value) |
| return recommend_for_user(user_id, top_k) |
| except: |
| return ["Invalid User ID"] |
| else: |
| return ["Invalid input type"] |
|
|
| iface = gr.Interface( |
| fn=gradio_recommend, |
| inputs=[ |
| gr.Dropdown(["Movie Title", "User ID"], label="Input Type"), |
| gr.Textbox(label="Enter movie title or user ID"), |
| gr.Slider(1, 10, value=5, step=1, label="Number of recommendations") |
| ], |
| outputs=gr.JSON(label="Recommendations"), |
| title="Movie Recommendation System", |
| description="Content-based and user-personalized movie recommendations" |
| ) |
|
|
| iface.launch() |