import gradio as gr import pandas as pd import numpy as np import pickle import os from comprehensive_recommendation_system import ComprehensiveRecommendationSystem import warnings warnings.filterwarnings('ignore') rec_system = None def load_recommendation_system(): """Load the trained recommendation system""" global rec_system if rec_system is None: print("Loading comprehensive recommendation system...") rec_system = ComprehensiveRecommendationSystem() rec_system.load_data("u.data", "u.item") if os.path.exists("comprehensive_recommendation_model.pkl"): print("Loading pre-trained model...") rec_system.load_model("comprehensive_recommendation_model.pkl") else: print("Training models...") rec_system.train_all_models() rec_system.save_model("comprehensive_recommendation_model.pkl") print("Recommendation system loaded successfully!") return rec_system def get_available_users(): """Get list of available users""" if rec_system is None: return [] return sorted(rec_system.ratings['user_id'].unique().tolist()) def get_user_stats(): """Get user statistics""" if rec_system is None: return "System not loaded" total_users = rec_system.ratings['user_id'].nunique() total_movies = rec_system.movies['movie_id'].nunique() total_ratings = len(rec_system.ratings) avg_rating = rec_system.ratings['rating'].mean() return f""" **Dataset Statistics:** - **Users:** {total_users:,} - **Movies:** {total_movies:,} - **Ratings:** {total_ratings:,} - **Average Rating:** {avg_rating:.2f}/5.0 - **Sparsity:** 93.70% """ def get_user_info(user_id): """Get detailed information about a user""" if rec_system is None: return "System not loaded" if user_id is None: return "Please select a user" user_ratings = rec_system.ratings[rec_system.ratings['user_id'] == user_id] if len(user_ratings) == 0: return f"User {user_id} not found in dataset" # Get user's rating statistics avg_rating = user_ratings['rating'].mean() num_ratings = len(user_ratings) rating_range = f"{user_ratings['rating'].min()} - {user_ratings['rating'].max()}" # Get rating distribution rating_dist = user_ratings['rating'].value_counts().sort_index() # Get user's top-rated movies top_movies = user_ratings.merge( rec_system.movies[['movie_id', 'title']], on='movie_id' ).sort_values('rating', ascending=False).head(10) info = f""" ## 👤 User {user_id} Profile ### 📊 Rating Statistics - **Total Ratings:** {num_ratings:,} - **Average Rating:** {avg_rating:.2f}/5.0 - **Rating Range:** {rating_range} ### 📈 Rating Distribution """ for rating, count in rating_dist.items(): percentage = (count / num_ratings) * 100 info += f"- **{rating} stars:** {count} ratings ({percentage:.1f}%)\n" info += f""" ### 🎬 Top 10 Rated Movies """ for i, (_, movie) in enumerate(top_movies.iterrows(), 1): stars = "⭐" * int(movie['rating']) info += f"{i:2d}. {movie['title']} {stars} ({movie['rating']})\n" return info def recommend_movies(user_id, num_recommendations, method): """Generate movie recommendations""" if rec_system is None: return "Error: Recommendation system not loaded" if user_id is None: return "Please select a user" try: recommendations = rec_system.recommend_movies( user_id=int(user_id), N=int(num_recommendations), method=method ) if len(recommendations) == 0: return "No recommendations available for this user" method_names = { "user_based": "👥 User-based Collaborative Filtering", "item_based": "🎬 Item-based Collaborative Filtering", "svd": "📊 SVD Matrix Factorization", "neural": "🧠 Neural Embeddings", "ensemble": "🎯 Ensemble Method" } result = f"## 🎬 Top {len(recommendations)} Movie Recommendations\n\n" result += f"**Method:** {method_names.get(method, method.upper())}\n" result += f"**User:** {user_id}\n\n" for i, (_, rec) in enumerate(recommendations.iterrows(), 1): rating_emoji = "⭐" * int(round(rec['predicted_rating'])) result += f"**{i:2d}.** {rec['title']}\n" result += f" {rating_emoji} Predicted Rating: {rec['predicted_rating']:.3f}\n\n" return result except Exception as e: return f"❌ Error generating recommendations: {str(e)}" def compare_all_methods(user_id, num_recommendations): """Compare all recommendation methods""" if rec_system is None: return "Error: Recommendation system not loaded" if user_id is None: return "Please select a user" methods = ["user_based", "item_based", "svd", "neural", "ensemble"] results = {} try: for method in methods: recommendations = rec_system.recommend_movies( user_id=int(user_id), N=int(num_recommendations), method=method ) results[method] = recommendations result = f"## ⚖️ Method Comparison for User {user_id}\n\n" result += f"**Number of recommendations:** {num_recommendations}\n\n" method_names = { "user_based": "👥 User-based CF", "item_based": "🎬 Item-based CF", "svd": "📊 SVD", "neural": "🧠 Neural", "ensemble": "🎯 Ensemble" } for method, recs in results.items(): result += f"### {method_names[method]}\n" if len(recs) == 0: result += "No recommendations available\n\n" else: for i, (_, rec) in enumerate(recs.iterrows(), 1): rating_emoji = "⭐" * int(round(rec['predicted_rating'])) result += f"{i:2d}. {rec['title']} {rating_emoji} ({rec['predicted_rating']:.3f})\n" result += "\n" return result except Exception as e: return f"❌ Error comparing methods: {str(e)}" def evaluate_system_performance(): """Evaluate the recommendation system performance""" if rec_system is None: return "Error: Recommendation system not loaded" try: all_users = rec_system.ratings['user_id'].unique() test_users = np.random.choice(all_users, min(15, len(all_users)), replace=False) methods = ["user_based", "item_based", "svd", "neural", "ensemble"] results = {} for method in methods: eval_results = rec_system.evaluate_model(test_users, method=method, N=10) results[method] = eval_results result = "## 📊 System Performance Evaluation\n\n" result += f"**Evaluated on:** {len(test_users)} users\n" result += f"**Recommendations per user:** 10\n\n" result += "| Method | Precision@10 | Recall@10 | NDCG@10 |\n" result += "|--------|--------------|-----------|----------|\n" for method, eval_results in results.items(): method_emoji = {"user_based": "👥", "item_based": "🎬", "svd": "📊", "neural": "🧠", "ensemble": "🎯"} emoji = method_emoji.get(method, "📈") result += f"| {emoji} {method:12} | {eval_results['precision']:.4f} | {eval_results['recall']:.4f} | {eval_results['ndcg']:.4f} |\n" best_method = max(results.keys(), key=lambda x: results[x]['ndcg']) best_emoji = {"user_based": "👥", "item_based": "🎬", "svd": "📊", "neural": "🧠", "ensemble": "🎯"}.get(best_method, "📈") result += f"\n### 🏆 Best Performing Method\n" result += f"**{best_emoji} {best_method.upper()}** with NDCG@10: {results[best_method]['ndcg']:.4f}\n\n" result += "### 📈 Metric Explanations\n" result += "- **Precision@10:** Fraction of recommended items that are relevant\n" result += "- **Recall@10:** Fraction of relevant items that are recommended\n" result += "- **NDCG@10:** Normalized Discounted Cumulative Gain (ranking quality)\n" return result except Exception as e: return f"❌ Error evaluating system: {str(e)}" def get_method_explanations(): """Get detailed explanations of each recommendation method""" return """ ## 🔬 Recommendation Methods Explained ### 👥 User-based Collaborative Filtering **How it works:** Finds users with similar rating patterns and recommends movies they liked. **Strengths:** - Intuitive approach that mimics human behavior - Good for finding diverse recommendations - Effective when user base is large **Best for:** Users who want to discover new genres and diverse content --- ### 🎬 Item-based Collaborative Filtering **How it works:** Finds movies with similar rating patterns and recommends items similar to those a user has liked. **Strengths:** - More stable than user-based approach - Computationally efficient - Good for popular items **Best for:** Users who want recommendations similar to movies they already like --- ### 📊 SVD Matrix Factorization **How it works:** Decomposes the user-item matrix into latent factors representing user preferences and item characteristics. **Strengths:** - Handles sparsity well - Captures implicit relationships - Computationally efficient **Best for:** Balanced performance with good generalization --- ### 🧠 Neural Embeddings **How it works:** Uses deep learning to learn complex non-linear relationships between users and items. **Strengths:** - Can capture complex patterns - Flexible architecture - Good for non-linear relationships **Best for:** Advanced pattern recognition and complex user behaviors --- ### 🎯 Ensemble Method **How it works:** Combines predictions from all four approaches by averaging their recommendation scores. **Strengths:** - Reduces individual method biases - More robust predictions - Better coverage of different patterns **Best for:** Optimal overall performance and reliability """ def create_interface(): """Create the enhanced Gradio interface""" load_recommendation_system() with gr.Blocks( title="🎬 Comprehensive Movie Recommendation System", theme=gr.themes.Soft( primary_hue="blue", secondary_hue="purple", neutral_hue="slate" ), css=""" .main-header { text-align: center; background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-size: 2.5em; font-weight: bold; margin-bottom: 20px; } .method-card { border: 2px solid #333333; border-radius: 12px; padding: 20px; margin: 15px 0; background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); color: white; } .stats-card { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 12px; margin: 10px 0; } .footer-text { color: white !important; } .footer-text h2, .footer-text h3 { color: white !important; } .footer-text p, .footer-text li { color: #e0e0e0 !important; } """ ) as app: gr.Markdown( """ # 🎬 Comprehensive Movie Recommendation System **Advanced ML Approaches for Personalized Recommendations** This system implements multiple state-of-the-art recommendation approaches including collaborative filtering, matrix factorization, and neural embeddings using the MovieLens 100K dataset. """, elem_classes="main-header" ) # Stats overview with gr.Row(): with gr.Column(): stats_display = gr.Markdown( get_user_stats(), elem_classes="stats-card" ) # Main tabs with gr.Tabs(): # Recommendation Tab with gr.Tab("🎯 Get Recommendations", id="recommendations"): gr.Markdown("### Generate personalized movie recommendations using different ML approaches") with gr.Row(): with gr.Column(scale=1): user_dropdown = gr.Dropdown( choices=get_available_users(), label="👤 Select User ID", value=get_available_users()[0] if get_available_users() else None, info="Choose from 943 available users" ) num_recommendations = gr.Slider( minimum=5, maximum=20, value=10, step=1, label="📊 Number of Recommendations", info="How many movies to recommend" ) method_dropdown = gr.Dropdown( choices=[ ("🎯 Ensemble Method (Recommended)", "ensemble"), ("👥 User-based Collaborative Filtering", "user_based"), ("🎬 Item-based Collaborative Filtering", "item_based"), ("📊 SVD Matrix Factorization", "svd"), ("🧠 Neural Embeddings", "neural") ], value="ensemble", label="🔬 Recommendation Method", info="Choose the ML approach for recommendations" ) recommend_btn = gr.Button("🚀 Get Recommendations", variant="primary", size="lg") with gr.Column(scale=2): recommendations_output = gr.Markdown( "👆 Select a user and method to get personalized movie recommendations...", label="🎬 Recommendations" ) recommend_btn.click( fn=recommend_movies, inputs=[user_dropdown, num_recommendations, method_dropdown], outputs=recommendations_output ) # User Analysis Tab with gr.Tab("👤 User Analysis", id="analysis"): gr.Markdown("### Analyze user preferences, rating patterns, and movie tastes") with gr.Row(): with gr.Column(scale=1): user_analysis_dropdown = gr.Dropdown( choices=get_available_users(), label="👤 Select User ID", value=get_available_users()[0] if get_available_users() else None, info="Choose a user to analyze" ) analyze_user_btn = gr.Button("🔍 Analyze User", variant="primary", size="lg") with gr.Column(scale=2): user_info_output = gr.Markdown( "👆 Select a user to analyze their preferences and rating patterns...", label="📊 User Profile" ) analyze_user_btn.click( fn=get_user_info, inputs=[user_analysis_dropdown], outputs=user_info_output ) # Method Comparison Tab with gr.Tab("⚖️ Compare Methods", id="comparison"): gr.Markdown("### Compare all recommendation methods side-by-side for a user") with gr.Row(): with gr.Column(scale=1): compare_user_dropdown = gr.Dropdown( choices=get_available_users(), label="👤 Select User ID", value=get_available_users()[0] if get_available_users() else None, info="Choose a user to compare methods for" ) compare_num_recs = gr.Slider( minimum=5, maximum=15, value=10, step=1, label="📊 Number of Recommendations", info="How many recommendations per method" ) compare_btn = gr.Button("⚖️ Compare All Methods", variant="primary", size="lg") with gr.Column(scale=2): comparison_output = gr.Markdown( "👆 Select a user to compare all recommendation methods...", label="📈 Method Comparison" ) compare_btn.click( fn=compare_all_methods, inputs=[compare_user_dropdown, compare_num_recs], outputs=comparison_output ) with gr.Tab("📊 System Evaluation", id="evaluation"): gr.Markdown("### Evaluate system performance with comprehensive metrics") with gr.Row(): with gr.Column(scale=1): evaluate_btn = gr.Button("📊 Evaluate System Performance", variant="primary", size="lg") with gr.Column(scale=2): evaluation_output = gr.Markdown( "👆 Click 'Evaluate System Performance' to see detailed metrics...", label="📈 Performance Results" ) evaluate_btn.click( fn=evaluate_system_performance, inputs=[], outputs=evaluation_output ) # Method Explanations Tab with gr.Tab("🔬 Method Explanations", id="explanations"): gr.Markdown("### Learn about each recommendation method and when to use them") explanations_output = gr.Markdown( get_method_explanations(), label="📚 Method Details" ) gr.Markdown( """ --- ## 🚀 About This System This comprehensive recommendation system demonstrates multiple state-of-the-art approaches: - **👥 Collaborative Filtering**: Both user-based and item-based methods - **📊 Matrix Factorization**: SVD for dimensionality reduction - **🧠 Neural Networks**: Deep learning embeddings for complex patterns - **🎯 Ensemble Methods**: Combining multiple approaches for optimal performance ### 📈 Evaluation Metrics - **Precision@K**: Fraction of recommended items that are relevant - **Recall@K**: Fraction of relevant items that are recommended - **NDCG@K**: Normalized Discounted Cumulative Gain for ranking quality ### 🎓 Educational Value Perfect for learning about recommendation systems, machine learning approaches, and interactive web application development. """, elem_classes="method-card footer-text" ) return app if __name__ == "__main__": app = create_interface() app.launch( server_name="0.0.0.0", server_port=7860, share=True, show_error=True )