Spaces:
Sleeping
Sleeping
import streamlit as st | |
import pandas as pd | |
import numpy as np | |
import tensorflow as tf | |
import joblib | |
import os | |
# Define file paths (assuming all files are in the same folder as this script) | |
BASE_DIR = os.path.dirname(__file__) | |
KERAS_MODEL_PATH = os.path.join(BASE_DIR, "recommender_model.keras") | |
MOVIES_PATH = os.path.join(BASE_DIR, "movies.csv") | |
ENCODINGS_PATH = os.path.join(BASE_DIR, "encodings.pkl") | |
def load_model(): | |
if not os.path.exists(KERAS_MODEL_PATH): | |
st.error(f"β Model file not found at: {KERAS_MODEL_PATH}") | |
st.stop() | |
try: | |
return tf.keras.models.load_model(KERAS_MODEL_PATH) | |
except Exception as e: | |
st.error(f"β Failed to load model:\n\n{e}") | |
st.stop() | |
def load_assets(): | |
if not os.path.exists(MOVIES_PATH): | |
st.error("β movies.csv not found.") | |
st.stop() | |
if not os.path.exists(ENCODINGS_PATH): | |
st.error("β encodings.pkl not found.") | |
st.stop() | |
try: | |
df_movies = pd.read_csv(MOVIES_PATH) | |
user_map, movie_map = joblib.load(ENCODINGS_PATH) | |
return df_movies, user_map, movie_map | |
except Exception as e: | |
st.error(f"β Failed to load assets:\n\n{e}") | |
st.stop() | |
# Load model and assets | |
model = load_model() | |
movies_df, user2idx, movie2idx = load_assets() | |
reverse_movie_map = {v: k for k, v in movie2idx.items()} | |
# UI | |
st.title("π¬ TensorFlow Movie Recommender") | |
st.write("Select some movies you've liked to get personalized recommendations:") | |
# Movie title selection | |
movie_titles = movies_df.set_index("movieId")["title"].to_dict() | |
movie_choices = [movie_titles[mid] for mid in movie2idx if mid in movie_titles] | |
selected_titles = st.multiselect("ποΈ Liked movies", sorted(movie_choices)) | |
# User ratings dict | |
user_ratings = {} | |
for title in selected_titles: | |
movie_id = next((k for k, v in movie_titles.items() if v == title), None) | |
if movie_id: | |
user_ratings[movie_id] = 5.0 | |
# Generate recommendations | |
if st.button("π― Get Recommendations"): | |
if not user_ratings: | |
st.warning("Please select at least one movie.") | |
else: | |
liked_indices = [movie2idx[m] for m in user_ratings if m in movie2idx] | |
if not liked_indices: | |
st.error("β οΈ No valid movie encodings found.") | |
st.stop() | |
try: | |
# Calculate average embedding and similarity scores | |
avg_embedding = tf.reduce_mean(model.layers[2](tf.constant(liked_indices)), axis=0, keepdims=True) | |
all_movie_indices = tf.range(len(movie2idx)) | |
movie_embeddings = model.layers[3](all_movie_indices) | |
scores = tf.reduce_sum(avg_embedding * movie_embeddings, axis=1).numpy() | |
top_indices = np.argsort(scores)[::-1] | |
# Top 10 recommendations excluding already liked | |
recommended = [] | |
for idx in top_indices: | |
mid = reverse_movie_map.get(idx) | |
if mid not in user_ratings and mid in movie_titles: | |
recommended.append((movie_titles[mid], scores[idx])) | |
if len(recommended) >= 10: | |
break | |
st.subheader("πΏ Top 10 Recommendations") | |
for title, score in recommended: | |
st.write(f"**{title}** β Score: `{score:.3f}`") | |
except Exception as e: | |
st.error(f"β Error generating recommendations:\n\n{e}") | |