krishnaveni76 commited on
Commit
63361d4
·
1 Parent(s): b4f6ffc

Updated all files

Browse files
Files changed (4) hide show
  1. .gitignore +1 -1
  2. Dockerfile +42 -1
  3. README.md +120 -3
  4. app.py +217 -208
.gitignore CHANGED
@@ -1,4 +1,4 @@
1
- anime/
2
  .env
3
  Artifacts/
4
  logs/
 
1
+ anime/
2
  .env
3
  Artifacts/
4
  logs/
Dockerfile CHANGED
@@ -1,6 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # Use the official Python image as a base
2
  FROM python:3.10-slim-buster
3
 
 
 
 
 
 
 
 
 
 
 
 
4
  # Set the working directory in the container
5
  WORKDIR /app
6
 
@@ -8,10 +48,11 @@ WORKDIR /app
8
  COPY . .
9
 
10
  # Install required packages
 
11
  RUN pip install -r requirements.txt
12
 
13
  # Expose the port that Streamlit uses
14
  EXPOSE 8501
15
 
16
  # Run the Streamlit app
17
- CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
 
1
+ # # Use the official Python image as a base
2
+ # FROM python:3.10-slim-buster
3
+
4
+ # # Set the working directory in the container
5
+ # WORKDIR /app
6
+
7
+ # # Copy the app files into the container
8
+ # COPY . .
9
+
10
+ # # Install required packages
11
+ # RUN pip install -r requirements.txt
12
+
13
+ # # Expose the port that Streamlit uses
14
+ # EXPOSE 8501
15
+
16
+ # # Run the Streamlit app
17
+ # CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
  # Use the official Python image as a base
31
  FROM python:3.10-slim-buster
32
 
33
+ # Install system dependencies required to build scikit-surprise
34
+ RUN apt-get update && apt-get install -y \
35
+ build-essential \
36
+ gcc \
37
+ python3-dev \
38
+ libxml2 \
39
+ libxmlsec1 \
40
+ libxslt1-dev \
41
+ libffi-dev \
42
+ && apt-get clean
43
+
44
  # Set the working directory in the container
45
  WORKDIR /app
46
 
 
48
  COPY . .
49
 
50
  # Install required packages
51
+ RUN pip install --upgrade pip
52
  RUN pip install -r requirements.txt
53
 
54
  # Expose the port that Streamlit uses
55
  EXPOSE 8501
56
 
57
  # Run the Streamlit app
58
+ CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
README.md CHANGED
@@ -8,8 +8,125 @@ sdk_version: 1.41.1
8
  app_file: app.py
9
  pinned: false
10
  license: apache-2.0
11
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
14
 
15
- # Welcome to Anime Recommendation system
 
8
  app_file: app.py
9
  pinned: false
10
  license: apache-2.0
