File size: 11,684 Bytes
b2773c3
 
db5542d
 
 
b2773c3
db5542d
b2773c3
 
 
 
 
 
 
db5542d
 
b2773c3
 
 
 
 
db5542d
 
f7871c8
db5542d
93e62a0
 
 
 
db5542d
 
 
 
 
 
 
 
 
 
 
 
 
b2773c3
 
 
 
f7871c8
 
 
b2773c3
f7871c8
 
 
db5542d
93e62a0
db5542d
 
 
b2773c3
 
 
 
 
 
 
 
f7871c8
b2773c3
 
 
f7871c8
b2773c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db5542d
b2773c3
 
 
8c4c8f9
b2773c3
 
 
8c4c8f9
 
 
b2773c3
 
f7871c8
 
b2773c3
 
 
 
 
 
8c4c8f9
 
b2773c3
8c4c8f9
b2773c3
 
 
 
 
 
 
 
f7871c8
b2773c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c4c8f9
b2773c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2f0782
b2773c3
f7871c8
b2773c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import pandas as pd
import streamlit as st
from anime_recommender.model_trainer.content_based_modelling import ContentBasedRecommender
from anime_recommender.model_trainer.collaborative_modelling import CollaborativeAnimeRecommender
from anime_recommender.model_trainer.top_anime_filtering import PopularityBasedFiltering
import joblib
from anime_recommender.constant import *
from huggingface_hub import hf_hub_download
from datasets import load_dataset

st.set_page_config(page_title="Anime Recommendation System", layout="wide")

if "anime_data" not in st.session_state or "anime_user_ratings" not in st.session_state:
    # Load datasets from Hugging Face (assuming no splits)
    animedataset = load_dataset(ANIME_FILE_PATH, split=None)
    mergeddataset = load_dataset(ANIMEUSERRATINGS_FILE_PATH, split=None)

    # Convert the dataset to Pandas DataFrame
    st.session_state.anime_data = pd.DataFrame(animedataset["train"])
    st.session_state.anime_user_ratings = pd.DataFrame(mergeddataset["train"]) 

# Load models only once
if "models_loaded" not in st.session_state:
    st.session_state.models_loaded = {} 
    # Load models
    st.session_state.models_loaded["cosine_similarity_model"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_COSINESIMILARITY_MODEL_NAME)
    st.session_state.models_loaded["item_based_knn_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_ITEM_KNN_TRAINED_MODEL_NAME)
    st.session_state.models_loaded["user_based_knn_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_USER_KNN_TRAINED_MODEL_NAME)
    st.session_state.models_loaded["svd_model_path"] = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_SVD_TRAINED_MODEL_NAME)

    # Load the models using joblib
    with open(st.session_state.models_loaded["item_based_knn_model_path"], "rb") as f:
        st.session_state.models_loaded["item_based_knn_model"] = joblib.load(f)

    with open(st.session_state.models_loaded["user_based_knn_model_path"], "rb") as f:
        st.session_state.models_loaded["user_based_knn_model"] = joblib.load(f)

    with open(st.session_state.models_loaded["svd_model_path"], "rb") as f:
        st.session_state.models_loaded["svd_model"] = joblib.load(f)

    print("Models loaded successfully!")

# Access the data from session state
anime_data = st.session_state.anime_data 
anime_user_ratings = st.session_state.anime_user_ratings

# # Display dataset info
# st.write("Anime Data:")
# st.dataframe(anime_data.head())
 
# st.write("Anime User Ratings Data:")
# st.dataframe(anime_user_ratings.head())
  
# Access the models from session state
cosine_similarity_model_path = hf_hub_download(MODELS_FILEPATH, MODEL_TRAINER_COSINESIMILARITY_MODEL_NAME)
item_based_knn_model = st.session_state.models_loaded["item_based_knn_model"]
user_based_knn_model = st.session_state.models_loaded["user_based_knn_model"]
svd_model = st.session_state.models_loaded["svd_model"] 
print("Models loaded successfully!")
    
# Streamlit UI
app_selector = st.sidebar.radio(
    "Select App", ("Content-Based Recommender", "Collaborative Recommender", "Top Anime Recommender")
)

if app_selector == "Content-Based Recommender":
    st.title("Content-Based Recommendation System") 
    try:
        
        anime_list = anime_data["name"].tolist()
        anime_name = st.selectbox("Pick an anime..unlock similar anime recommendations..", anime_list)

        # Set number of recommendations
        max_recommendations = min(len(anime_data), 100)
        n_recommendations = st.slider("Number of Recommendations", 1, max_recommendations, 10)

        # Inject custom CSS for anime name font size
        st.markdown(
            """
            <style>
            .anime-title {
                font-size: 14px !important;
                font-weight: bold;
                text-align: center;
                margin-top: 5px;
            }
            </style>
            """,
            unsafe_allow_html=True,
        ) 
        # Get Recommendations
        if st.button("Get Recommendations"):
            try:
                recommender = ContentBasedRecommender(anime_data)
                recommendations = recommender.get_rec_cosine(anime_name, n_recommendations=n_recommendations,model_path=cosine_similarity_model_path)

                if isinstance(recommendations, str):
                    st.warning(recommendations)
                elif recommendations.empty:
                    st.warning("No recommendations found.")
                else:
                    st.write(f"Here are the Content-based Recommendations for {anime_name}:") 
                    cols = st.columns(5)
                    for i, row in enumerate(recommendations.iterrows()):
                        col = cols[i % 5]
                        with col:
                            st.image(row[1]['Image URL'], use_container_width=True)
                            st.markdown(
                                f"<div class='anime-title'>{row[1]['Anime name']}</div>",
                                unsafe_allow_html=True,
                            )
                            st.caption(f"Genres: {row[1]['Genres']} | Rating: {row[1]['Rating']}") 
            except Exception as e:
                st.error(f"Unexpected error: {str(e)}")
 
    except Exception as e:
        st.error(f"Unexpected error: {str(e)}")

elif app_selector == "Collaborative Recommender":
    st.title("Collaborative Recommender System")
    
    try:  
        # Sidebar for choosing the collaborative filtering method
        collaborative_method = st.sidebar.selectbox(
            "Choose a collaborative filtering method:", 
            ["SVD Collaborative Filtering", "User-Based Collaborative Filtering", "Anime-Based KNN Collaborative Filtering"]
        )

        # User input
        if collaborative_method == "SVD Collaborative Filtering" or collaborative_method == "User-Based Collaborative Filtering": 
            user_ids = anime_user_ratings['user_id'].unique()  
            user_id = st.selectbox("Choose a user, and we'll show you animes they'd recommend", user_ids) 
            n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=50, value=10)
        elif collaborative_method == "Anime-Based KNN Collaborative Filtering": 
            anime_list = anime_user_ratings["name"].dropna().unique().tolist() 
            anime_name = st.selectbox("Pick an anime, and we'll suggest more titles you'll love", anime_list)
            n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=50, value=10)
   
        # Get recommendations
        if st.button("Get Recommendations"):
            # Load the recommender
            recommender = CollaborativeAnimeRecommender(anime_user_ratings) 
            if collaborative_method == "SVD Collaborative Filtering": 
                recommendations = recommender.get_svd_recommendations(user_id, n=n_recommendations, svd_model=svd_model)  
            elif collaborative_method == "User-Based Collaborative Filtering": 
                recommendations = recommender.get_user_based_recommendations(user_id, n_recommendations=n_recommendations, knn_user_model=user_based_knn_model)
            elif collaborative_method == "Anime-Based KNN Collaborative Filtering":
                if anime_name: 
                    recommendations = recommender.get_item_based_recommendations(anime_name, n_recommendations=n_recommendations, knn_item_model=item_based_knn_model)
                else:
                    st.error("Invalid Anime Name. Please enter a valid anime title.")
            
            if isinstance(recommendations, pd.DataFrame) and not recommendations.empty:
                if len(recommendations) < n_recommendations:
                    st.warning(f"Oops...Only {len(recommendations)} recommendations available, fewer than the requested {n_recommendations}.")
                st.write(f"Here are the Collaborative Recommendations:")
                cols = st.columns(5)
                for i, row in enumerate(recommendations.iterrows()):
                    col = cols[i % 5]
                    with col:
                        st.image(row[1]['Image URL'], use_container_width=True)
                        st.markdown(
                            f"<div class='anime-title'>{row[1]['Anime Name']}</div>",
                            unsafe_allow_html=True,
                        ) 
                        st.caption(f"Genres: {row[1]['Genres']} | Rating: {row[1]['Rating']}")
            else:
                st.error("No recommendations found.")
    except Exception as e:
        st.error(f"An error occurred: {e}")


