LvMAC commited on
Commit
0be6b17
·
verified ·
1 Parent(s): a4d5352

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -0
app.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ from surprise import SVD, Dataset, Reader, accuracy
4
+ from surprise.model_selection import train_test_split, cross_validate
5
+ from collections import defaultdict
6
+
7
+ class MovieRecommender:
8
+ def __init__(self, ratings_path, movies_path):
9
+ # Load data
10
+ self.ratings = pd.read_csv(ratings_path)
11
+ self.movies = pd.read_csv(movies_path)
12
+
13
+ # Build Surprise dataset
14
+ reader = Reader(rating_scale=(0.5, 5.0))
15
+ self.data = Dataset.load_from_df(
16
+ self.ratings[['userId', 'movieId', 'rating']],
17
+ reader
18
+ )
19
+
20
+ # Train model
21
+ self.trainset = self.data.build_full_trainset()
22
+ self.algo = SVD(n_factors=100, n_epochs=20, lr_all=0.005, reg_all=0.02)
23
+ self.algo.fit(self.trainset)
24
+
25
+ def recommend_movies(self, user_id, N):
26
+ # Get all movie IDs
27
+ all_movie_ids = self.movies['movieId'].unique()
28
+
29
+ # Get movies user has already rated
30
+ rated_movies = self.ratings[self.ratings['userId'] == user_id]['movieId'].values
31
+
32
+ # Get unrated movies
33
+ unrated_movies = [m for m in all_movie_ids if m not in rated_movies]
34
+
35
+ # Predict ratings
36
+ predictions = []
37
+ for movie_id in unrated_movies:
38
+ pred = self.algo.predict(user_id, movie_id)
39
+ predictions.append((movie_id, pred.est))
40
+
41
+ # Sort by predicted rating
42
+ predictions.sort(key=lambda x: x[1], reverse=True)
43
+
44
+ # Get top N
45
+ top_n = predictions[:N]
46
+
47
+ # Merge with movie titles
48
+ results = []
49
+ for movie_id, score in top_n:
50
+ title = self.movies[self.movies['movieId'] == movie_id]['title'].values[0]
51
+ results.append({
52
+ 'movieId': movie_id,
53
+ 'title': title,
54
+ 'predicted_rating': round(score, 2)
55
+ })
56
+
57
+ return results
58
+
59
+ def evaluate(self):
60
+ # Cross-validation
61
+ results = cross_validate(
62
+ self.algo,
63
+ self.data,
64
+ measures=['RMSE', 'MAE'],
65
+ cv=5,
66
+ verbose=False
67
+ )
68
+
69
+ # Custom metrics: Precision@K, Recall@K, NDCG@K
70
+ trainset, testset = train_test_split(self.data, test_size=0.2)
71
+ self.algo.fit(trainset)
72
+ predictions = self.algo.test(testset)
73
+
74
+ # Calculate Precision@K and Recall@K
75
+ k = 10
76
+ threshold = 4.0
77
+
78
+ user_est_true = defaultdict(list)
79
+ for uid, _, true_r, est, _ in predictions:
80
+ user_est_true[uid].append((est, true_r))
81
+
82
+ precisions = []
83
+ recalls = []
84
+
85
+ for uid, user_ratings in user_est_true.items():
86
+ user_ratings.sort(key=lambda x: x[0], reverse=True)
87
+ top_k = user_ratings[:k]
88
+
89
+ n_rel = sum(1 for (_, true_r) in user_ratings if true_r >= threshold)
90
+ n_rec_k = sum(1 for (est, _) in top_k if est >= threshold)
91
+ n_rel_and_rec_k = sum(1 for (est, true_r) in top_k
92
+ if true_r >= threshold and est >= threshold)
93
+
94
+ precisions.append(n_rel_and_rec_k / n_rec_k if n_rec_k > 0 else 0)
95
+ recalls.append(n_rel_and_rec_k / n_rel if n_rel > 0 else 0)
96
+
97
+ return {
98
+ 'rmse': np.mean(results['test_rmse']),
99
+ 'mae': np.mean(results['test_mae']),
100
+ f'precision@{k}': np.mean(precisions),
101
+ f'recall@{k}': np.mean(recalls)
102
+ }
103
+
104
+
105
+ import gradio as gr
106
+
107
+ # Initialize recommender
108
+ recommender = MovieRecommender('ratings.csv', 'movies.csv')
109
+
110
+ def recommend_interface(user_id, n_recommendations):
111
+ try:
112
+ user_id = int(user_id)
113
+ n_recommendations = int(n_recommendations)
114
+
115
+ recommendations = recommender.recommend_movies(user_id, n_recommendations)
116
+
117
+ output = []
118
+ for i, rec in enumerate(recommendations, 1):
119
+ output.append(f"{i}. {rec['title']} (Predicted: {rec['predicted_rating']})")
120
+
121
+ return "\n".join(output)
122
+ except Exception as e:
123
+ return f"Error: {str(e)}"
124
+
125
+ # Create interface
126
+ demo = gr.Interface(
127
+ fn=recommend_interface,
128
+ inputs=[
129
+ gr.Textbox(label="User ID", placeholder="Enter user ID"),
130
+ gr.Slider(minimum=1, maximum=20, value=10, step=1, label="Number of Recommendations")
131
+ ],
132
+ outputs=gr.Textbox(label="Recommendations", lines=15),
133
+ title="MovieLens Recommendation System",
134
+ description="Enter a user ID to get personalized movie recommendations"
135
+ )
136
+
137
+ demo.launch()