N-Kibria commited on
Commit
9a02c17
·
verified ·
1 Parent(s): 117e641

create app.py

Browse files
Files changed (1) hide show
  1. app.py +303 -0
app.py ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pickle
3
+ import pandas as pd
4
+ import numpy as np
5
+ import torch
6
+ import os
7
+
8
+ def load_model_and_data():
9
+ try:
10
+ with open('model_artifacts/hybrid_model.pkl', 'rb') as f:
11
+ model = pickle.load(f)
12
+
13
+ with open('model_artifacts/loader.pkl', 'rb') as f:
14
+ loader = pickle.load(f)
15
+
16
+ with open('model_artifacts/movies.pkl', 'rb') as f:
17
+ movies = pickle.load(f)
18
+
19
+ user_ids = sorted(loader.user_id_map.keys())
20
+
21
+ return model, loader, movies, user_ids
22
+ except Exception as e:
23
+ print(f"Error loading model: {e}")
24
+ return None, None, None, []
25
+
26
+ print("Loading model and data...")
27
+ model, loader, movies_df, user_ids = load_model_and_data()
28
+ print(f"Model loaded! Available users: {len(user_ids)}")
29
+
30
+ def get_recommendations(user_id, num_recommendations):
31
+ if model is None or loader is None:
32
+ return "Error: Model not loaded properly."
33
+
34
+ try:
35
+ user_id = int(user_id)
36
+ num_recommendations = int(num_recommendations)
37
+
38
+ if user_id not in loader.user_id_map:
39
+ return f"User ID {user_id} not found! Please select a valid user ID."
40
+
41
+ recommendations = model.recommend_movies(
42
+ user_id=user_id,
43
+ N=num_recommendations,
44
+ user_id_map=loader.user_id_map,
45
+ reverse_movie_map=loader.reverse_movie_map,
46
+ movies_df=movies_df
47
+ )
48
+
49
+ if not recommendations:
50
+ return f"No recommendations found for User {user_id}"
51
+
52
+ output = f"Top {num_recommendations} Movie Recommendations for User {user_id}\n\n"
53
+ output += "=" * 60 + "\n\n"
54
+
55
+ for i, (movie_id, title, score) in enumerate(recommendations, 1):
56
+ stars = "*" * int(score)
57
+ output += f"{i}. {title}\n"
58
+ output += f" Predicted Rating: {score:.2f}/5.00 {stars}\n"
59
+ output += f" Movie ID: {movie_id}\n\n"
60
+
61
+ return output
62
+
63
+ except ValueError:
64
+ return "Error: Please enter valid numbers for User ID and Number of Recommendations"
65
+ except Exception as e:
66
+ return f"Error generating recommendations: {str(e)}"
67
+
68
+ def get_user_history(user_id):
69
+ if model is None or loader is None:
70
+ return "Error: Model not loaded properly."
71
+
72
+ try:
73
+ user_id = int(user_id)
74
+
75
+ if user_id not in loader.user_id_map:
76
+ return f"User ID {user_id} not found!"
77
+
78
+ user_idx = loader.user_id_map[user_id]
79
+
80
+ user_ratings = model.item_cf.user_item_matrix[user_idx].toarray().flatten()
81
+ rated_indices = np.where(user_ratings > 0)[0]
82
+
83
+ if len(rated_indices) == 0:
84
+ return f"No rating history found for User {user_id}"
85
+
86
+ history = []
87
+ for movie_idx in rated_indices:
88
+ original_movie_id = loader.reverse_movie_map[movie_idx]
89
+ title = movies_df[movies_df['movie_id'] == original_movie_id]['title'].values[0]
90
+ rating = user_ratings[movie_idx]
91
+ history.append((title, rating))
92
+
93
+ history.sort(key=lambda x: x[1], reverse=True)
94
+
95
+ output = f"Rating History for User {user_id}\n\n"
96
+ output += f"Total movies rated: {len(history)}\n"
97
+ output += f"Average rating: {np.mean([r for _, r in history]):.2f}\n\n"
98
+ output += "=" * 60 + "\n\n"
99
+ output += "Top 10 Highest Rated Movies:\n\n"
100
+
101
+ for i, (title, rating) in enumerate(history[:10], 1):
102
+ stars = "*" * int(rating)
103
+ output += f"{i}. {title} - {rating:.1f}/5 {stars}\n"
104
+
105
+ return output
106
+
107
+ except Exception as e:
108
+ return f"Error: {str(e)}"
109
+
110
+ def get_movie_info(movie_title_search):
111
+ if movies_df is None:
112
+ return "Error: Movies data not loaded"
113
+
114
+ try:
115
+ matches = movies_df[movies_df['title'].str.contains(movie_title_search, case=False, na=False)]
116
+
117
+ if len(matches) == 0:
118
+ return f"No movies found matching '{movie_title_search}'"
119
+
120
+ output = f"Search Results for '{movie_title_search}'\n\n"
121
+ output += f"Found {len(matches)} movie(s):\n\n"
122
+ output += "=" * 60 + "\n\n"
123
+
124
+ for i, (_, row) in enumerate(matches.head(20).iterrows(), 1):
125
+ output += f"{i}. {row['title']} (ID: {row['movie_id']})\n"
126
+
127
+ if len(matches) > 20:
128
+ output += f"\n... and {len(matches) - 20} more results"
129
+
130
+ return output
131
+
132
+ except Exception as e:
133
+ return f"Error: {str(e)}"
134
+
135
+ with gr.Blocks(theme=gr.themes.Soft(), title="Movie Recommender - DataSynthis") as demo:
136
+
137
+ gr.Markdown("""
138
+ # Hybrid Movie Recommendation System
139
+ ### DataSynthis Job Task - Powered by AI
140
+
141
+ This system combines Collaborative Filtering, SVD Matrix Factorization, and Neural Networks
142
+ to provide personalized movie recommendations from the MovieLens 100k dataset.
143
+
144
+ ---
145
+ """)
146
+
147
+ with gr.Tabs():
148
+
149
+ with gr.Tab("Get Recommendations"):
150
+ gr.Markdown("### Get personalized movie recommendations for any user")
151
+
152
+ with gr.Row():
153
+ with gr.Column(scale=1):
154
+ user_id_input = gr.Number(
155
+ label="User ID",
156
+ value=1,
157
+ minimum=1,
158
+ maximum=943,
159
+ step=1,
160
+ info="Enter a user ID (1-943)"
161
+ )
162
+
163
+ num_recs_input = gr.Slider(
164
+ label="Number of Recommendations",
165
+ minimum=5,
166
+ maximum=20,
167
+ value=10,
168
+ step=1
169
+ )
170
+
171
+ recommend_btn = gr.Button("Get Recommendations", variant="primary")
172
+
173
+ with gr.Column(scale=2):
174
+ recommendations_output = gr.Textbox(
175
+ label="Recommendations",
176
+ lines=20,
177
+ max_lines=30
178
+ )
179
+
180
+ recommend_btn.click(
181
+ fn=get_recommendations,
182
+ inputs=[user_id_input, num_recs_input],
183
+ outputs=recommendations_output
184
+ )
185
+
186
+ gr.Markdown("""
187
+ How it works:
188
+ - Enter a User ID (between 1 and 943)
189
+ - Choose how many recommendations you want
190
+ - Click "Get Recommendations" to see personalized movie suggestions
191
+ """)
192
+
193
+ with gr.Tab("User History"):
194
+ gr.Markdown("### View a user's rating history")
195
+
196
+ with gr.Row():
197
+ with gr.Column(scale=1):
198
+ user_id_history = gr.Number(
199
+ label="User ID",
200
+ value=1,
201
+ minimum=1,
202
+ maximum=943,
203
+ step=1
204
+ )
205
+
206
+ history_btn = gr.Button("View History", variant="primary")
207
+
208
+ with gr.Column(scale=2):
209
+ history_output = gr.Textbox(
210
+ label="Rating History",
211
+ lines=20,
212
+ max_lines=30
213
+ )
214
+
215
+ history_btn.click(
216
+ fn=get_user_history,
217
+ inputs=user_id_history,
218
+ outputs=history_output
219
+ )
220
+
221
+ with gr.Tab("Search Movies"):
222
+ gr.Markdown("### Search for movies in the database")
223
+
224
+ with gr.Row():
225
+ with gr.Column(scale=1):
226
+ movie_search = gr.Textbox(
227
+ label="Movie Title Search",
228
+ placeholder="e.g., Star Wars, Godfather, Titanic...",
229
+ value="Star Wars"
230
+ )
231
+
232
+ search_btn = gr.Button("Search", variant="primary")
233
+
234
+ with gr.Column(scale=2):
235
+ search_output = gr.Textbox(
236
+ label="Search Results",
237
+ lines=20,
238
+ max_lines=30
239
+ )
240
+
241
+ search_btn.click(
242
+ fn=get_movie_info,
243
+ inputs=movie_search,
244
+ outputs=search_output
245
+ )
246
+
247
+ with gr.Tab("About"):
248
+ gr.Markdown("""
249
+ ## About This System
250
+
251
+ ### Model Architecture
252
+ This is a Hybrid Recommendation System that combines three approaches:
253
+
254
+ 1. Item-Based Collaborative Filtering
255
+ - Uses cosine similarity between movies
256
+ - Recommends movies similar to what you've liked before
257
+
258
+ 2. SVD Matrix Factorization
259
+ - Decomposes the user-movie rating matrix
260
+ - Discovers latent factors that explain user preferences
261
+
262
+ 3. Neural Collaborative Filtering (NCF)
263
+ - Deep learning model with user and movie embeddings
264
+ - Learns complex non-linear patterns in user behavior
265
+
266
+ ### Dataset
267
+ - MovieLens 100k dataset
268
+ - 100,000 ratings from 943 users on 1,682 movies
269
+ - Ratings scale: 1-5 stars
270
+
271
+ ### Performance Metrics
272
+ - Precision@10: 26.77%
273
+ - NDCG@10: 28.50%
274
+ - Model improves recommendations by 40% vs baseline
275
+
276
+ ### Created For
277
+ DataSynthis Job Task
278
+
279
+ ### Technologies Used
280
+ - PyTorch (Neural Networks)
281
+ - Scikit-learn (SVD, Similarity)
282
+ - Pandas & NumPy (Data Processing)
283
+ - Gradio (Web Interface)
284
+
285
+ ---
286
+
287
+ Note: This model is trained on the MovieLens 100k dataset.
288
+ User IDs range from 1 to 943, and movie IDs range from 1 to 1682.
289
+ """)
290
+
291
+ gr.Markdown("""
292
+ ---
293
+ <div style='text-align: center'>
294
+ <p>Hybrid Movie Recommendation System | Built for DataSynthis</p>
295
+ </div>
296
+ """)
297
+
298
+ if __name__ == "__main__":
299
+ demo.launch(
300
+ share=False,
301
+ server_name="0.0.0.0",
302
+ server_port=7860
303
+ )