elif app_selector == "Top Anime Recommender":
    st.title("Top Anime Recommender System")
    
    try:
        # Sidebar for choosing the popularity-based filtering method
        popularity_method = st.sidebar.selectbox(
            "Choose a Popularity-Based Filtering method:",
            [
                "Popular Animes",
                "Top Ranked Animes",
                "Overall Top Rated Animes",
                "Favorite Animes",
                "Top Animes by Members",
                "Popular Anime Among Members",
                "Top Average Rated Animes",
            ]
        )
        
        n_recommendations = st.slider("Number of Recommendations:", min_value=1, max_value=500, value=10)
        
        if st.button("Get Recommendations"):
            # Load the popularity-based recommender
            recommender = PopularityBasedFiltering(anime_data)
            
            # Get recommendations based on selected method
            if popularity_method == "Popular Animes":
                recommendations = recommender.popular_animes(n=n_recommendations)
            elif popularity_method == "Top Ranked Animes":
                recommendations = recommender.top_ranked_animes(n=n_recommendations)
            elif popularity_method == "Overall Top Rated Animes":
                recommendations = recommender.overall_top_rated_animes(n=n_recommendations)
            elif popularity_method == "Favorite Animes":
                recommendations = recommender.favorite_animes(n=n_recommendations)
            elif popularity_method == "Top Animes by Members":
                recommendations = recommender.top_animes_members(n=n_recommendations)
            elif popularity_method == "Popular Anime Among Members":
                recommendations = recommender.popular_anime_among_members(n=n_recommendations)
            elif popularity_method == "Top Average Rated Animes":
                recommendations = recommender.top_avg_rated(n=n_recommendations)
            else:
                st.error("Invalid selection. Please choose a valid method.")
                recommendations = None
            
            # Display recommendations
            if isinstance(recommendations, pd.DataFrame) and not recommendations.empty:
                st.write(f"Here are the {popularity_method}:")
                cols = st.columns(5)
                for i, row in recommendations.iterrows():
                    col = cols[i % 5]
                    with col:
                        st.image(row['Image URL'], use_container_width=True)
                        st.markdown(
                            f"<div class='anime-title'>{row['Anime name']}</div>",
                            unsafe_allow_html=True,
                        )
                        st.caption(f"Genres: {row['Genres']} | Rating: {row['Rating']}")
            else:
                st.error("No recommendations found.")
    except Exception as e:
        st.error(f"An error occurred: {e}")