Rijeet's picture
Update app.py
4f11e18 verified
Raw History Blame Contribute Delete
21.1 kB
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
)