11
+ ---
12
+
13
+ # Welcome to Anime Recommendation system
14
+
15
+ This is an **Anime Recommendation System** that combines multiple recommendation techniques such as **Collaborative Filtering**, **Content-Based Filtering**, and **Popularity-Based Filtering**. The system is designed to continuously ingest and transform data and is **dockerized** for easier deployment.
16
+
17
+ The system is hosted on **Hugging Face Spaces** and fetches datasets and pre-trained models from **Hugging Face Hub** to generate **personalized anime recommendations** based on user preferences and anime features.
18
+
19
+ ## Tech Stacks 🛠️
20
+
21
+ - **Python**: Main programming language used for building recommendation algorithms and Streamlit app.
22
+ - **Docker**: Containerizes the application to ensure a consistent environment across different platforms.
23
+ - **Streamlit**: For building and deploying the web app that serves the recommendations.
24
+ - **Hugging Face Spaces**: Hosts the Streamlit-based recommendation system.
25
+ - **Hugging Face Datasets**: Stores and retrieves anime datasets for processing.
26
+ - **Hugging Face Models**: Hosts the pre-trained recommendation models for inference.
27
+
28
+ ## Pipeline 🚀
29
+
30
+ The pipeline follows a structured sequence of steps to build an **Anime Recommendation System**, including data ingestion, transformation, and multiple recommendation models.
31
+
32
+ ### 1. Data Ingestion 📥
33
+ - Initiates the **data ingestion process**, where anime data is loaded from Hugging Face datasets.
34
+ - The ingested data is saved as artifacts in a local folder for further processing.
35
+
36
+ ### 2. Data Transformation 🔄
37
+ - Cleans, transforms, and processes the raw data into a structured format.
38
+ - Extracts important features required for **Content-Based Filtering** and prepares data for **Collaborative Filtering**.
39
+
40
+ ### 3. Collaborative Filtering 🤝
41
+ - Implements **three collaborative filtering models** to recommend anime based on user preferences:
42
+ - **Singular Value Decomposition (SVD)**: Factorizes the user-item interaction matrix to make personalized recommendations.
43
+ - **Item-Based K-Nearest Neighbors (Item-KNN)**: Recommends anime similar to a given anime based on user ratings.
44
+ - **User-Based K-Nearest Neighbors (User-KNN)**: Suggests anime that users with similar preferences have liked.
45
+ - The chosen model is trained using **transformed data**, and the final trained model is stored as an artifact.
46
+ - Once trained, it can generate recommendations for users or anime titles.
47
+
48
+ ### 4. Content-Based Filtering 🎭
49
+ - Uses extracted anime features like genres to train a **Content-Based Recommendation Model**.
50
+ - This model recommends anime similar to those a user has watched or liked.
51
+
52
+ ### 5. Popularity-Based Filtering ⭐
53
+ This recommendation system ranks anime based on various **popularity metrics**, making it ideal for users who want to discover trending or highly-rated shows **without needing personalized preferences**.
54
+
55
+ The system applies different filters to sort anime based on:
56
+
57
+ - **Most Popular** 🎭: Anime ranked by **popularity score**, highlighting the most widely recognized titles.
58
+ - **Top Ranked** 🏆: Highest-rated anime, based on **official ranking metrics**.
59
+ - **Overall Top Rated** ⭐: Best-rated anime, sorted by **average user ratings**.
60
+ - **Most Favorited** ❤️: Anime with the highest number of **favorites**, indicating strong fan appreciation.
61
+ - **Highest Member Count** 👥: Anime with the largest **viewer base**, showing widespread appeal.
62
+ - **Popular Among Members** 🔥: Anime with a **high number of members and strong ratings**, making them community favorites.
63
+ - **Highest Average Rating** 🎖️: Shows that have the **best average rating** after handling missing values.
64
+
65
+ ## Artifacts Storage 📂
66
+
67
+ All intermediate and final outputs, including processed datasets and trained models, are first saved locally in the **Artifacts** folder. These artifacts are then uploaded to **Hugging Face** for efficient storage and easy access.
68
+
69
+ When building the **Streamlit** app, these datasets and trained models are retrieved directly from **Hugging Face**, ensuring seamless integration and scalability.
70
+
71
+ - The datasets used in this project are available at:
72
+ - [Anime and User Ratings](https://www.kaggle.com/datasets/krishnaveniponna/anime-and-ratings-list-dataset-2023)
73
+
74
+ - You can find the Artifacts of trained models here:
75
+ - [Pre-trained Models](https://huggingface.co/krishnaveni76/anime-recommendation-models)
76
+
77
+ ## 🚀 Deployment on Hugging Face Spaces
78
+
79
+ This project is deployed using **Hugging Face Spaces**, which provides a seamless way to host **Streamlit applications**. The application pulls the datasets and trained models from Hugging Face and runs inside a **Docker container**.
80
+
81
+ ### Pre-requisites
82
+ - Docker
83
+ - Hugging Face (for datasets and trained models)
84
+ - Python 3.8+
85
+ - Hugging Face Spaces account
86
+
87
+ ### Local step 🔧
88
+ 1. **Clone the repository**
89
+ ```bash
90
+ git clone https://huggingface.co/spaces/krishnaveni76/Anime-Recommendation-System
91
+ cd Anime-Recommendation-System
92
+ ```
93
+ 2. **Set Up a Virtual Environment**:
94
+ ```bash
95
+ # For macOS and Linux:
96
+ python3 -m venv venv
97
+ # For Windows:
98
+ python -m venv venv
99
+ ```
100
+ 3. **Activate the Virtual Environment**:
101
+ ```bash
102
+ # For macOS and Linux:
103
+ source venv/bin/activate
104
+ # For Windows:
105
+ .\venv\Scripts\activate
106
+ ```
107
+ 4. **Install Required Dependencies**:
108
+ ```bash
109
+ pip install -r requirements.txt
110
+ ```
111
+
112
+ ### Running with Docker 🚀
113
+ To run the application inside a Docker container, follow these steps:
114
+
115
+ 1. Build the Docker Image
116
+ ```bash
117
+ docker build -t anime-recommendation-system .
118
+ ```
119
+ 2. Run the Docker Container
120
+ ```bash
121
+ docker run -p 8501:8501 anime-recommendation-system
122
+ ```
123
+ This will start the Streamlit application, which can be accessed at `http://localhost:8501`.
124
+
125
+ ### Contact 📫
126
+ For any questions, suggestions, or collaboration opportunities, feel free to reach out:
127
+
128
+ 📧Email: [email protected]
129
 
130
+ 🌐 LinkedIn: [Krishnaveni Ponna](https://www.linkedin.com/in/krishnaveni-ponna-28ab93239)
131
 
132
+ 🐦 Twitter: [@Krishnaveni076](https://x.com/Krishnaveni076)
app.py CHANGED
@@ -8,226 +8,235 @@ from anime_recommender.constant import *
8
  from huggingface_hub import hf_hub_download
9
  from datasets import load_dataset
10
 
11
- st.set_page_config(page_title="Anime Recommendation System", layout="wide")
12
-
13
- if "anime_data" not in st.session_state or "anime_user_ratings" not in st.session_state:
14
- # Load datasets from Hugging Face (assuming no splits)
15
- animedataset = load_dataset(ANIME_FILE_PATH, split=None)
16
- mergeddataset = load_dataset(ANIMEUSERRATINGS_FILE_PATH, split=None)
17
-
18
- # Convert the dataset to Pandas DataFrame
19
- st.session_state.anime_data = pd.DataFrame(animedataset["train"])
20
- st.session_state.anime_user_ratings = pd.DataFrame(mergeddataset["train"])
21
-
22
- # Load models only once
23
- if "models_loaded" not in st.session_state:
24
- st.session_state.models_loaded = {}
25
- # Load models
26
- st.session_state.models_loaded["cosine_similarity_model"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_COSINESIMILARITY_MODEL_NAME)
27
- st.session_state.models_loaded["item_based_knn_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_ITEM_KNN_TRAINED_MODEL_NAME)
28
- st.session_state.models_loaded["user_based_knn_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_USER_KNN_TRAINED_MODEL_NAME)
29
- st.session_state.models_loaded["svd_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_SVD_TRAINED_MODEL_NAME)
30
-
31
- # Load the models using joblib
32
- with open(st.session_state.models_loaded["item_based_knn_model_path"], "rb") as f:
33
- st.session_state.models_loaded["item_based_knn_model"] = joblib.load(f)
34
-
35
- with open(st.session_state.models_loaded["user_based_knn_model_path"], "rb") as f:
36
- st.session_state.models_loaded["user_based_knn_model"] = joblib.load(f)
37
-
38
- with open(st.session_state.models_loaded["svd_model_path"], "rb") as f:
39
- st.session_state.models_loaded["svd_model"] = joblib.load(f)
40
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  print("Models loaded successfully!")
42
-
43
- # Access the data from session state
44
- anime_data = st.session_state.anime_data
45
- anime_user_ratings = st.session_state.anime_user_ratings
46
-
47
- # # Display dataset info
48
- # st.write("Anime Data:")
49
- # st.dataframe(anime_data.head())
50
-
51
- # st.write("Anime User Ratings Data:")
52
- # st.dataframe(anime_user_ratings.head())
53
-
54
- # Access the models from session state
55
- cosine_similarity_model_path = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_COSINESIMILARITY_MODEL_NAME)
56
- item_based_knn_model = st.session_state.models_loaded["item_based_knn_model"]
57
- user_based_knn_model = st.session_state.models_loaded["user_based_knn_model"]
58
- svd_model = st.session_state.models_loaded["svd_model"]
59
- print("Models loaded successfully!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
- # Streamlit UI
62
- app_selector = st.sidebar.radio(
63
- "Select App", ("Content-Based Recommender", "Collaborative Recommender", "Top Anime Recommender")
64
- )
65
-
66
- if app_selector == "Content-Based Recommender":
67
- st.title("Content-Based Recommendation System")
68
- try:
69
 
70
- anime_list = anime_data["name"].tolist()
71
- anime_name = st.selectbox("Pick an anime..unlock similar anime recommendations..", anime_list)
72
-
73
- # Set number of recommendations
74
- max_recommendations = min(len(anime_data), 100)
75
- n_recommendations = st.slider("Number of Recommendations", 1, max_recommendations, 10)
76
-
77
- # Inject custom CSS for anime name font size
78
- st.markdown(
79
- """
80
- <style>
81
- .anime-title {
82
- font-size: 14px !important;
83
- font-weight: bold;
84
- text-align: center;
85
- margin-top: 5px;
86
- }
87
- </style>
88
- """,
89
- unsafe_allow_html=True,
90
- )
91
- # Get Recommendations
92
- if st.button("Get Recommendations"):
93
- try:
94
- recommender = ContentBasedRecommender(anime_data)
95
- recommendations = recommender.get_rec_cosine(anime_name, n_recommendations=n_recommendations,model_path=cosine_similarity_model_path)
96
-
97
- if isinstance(recommendations, str):
98
- st.warning(recommendations)
99
- elif recommendations.empty:
100
- st.warning("No recommendations found.")
101
- else:
102
- st.write(f"Here are the Content-based Recommendations for {anime_name}:")
 
 
103
  cols = st.columns(5)
104
  for i, row in enumerate(recommendations.iterrows()):
105
  col = cols[i % 5]
106
  with col:
107
  st.image(row[1]['Image URL'], use_container_width=True)
108
  st.markdown(
109
- f"<div class='anime-title'>{row[1]['Anime name']}</div>",
110
  unsafe_allow_html=True,
111
- )
112
- st.caption(f"Genres: {row[1]['Genres']} | Rating: {row[1]['Rating']}")
113
- except Exception as e:
114
- st.error(f"Unexpected error: {str(e)}")
115
-
116
- except Exception as e:
117
- st.error(f"Unexpected error: {str(e)}")
118
-
119
- elif app_selector == "Collaborative Recommender":
120
- st.title("Collaborative Recommender System")
121
-
122
- try:
123
- # Sidebar for choosing the collaborative filtering method
124
- collaborative_method = st.sidebar.selectbox(
125
- "Choose a collaborative filtering method:",
126
- ["SVD Collaborative Filtering", "User-Based Collaborative Filtering", "Anime-Based KNN Collaborative Filtering"]
127
- )
128
-
129
- # User input
130
- if collaborative_method == "SVD Collaborative Filtering" or collaborative_method == "User-Based Collaborative Filtering":
131
- user_ids = anime_user_ratings['user_id'].unique()
132
- user_id = st.selectbox("Choose a user, and we'll show you animes they'd recommend", user_ids)
133
- n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=50, value=10)
134
- elif collaborative_method == "Anime-Based KNN Collaborative Filtering":
135
- anime_list = anime_user_ratings["name"].dropna().unique().tolist()
136
- anime_name = st.selectbox("Pick an anime, and we'll suggest more titles you'll love", anime_list)
137
- n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=50, value=10)
138
-
139
- # Get recommendations
140
- if st.button("Get Recommendations"):
141
- # Load the recommender
142
- recommender = CollaborativeAnimeRecommender(anime_user_ratings)
143
- if collaborative_method == "SVD Collaborative Filtering":
144
- recommendations = recommender.get_svd_recommendations(user_id, n=n_recommendations, svd_model=svd_model)
145
- elif collaborative_method == "User-Based Collaborative Filtering":
146
- recommendations = recommender.get_user_based_recommendations(user_id, n_recommendations=n_recommendations, knn_user_model=user_based_knn_model)
147
- elif collaborative_method == "Anime-Based KNN Collaborative Filtering":
148
- if anime_name:
149
- recommendations = recommender.get_item_based_recommendations(anime_name, n_recommendations=n_recommendations, knn_item_model=item_based_knn_model)
150
  else:
151
- st.error("Invalid Anime Name. Please enter a valid anime title.")
152
-
153
- if isinstance(recommendations, pd.DataFrame) and not recommendations.empty:
154
- if len(recommendations) < n_recommendations:
155
- st.warning(f"Oops...Only {len(recommendations)} recommendations available, fewer than the requested {n_recommendations}.")
156
- st.write(f"Here are the Collaborative Recommendations:")
157
- cols = st.columns(5)
158
- for i, row in enumerate(recommendations.iterrows()):
159
- col = cols[i % 5]
160
- with col:
161
- st.image(row[1]['Image URL'], use_container_width=True)
162
- st.markdown(
163
- f"<div class='anime-title'>{row[1]['Anime Name']}</div>",
164
- unsafe_allow_html=True,
165
- )
166
- st.caption(f"Genres: {row[1]['Genres']} | Rating: {row[1]['Rating']}")
167
- else:
168
- st.error("No recommendations found.")
169
- except Exception as e:
170
- st.error(f"An error occurred: {e}")
171
-
172
-
173
- elif app_selector == "Top Anime Recommender":
174
- st.title("Top Anime Recommender System")
175
-
176
- try:
177
- # Sidebar for choosing the popularity-based filtering method
178
- popularity_method = st.sidebar.selectbox(
179
- "Choose a Popularity-Based Filtering method:",
180
- [
181
- "Popular Animes",
182
- "Top Ranked Animes",
183
- "Overall Top Rated Animes",
184
- "Favorite Animes",
185
- "Top Animes by Members",
186
- "Popular Anime Among Members",
187
- "Top Average Rated Animes",
188
- ]
189
- )
190
-
191
- n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=500, value=10)
192
 
193
- if st.button("Get Recommendations"):
194
- # Load the popularity-based recommender
195
- recommender = PopularityBasedFiltering(anime_data)
 
 
 
 
 
 
 
 
 
 
196
 
197
- # Get recommendations based on selected method
198
- if popularity_method == "Popular Animes":
199
- recommendations = recommender.popular_animes(n=n_recommendations)
200
- elif popularity_method == "Top Ranked Animes":
201
- recommendations = recommender.top_ranked_animes(n=n_recommendations)
202
- elif popularity_method == "Overall Top Rated Animes":
203
- recommendations = recommender.overall_top_rated_animes(n=n_recommendations)
204
- elif popularity_method == "Favorite Animes":
205
- recommendations = recommender.favorite_animes(n=n_recommendations)
206
- elif popularity_method == "Top Animes by Members":
207
- recommendations = recommender.top_animes_members(n=n_recommendations)
208
- elif popularity_method == "Popular Anime Among Members":
209
- recommendations = recommender.popular_anime_among_members(n=n_recommendations)
210
- elif popularity_method == "Top Average Rated Animes":
211
- recommendations = recommender.top_avg_rated(n=n_recommendations)
212
- else:
213
- st.error("Invalid selection. Please choose a valid method.")
214
- recommendations = None
215
 
216
- # Display recommendations
217
- if isinstance(recommendations, pd.DataFrame) and not recommendations.empty:
218
- st.write(f"Here are the {popularity_method}:")
219
- cols = st.columns(5)
220
- for i, row in recommendations.iterrows():
221
- col = cols[i % 5]
222
- with col:
223
- st.image(row['Image URL'], use_container_width=True)
224
- st.markdown(
225
- f"<div class='anime-title'>{row['Anime name']}</div>",
226
- unsafe_allow_html=True,
227
- )
228
- st.caption(f"Genres: {row['Genres']} | Rating: {row['Rating']}")
229
- else:
230
- st.error("No recommendations found.")
231
- except Exception as e:
232
- st.error(f"An error occurred: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
 
 
 
 
8
  from huggingface_hub import hf_hub_download
9
  from datasets import load_dataset
10
 
11
+ def run_app():
12
+ """
13
+ Initializes the Streamlit app, loads necessary datasets and models,
14
+ and provides a UI for anime recommendations based on three methods:
15
+ Content-Based, Collaborative, and Popularity-Based Filtering. 🎬🎮
16
+ """
17
+
18
+ # Set page configuration
19
+ st.set_page_config(page_title="Anime Recommendation System", layout="wide")
20
+
21
+ # Load datasets if not present in session state
22
+ if "anime_data" not in st.session_state or "anime_user_ratings" not in st.session_state:
23
+ # Load datasets from Hugging Face (assuming no splits)
24
+ animedataset = load_dataset(ANIME_FILE_PATH, split=None)
25
+ mergeddataset = load_dataset(ANIMEUSERRATINGS_FILE_PATH, split=None)
26
+
27
+ # Convert the dataset to Pandas DataFrame
28
+ st.session_state.anime_data = pd.DataFrame(animedataset["train"])
29
+ st.session_state.anime_user_ratings = pd.DataFrame(mergeddataset["train"])
30
+
31
+ # Load models only once
32
+ if "models_loaded" not in st.session_state:
33
+ st.session_state.models_loaded = {}
34
+ # Load models
35
+ st.session_state.models_loaded["cosine_similarity_model"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_COSINESIMILARITY_MODEL_NAME)
36
+ st.session_state.models_loaded["item_based_knn_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_ITEM_KNN_TRAINED_MODEL_NAME)
37
+ st.session_state.models_loaded["user_based_knn_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_USER_KNN_TRAINED_MODEL_NAME)
38
+ st.session_state.models_loaded["svd_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_SVD_TRAINED_MODEL_NAME)
39
+
40
+ # Load the models using joblib
41
+ with open(st.session_state.models_loaded["item_based_knn_model_path"], "rb") as f:
42
+ st.session_state.models_loaded["item_based_knn_model"] = joblib.load(f)
43
+
44
+ with open(st.session_state.models_loaded["user_based_knn_model_path"], "rb") as f:
45
+ st.session_state.models_loaded["user_based_knn_model"] = joblib.load(f)
46
+
47
+ with open(st.session_state.models_loaded["svd_model_path"], "rb") as f:
48
+ st.session_state.models_loaded["svd_model"] = joblib.load(f)
49
+
50
+ print("Models loaded successfully!")
51
+
52
+ # Access the data from session state
53
+ anime_data = st.session_state.anime_data
54
+ anime_user_ratings = st.session_state.anime_user_ratings
55
+
56
+ # # Display dataset info
57
+ # st.write("Anime Data:")
58
+ # st.dataframe(anime_data.head())
59
+
60
+ # st.write("Anime User Ratings Data:")
61
+ # st.dataframe(anime_user_ratings.head())
62
+
63
+ # Access the models from session state
64
+ cosine_similarity_model_path = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_COSINESIMILARITY_MODEL_NAME)
65
+ item_based_knn_model = st.session_state.models_loaded["item_based_knn_model"]
66
+ user_based_knn_model = st.session_state.models_loaded["user_based_knn_model"]
67
+ svd_model = st.session_state.models_loaded["svd_model"]
68
  print("Models loaded successfully!")
69
+
70
+ # Streamlit UI
71
+ app_selector = st.sidebar.radio(
72
+ "Select App", ("Content-Based Recommender", "Collaborative Recommender", "Top Anime Recommender")
73
+ )
74
+
75
+ # Content-Based Recommender App
76
+ if app_selector == "Content-Based Recommender":
77
+ st.title("Content-Based Recommendation System")
78
+ try:
79
+
80
+ anime_list = anime_data["name"].tolist()
81
+ anime_name = st.selectbox("Pick an anime..unlock similar anime recommendations..", anime_list)
82
+
83
+ # Set number of recommendations
84
+ max_recommendations = min(len(anime_data), 100)
85
+ n_recommendations = st.slider("Number of Recommendations", 1, max_recommendations, 10)
86
+
87
+ # Inject custom CSS for anime name font size
88
+ st.markdown(
89
+ """
90
+ <style>
91
+ .anime-title {
92
+ font-size: 14px !important;
93
+ font-weight: bold;
94
+ text-align: center;
95
+ margin-top: 5px;
96
+ }
97
+ </style>
98
+ """,
99
+ unsafe_allow_html=True,
100
+ )
101
+ # Get Recommendations
102
+ if st.button("Get Recommendations"):
103
+ try:
104
+ recommender = ContentBasedRecommender(anime_data)
105
+ recommendations = recommender.get_rec_cosine(anime_name, n_recommendations=n_recommendations,model_path=cosine_similarity_model_path)
106
+
107
+ if isinstance(recommendations, str):
108
+ st.warning(recommendations)
109
+ elif recommendations.empty:
110
+ st.warning("No recommendations found.🧐")
111
+ else:
112
+ st.write(f"Here are the Content-based Recommendations for {anime_name}:")
113
+ cols = st.columns(5)
114
+ for i, row in enumerate(recommendations.iterrows()):
115
+ col = cols[i % 5]
116
+ with col:
117
+ st.image(row[1]['Image URL'], use_container_width=True)
118
+ st.markdown(
119
+ f"<div class='anime-title'>{row[1]['Anime name']}</div>",
120
+ unsafe_allow_html=True,
121
+ )
122
+ st.caption(f"Genres: {row[1]['Genres']} | Rating: {row[1]['Rating']}")
123
+ except Exception as e:
124
+ st.error(f"Unexpected error: {str(e)}")
125
 
126
+ except Exception as e:
127
+ st.error(f"Unexpected error: {str(e)}")
128
+
129
+ elif app_selector == "Collaborative Recommender":
130
+ st.title("Collaborative Recommender System 🧑‍🤝‍🧑💬")
 
 
 
131
 
132
+ try:
133
+ # Sidebar for choosing the collaborative filtering method
134
+ collaborative_method = st.sidebar.selectbox(
135
+ "Choose a collaborative filtering method:",
136
+ ["SVD Collaborative Filtering", "User-Based Collaborative Filtering", "Anime-Based KNN Collaborative Filtering"]
137
+ )
138
+
139
+ # User input
140
+ if collaborative_method == "SVD Collaborative Filtering" or collaborative_method == "User-Based Collaborative Filtering":
141
+ user_ids = anime_user_ratings['user_id'].unique()
142
+ user_id = st.selectbox("Choose a user, and we'll show you animes they'd recommend", user_ids)
143
+ n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=50, value=10)
144
+ elif collaborative_method == "Anime-Based KNN Collaborative Filtering":
145
+ anime_list = anime_user_ratings["name"].dropna().unique().tolist()
146
+ anime_name = st.selectbox("Pick an anime, and we'll suggest more titles you'll love", anime_list)
147
+ n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=50, value=10)
148
+
149
+ # Get recommendations
150
+ if st.button("Get Recommendations"):
151
+ # Load the recommender
152
+ recommender = CollaborativeAnimeRecommender(anime_user_ratings)
153
+ if collaborative_method == "SVD Collaborative Filtering":
154
+ recommendations = recommender.get_svd_recommendations(user_id, n=n_recommendations, svd_model=svd_model)
155
+ elif collaborative_method == "User-Based Collaborative Filtering":
156
+ recommendations = recommender.get_user_based_recommendations(user_id, n_recommendations=n_recommendations, knn_user_model=user_based_knn_model)
157
+ elif collaborative_method == "Anime-Based KNN Collaborative Filtering":
158
+ if anime_name:
159
+ recommendations = recommender.get_item_based_recommendations(anime_name, n_recommendations=n_recommendations, knn_item_model=item_based_knn_model)
160
+ else:
161
+ st.error("Invalid Anime Name. Please enter a valid anime title.")
162
+
163
+ if isinstance(recommendations, pd.DataFrame) and not recommendations.empty:
164
+ if len(recommendations) < n_recommendations:
165
+ st.warning(f"Oops...Only {len(recommendations)} recommendations available, fewer than the requested {n_recommendations}.")
166
+ st.write(f"Here are the {collaborative_method} Recommendations:")
167
  cols = st.columns(5)
168
  for i, row in enumerate(recommendations.iterrows()):
169
  col = cols[i % 5]
170
  with col:
171
  st.image(row[1]['Image URL'], use_container_width=True)
172
  st.markdown(
173
+ f"<div class='anime-title'>{row[1]['Anime Name']}</div>",
174
  unsafe_allow_html=True,
175
+ )
176
+ st.caption(f"Genres: {row[1]['Genres']} | Rating: {row[1]['Rating']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  else:
178
+ st.error("No recommendations found.")
179
+ except Exception as e:
180
+ st.error(f"An error occurred: {e}")
181
+
182
+ elif app_selector == "Top Anime Recommender":
183
+ st.title("Top Anime Recommender System 🌟🔥")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
 
185
+ try:
186
+ popularity_method = st.sidebar.selectbox(
187
+ "Choose a Popularity-Based Filtering method:",
188
+ [
189
+ "Popular Animes",
190
+ "Top Ranked Animes",
191
+ "Overall Top Rated Animes",
192
+ "Favorite Animes",
193
+ "Top Animes by Members",
194
+ "Popular Anime Among Members",
195
+ "Top Average Rated Animes",
196
+ ]
197
+ )
198
 
199
+ n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=500 , value=10)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
+ if st.button("Get Recommendations"):
202
+ recommender = PopularityBasedFiltering(anime_data)
203
+
204
+ # Get recommendations based on selected method
205
+ if popularity_method == "Popular Animes":
206
+ recommendations = recommender.popular_animes(n=n_recommendations)
207
+ elif popularity_method == "Top Ranked Animes":
208
+ recommendations = recommender.top_ranked_animes(n=n_recommendations)
209
+ elif popularity_method == "Overall Top Rated Animes":
210
+ recommendations = recommender.overall_top_rated_animes(n=n_recommendations)
211
+ elif popularity_method == "Favorite Animes":
212
+ recommendations = recommender.favorite_animes(n=n_recommendations)
213
+ elif popularity_method == "Top Animes by Members":
214
+ recommendations = recommender.top_animes_members(n=n_recommendations)
215
+ elif popularity_method == "Popular Anime Among Members":
216
+ recommendations = recommender.popular_anime_among_members(n=n_recommendations)
217
+ elif popularity_method == "Top Average Rated Animes":
218
+ recommendations = recommender.top_avg_rated(n=n_recommendations)
219
+ else:
220
+ st.error("Invalid selection. Please choose a valid method.")
221
+ recommendations = None
222
+
223
+ # Display recommendations
224
+ if isinstance(recommendations, pd.DataFrame) and not recommendations.empty:
225
+ st.write(f" Here are the Recommendations:")
226
+ cols = st.columns(5)
227
+ for i, row in recommendations.iterrows():
228
+ col = cols[i % 5]
229
+ with col:
230
+ st.image(row['Image URL'], use_container_width=True)
231
+ st.markdown(
232
+ f"<div class='anime-title'>{row['Anime name']}</div>",
233
+ unsafe_allow_html=True,
234
+ )
235
+ st.caption(f"Genres: {row['Genres']} | Rating: {row['Rating']}")
236
+ else:
237
+ st.error("No recommendations found.")
238
+ except Exception as e:
239
+ st.error(f"An error occurred: {e}")
240
 
241
+ if __name__ == "__main__":
242
+ run_app()