jchen8000's picture
Update app.py
eceea93 verified
raw
history blame
3.69 kB
import pandas as pd
import numpy as np
from scipy.sparse import csr_matrix
from sklearn.neighbors import NearestNeighbors
import gradio as gr
import zipfile
import random
input_count = 300
result_count = 21
# Extract the MovieLens dataset
with zipfile.ZipFile('ml-latest-small.zip') as z:
with z.open('ml-latest-small/movies.csv') as f:
movies = pd.read_csv(f)
with z.open('ml-latest-small/ratings.csv') as f:
ratings = pd.read_csv(f)
# Create a user-item matrix
user_item_matrix = ratings.pivot(index='userId', columns='movieId', values='rating').fillna(0)
# Create a sparse matrix
user_item_matrix_sparse = csr_matrix(user_item_matrix.values)
# Fit the NearestNeighbors model
model_knn = NearestNeighbors(metric='cosine', algorithm='brute', n_neighbors=20, n_jobs=-1)
model_knn.fit(user_item_matrix_sparse)
# Function to get movie recommendations using collaborative filtering
def get_cf_recommendations(user_id, user_item_matrix=user_item_matrix, model_knn=model_knn, movies=movies):
if user_id not in user_item_matrix.index:
return []
user_vector = user_item_matrix.loc[user_id].values.reshape(1, -1)
distances, indices = model_knn.kneighbors(user_vector, n_neighbors=result_count)
similar_users = user_item_matrix.index[indices.flatten()]
similar_users_df = pd.DataFrame({'userId': similar_users, 'distance': distances.flatten()})
user_seen_movies = set(user_item_matrix.columns[user_item_matrix.loc[user_id] > 0])
recommendations = []
for _, row in similar_users_df.iterrows():
similar_user_id = row['userId']
similar_user_movies = set(user_item_matrix.columns[user_item_matrix.loc[similar_user_id] > 0])
new_movies = similar_user_movies - user_seen_movies
for movie_id in new_movies:
movie_title = movies.loc[movies['movieId'] == movie_id, 'title'].values[0]
score = 1 - row['distance'] # Convert distance to similarity score
recommendations.append((movie_title, score))
recommendations.sort(key=lambda x: x[1], reverse=True)
return recommendations[:result_count]
# Gradio interface for collaborative filtering
def recommend_movies_cf(user_id):
try:
user_id = int(user_id)
except ValueError:
return "Please enter a valid user ID (integer)."
if user_id not in user_item_matrix.index:
return f"User ID {user_id} not found in the dataset."
recommendations = get_cf_recommendations(user_id)
format_string = "{:>5.2f} {:<20}"
return "Score Title\n" + "\n".join([format_string.format(score, title) for title, score in recommendations])
# Update the existing Gradio interface
with gr.Blocks() as iface:
with gr.Tab("Content-Based Filtering"):
gr.Interface(fn=recommend_movies,
inputs=gr.Dropdown(movie_list, label=f"Select a Movie (Total movies: {total_movies}, randomly list {input_count} for demo purpose.)"),
outputs=[gr.Textbox(label="Recommended Movies:")],
title="Movie Recommender - Content-Based Filtering",
description="Select a movie to get recommendations based on content filtering.")
with gr.Tab("Collaborative Filtering"):
gr.Interface(fn=recommend_movies_cf,
inputs=gr.Number(label="Enter User ID"),
outputs=[gr.Textbox(label="Recommended Movies:")],
title="Movie Recommender - Collaborative Filtering",
description="Enter a user ID to get movie recommendations based on collaborative filtering.")
# Launch the app
iface.launch()