Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pickle | |
| import pandas as pd | |
| import numpy as np | |
| from surprise import SVD | |
| import warnings | |
| warnings.filterwarnings('ignore') | |
| # Load models and data | |
| print("Loading models...") | |
| with open('svd_model.pkl', 'rb') as f: | |
| svd_model = pickle.load(f) | |
| with open('movies.pkl', 'rb') as f: | |
| movies = pickle.load(f) | |
| with open('ratings.pkl', 'rb') as f: | |
| ratings = pickle.load(f) | |
| print("Models loaded successfully!") | |
| def recommend_movies(user_id, num_recommendations, min_rating): | |
| """ | |
| Generate movie recommendations for a user | |
| """ | |
| try: | |
| user_id = int(user_id) | |
| num_recommendations = int(num_recommendations) | |
| min_rating = float(min_rating) | |
| # Check if user exists | |
| if user_id not in ratings['userId'].values: | |
| return f"β οΈ User ID {user_id} not found in database. Please try a different user ID (1-{ratings['userId'].max()})." | |
| # Get all movies | |
| all_movie_ids = movies['movieId'].unique() | |
| # Get movies the user has already rated | |
| rated_movies = ratings[ratings['userId'] == user_id]['movieId'].values | |
| # Get movies the user hasn't rated | |
| movies_to_predict = [mid for mid in all_movie_ids if mid not in rated_movies] | |
| # Predict ratings | |
| predictions = [] | |
| for movie_id in movies_to_predict: | |
| pred = svd_model.predict(user_id, movie_id) | |
| if pred.est >= min_rating: | |
| predictions.append({ | |
| 'movieId': movie_id, | |
| 'predicted_rating': pred.est | |
| }) | |
| if not predictions: | |
| return f"No movies found with predicted rating >= {min_rating}. Try lowering the minimum rating." | |
| # Sort and get top N | |
| predictions_df = pd.DataFrame(predictions) | |
| predictions_df = predictions_df.sort_values('predicted_rating', ascending=False) | |
| top_recommendations = predictions_df.head(num_recommendations) | |
| # Merge with movie details | |
| recommendations = top_recommendations.merge(movies, on='movieId') | |
| recommendations['predicted_rating'] = recommendations['predicted_rating'].round(2) | |
| # Format output | |
| output = f"π¬ Top {len(recommendations)} Movie Recommendations for User {user_id}\n\n" | |
| for idx, row in recommendations.iterrows(): | |
| output += f"{idx + 1}. **{row['title']}**\n" | |
| output += f" β Predicted Rating: {row['predicted_rating']}/5.0\n" | |
| output += f" π Genres: {row['genres']}\n\n" | |
| return output | |
| except Exception as e: | |
| return f"β Error: {str(e)}" | |
| def get_user_history(user_id): | |
| """ | |
| Get user's rating history | |
| """ | |
| try: | |
| user_id = int(user_id) | |
| if user_id not in ratings['userId'].values: | |
| return f"β οΈ User ID {user_id} not found." | |
| user_ratings = ratings[ratings['userId'] == user_id].merge(movies, on='movieId') | |
| user_ratings = user_ratings.sort_values('rating', ascending=False).head(10) | |
| output = f"π User {user_id}'s Top Rated Movies:\n\n" | |
| for idx, row in user_ratings.iterrows(): | |
| output += f"β’ **{row['title']}** - β {row['rating']}/5.0\n" | |
| output += f" Genres: {row['genres']}\n\n" | |
| return output | |
| except Exception as e: | |
| return f"β Error: {str(e)}" | |
| # Create Gradio interface | |
| with gr.Blocks(theme=gr.themes.Soft()) as demo: | |
| gr.Markdown( | |
| """ | |
| # π¬ MovieLens Recommendation System | |
| ### Powered by SVD Matrix Factorization | |
| Get personalized movie recommendations based on collaborative filtering! | |
| """ | |
| ) | |
| with gr.Tab("π― Get Recommendations"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| user_id_input = gr.Number( | |
| label="User ID", | |
| value=1, | |
| info=f"Enter a user ID (1 to {ratings['userId'].max()})" | |
| ) | |
| num_rec_input = gr.Slider( | |
| minimum=5, | |
| maximum=20, | |
| value=10, | |
| step=1, | |
| label="Number of Recommendations" | |
| ) | |
| min_rating_input = gr.Slider( | |
| minimum=1.0, | |
| maximum=5.0, | |
| value=3.5, | |
| step=0.5, | |
| label="Minimum Predicted Rating" | |
| ) | |
| recommend_btn = gr.Button("π¬ Get Recommendations", variant="primary") | |
| with gr.Column(): | |
| recommendations_output = gr.Markdown(label="Recommendations") | |
| recommend_btn.click( | |
| fn=recommend_movies, | |
| inputs=[user_id_input, num_rec_input, min_rating_input], | |
| outputs=recommendations_output | |
| ) | |
| with gr.Tab("π User History"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| history_user_id = gr.Number( | |
| label="User ID", | |
| value=1, | |
| info="Enter a user ID to see their rating history" | |
| ) | |
| history_btn = gr.Button("π View History", variant="primary") | |
| with gr.Column(): | |
| history_output = gr.Markdown(label="User History") | |
| history_btn.click( | |
| fn=get_user_history, | |
| inputs=history_user_id, | |
| outputs=history_output | |
| ) | |
| gr.Markdown( | |
| """ | |
| --- | |
| ### π Model Information | |
| - **Algorithm**: SVD (Singular Value Decomposition) | |
| - **Dataset**: MovieLens Small (100K ratings) | |
| - **Evaluation Metrics**: RMSE, Precision@K, Recall@K, NDCG@K | |
| - **Best Performance**: Lowest RMSE and Highest NDCG among tested models | |
| """ | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |