AntonyG's picture
updated app with movies names and genre
5f98259 verified
import gradio as gr
import pickle
import numpy as np
import pandas as pd
# model weights pickled after training from scratch
with open('final_02_model_biases_factors.pkl', 'rb') as file:
model_state = pickle.load(file)
user_bias = model_state["user_bias"]
movie_bias = model_state["movie_bias"]
user_factors = model_state["user_factors"]
movie_factors = model_state["movie_factors"]
movies = pd.read_csv("movies.csv")
with open('map_movie_to_idx.pkl', 'rb') as file:
map_movie_to_idx = pickle.load(file)
with open('map_idx_to_movie.pkl', 'rb') as file:
map_idx_to_movie = pickle.load(file)
def get_movie_id(title):
movie = movies[movies['title'].str.contains(title, case=False, na=False)]
if not movie.empty:
return movie.iloc[0]['movieId'], movie.iloc[0]['title'], movie.iloc[0]['genres']
return None, None, None
def recommend_movies(movie_title, rating, latent_dim=10, lambda_param=0.1, tau=0.1):
movie_id, title, genres = get_movie_id(movie_title)
if movie_id is None:
return f"Movie '{movie_title}' not found."
# Map the dummy movie id to its index
dummy_movie_index = map_movie_to_idx[movie_id]
# Get the movie factors and bias for the dummy movie
dummy_movie_factors = movie_factors[:, dummy_movie_index]
dummy_movie_bias = movie_bias[dummy_movie_index]
# Initialize dummy user factors
dummy_user_factors = np.zeros(latent_dim)
# Calculate the dummy user factor
dummy_user_factor = np.linalg.inv(lambda_param * np.outer(dummy_movie_factors, dummy_movie_factors) +
tau * np.eye(latent_dim)) @ (lambda_param * dummy_movie_factors * (rating - dummy_movie_bias))
# Calculate the score for each movie
score = dummy_user_factor @ movie_factors + 0.05 * movie_bias
# Get the top 10 recommendations
recommend_movies_indices = np.argsort(score)[-10:]
# Map the indices back to movie titles
recommended_movies = [movies.loc[movies["movieId"] == map_idx_to_movie[movie]] for movie in recommend_movies_indices]
# Format the output as HTML
html_output = "<div style='font-family: Arial, sans-serif;'>"
html_output += f"<div style='margin-bottom: 20px;'><strong>Selected Movie:</strong><br>Title: {title}<br>Genres: {genres}</div>"
html_output += "<div style='margin-bottom: 20px;'><strong>Recommended Movies:</strong></div>"
for i, movie in enumerate(recommended_movies):
title = movie["title"].values[0]
genres = movie["genres"].values[0]
html_output += f"<div style='margin-bottom: 10px;'><strong>{i+1}. {title}</strong><br>Genres: {genres}</div>"
html_output += "</div>"
return html_output
# Define the Gradio interface
iface = gr.Interface(
fn=recommend_movies,
inputs=[
gr.Textbox(label="Movie Title"),
gr.Slider(0, 5, step=0.1, label="Rating")
],
outputs="html",
title="Movie Recommendation System",
description="""
Enter a movie title and rating to get top 10 movie recommendations.
I made this demo as part of a machine learning class taught by Prof. Ulich Paquet at AIMS South Africa.
Here are some sample movies you can try out of a database of over 62,000 movies:
- Toy Story
- Incredibles
- Lord of the rings
- Star Wars
- Terminator
"""
)
iface.launch(share=True)