diff --git a/edsa_recommender.py b/edsa_recommender.py index f1192112..8730b3d2 100644 --- a/edsa_recommender.py +++ b/edsa_recommender.py @@ -36,6 +36,7 @@ from utils.data_loader import load_movie_titles from recommenders.collaborative_based import collab_model from recommenders.content_based import content_model +from recommenders.matrix_mult import matrix_mult_model # Data Loading title_list = load_movie_titles('resources/data/movies.csv') @@ -45,7 +46,7 @@ def main(): # DO NOT REMOVE the 'Recommender System' option below, however, # you are welcome to add more options to enrich your app. - page_options = ["Recommender System","Solution Overview"] + page_options = ["Recommender System","Solution Overview","Movie Mate","About Us", "Exploratory Data Analysis"] # ------------------------------------------------------------------- # ----------- !! THIS CODE MUST NOT BE ALTERED !! ------------------- @@ -101,9 +102,156 @@ def main(): # ------------- SAFE FOR ALTERING/EXTENSION ------------------- if page_selection == "Solution Overview": + # st.title("Solution Overview") st.title("Solution Overview") - st.write("Describe your winning approach on this page") + st.image('resources/imgs/S1.PNG',use_column_width=True) + + st.info("Section 1: Utilizing AI for Recommender Systems") + + st.write("Solution: Implement advanced AI-powered algorithms for movie recommendation systems to enhance user experience.") + st.write("In today's technology-driven world, recommender systems play a crucial role in helping users make appropriate content choices daily. To provide seamless movie recommendations, we propose utilizing AI to power these systems. Major streaming platforms like Netflix, Amazon Prime, and Disney already leverage AI to analyze user behavior and preferences, ensuring the delivery of tailored content suggestions.") + + st.info("Section 2: Section 2: Learning User Ratings and Watch History") + + st.write("Solution: Analyze user ratings and watch history to understand individual preferences accurately.") + st.write("A well-designed movie recommendation system deeply analyzes user ratings and watch history. By employing intelligent algorithms, we can process this data to curate personalized movie lists. Understanding users' historical interactions allows the system to learn their preferences and refine future recommendations, ensuring a more satisfying movie-watching experience.") + + + st.info("Section 3: Providing Accurate Recommendations") + + st.write("Solution: AI-powered algorithms offer accurate recommendations, boosting user satisfaction and platform revenue.") + st.write("Accurate recommendations are key to increasing user satisfaction and platform affinity. By harnessing the power of AI, our system will curate content that aligns precisely with users' tastes. The personalized movie lists will not only enhance content consumption but also drive revenue for streaming platforms through increased user engagement.") + + + if page_selection == "About Us": + st.title("About Us") + + st.write("We are a team of data scientists passionate about giving you the best movie experience.") + st.write("Our goal is to provide the best Movie recommendatiosn for users across our platforms.") + + st.image('resources/imgs/comp.PNG',use_column_width=True) + + st.header("Team Members") + # Create three columns + col1, col2, col3 = st.columns(3) + desc1, desc2, desc3 = st.columns(3) + col4, col5, col6 = st.columns(3) + desc4,desc5,desc6 = st.columns(3) + + # Place the images in separate columns + col1.image("resources/imgs/aa.jpg", caption="Chief Data Scientist", width=200) + col3.image("resources/imgs/sm.jpg", caption="Chief Administrative Officer", width=200) + col2.image("resources/imgs/aag.jpg", caption="Chief Technical Officer", width=200) + + desc1.subheader("Abdulmalik Adeyemo") + desc1.write("Abdulmalik is an experienced data scientist. He has a strong background in machine learning and deep learning.") + + desc2.subheader("Ayomide Aladetuyi") + desc2.write("Ayomide is an experienced data analyst specializing in drawing insights from data. He has a strong background in Finance.") + + desc3.subheader("Setshaba Mashigo") + desc3.write("Setshaba is an experienced data expert specializing in modelling. He has a strong background in Quality Assesment.") + + col4.image("resources/imgs/os.jpg", caption="Senior Developer", width=200) + # col5.image("resources/l.jpg", caption="Market Researcher", width=200) + + desc4.subheader("Olaniyi Samuel") + desc4.write("Olaniyi is an experienced administrative specialist specialized in presenting amazing insights and presentations.") + # + desc5.subheader("Seye Tare Garanwei") + desc5.write("Seye is our Market researcher. He has a strong background in Market research.") + + + if page_selection == "Exploratory Data Analysis": + st.info("Exploratory Data Analysis") + st.write("1. Movie ratings play a crucial role in guiding audiences' choices and determining a film's success or failure. Understanding the distribution of movie ratings is essential for filmmakers, studios, and critics alike. In this analysis, we delve into the distribution of movie ratings and uncover a fascinating trend that sheds light on user preferences and the overall positivity of the ratings landscape.") + st.write("a. The majority of movies (1) receive ratings higher than the average, suggesting a favorable reception among audiences. This might be influenced by selection bias, leading to inflated ratings for well-received films.") + st.write("b. Most frequently assigned ratings include 3.0, 4.0, and 5.0 (2), representing positive thresholds. High ratings near 5.0 indicate outstanding films that leave a lasting impression, influenced by social factors.") + st.write("c. The left-skewed distribution of ratings (3) confirms the positive landscape, with fewer negative ratings. This could be due to users rating films they enjoyed and neglecting poorly received movies.") + st.write("d. Users prefer whole numbers (4) over decimals when rating movies, possibly due to simplicity and the psychological impact of round numbers, making it easier to express their opinions") + st.image('resources/imgs/eda1.png',use_column_width=True) + + st.write("2. In the dynamic world of movie ratings, understanding the trends across different time periods can provide valuable insights into audience preferences and cultural influences. In this analysis, we explore the quantity of ratings received by movies from different decades, with a particular focus on the 1990s. It is important to note that this study does not assess the sentiment or quality of the ratings; rather, it aims to highlight the popularity and enduring appeal of 90's movies based on the sheer number of ratings they have accumulated.") + st.write("a. Movies from the 1990s receive the highest quantity of ratings, reflecting their lasting global impact.") + st.write("b. The popularity of 90's movies stems from their cultural significance and nostalgia as cultural touchstones.") + st.write("c. Accessibility through streaming platforms boosts ratings, as viewers easily discover and rate these classics.") + st.write("d. 90's movies continue to captivate newer audiences, cementing their position as enduring rating favorites.") + st.image('resources/imgs/eda2.png',use_column_width=True) + + st.write("3.The realm of cinema has continually captivated audiences with its ability to transport them to worlds filled with excitement, wonder, and thrill. Among the vast array of films, certain masterpieces rise above the rest, garnering accolades and admiration from critics and viewers alike. In this write-up, we delve into the highest-rated movies, with special focus on the top two films—parts I and II of Planet Earth—providing insights into their genres and the reasons behind their overwhelming success.") + st.write("a. Common genres like action, adventure, and thriller dominate highly-rated movies, captivating audiences with adrenaline-pumping narratives and compelling storytelling. Understanding this preference is crucial for grasping cinematic appeal and the success of these captivating films.") + st.write("b. Planet Earth parts I and IIs unparalleled success exemplifies the genres allure. With extraordinary efforts and visionary storytelling, the series showcases breathtaking landscapes and natures wonders, immersing audiences in Earths raw beauty and diverse ecosystems.") + st.write("c. Action-Packed Adventure: The Planet Earth series is an action-packed adventure, immersing viewers in gripping encounters between predators and prey. Exploring remote and challenging terrains, the series captures heart-stopping moments, from breathtaking aerial chases to dramatic hunts, showcasing the raw survival instincts of Earth's inhabitants. Audiences are left on the edge of their seats, experiencing the thrill of the chase as if they were witnessing it firsthand.") + st.write("d. Thrills in the Natural World: Planet Earth series delivers unparalleled thrills through intimate portrayals of the animal kingdom. Filmmakers capture rare footage of animals in their natural habitats, evoking empathy and awe as viewers witness the beauty and fragility of wildlife, leading to a deeper understanding of Earth's delicate ecological balance") + st.image('resources/imgs/eda3.png',use_column_width=True) + + st.write("4.The genres of movies, when considered as an isolated feature, have minimal determining influence on the ratings they receive. This is evident from the comparable distributions observed in both the top 100 and bottom 100 rated movies. These movies exhibit similar genre compositions with similar frequencie.") + st.write("a. Genres have minimal isolated influence on movie ratings. Analyzing top 100 and bottom 100 rated films shows similar genre distributions, suggesting specific genres don't guarantee high or low ratings. Other factors play a more significant role in determining a movie's success. The presence of genres alone doesn't define audience reception. Filmmakers should focus on storytelling, performances, direction, and production quality to impact ratings positively") + st.write("b.The top 100 and bottom 100 rated movies have comparable genre compositions and frequencies. This indicates that genres alone don't heavily influence a film's reception. Other factors like storytelling, performances, direction, and production quality play a more significant role in determining audience response.") + st.image('resources/imgs/eda4.png',use_column_width=True) + + # st.subheader("Data Cleaning") + + if page_selection == "Movie Mate": + # Header contents + st.write('# Movie Mate Recommender') + st.write('### Team RR Movie Recommender Model ') + st.image('resources/imgs/moviemate.PNG',use_column_width=True) + # Recommender System algorithm selection + # sys = st.radio("Select an algorithm", + # ( + # # 'Content Based Filtering', + # # 'Collaborative Filtering (SVD)', + # 'Movie-Mate Recommender')) + + # User-based preferences + st.write('### Enter Your Three Favorite Movies') + movie_1 = st.selectbox('Fisrt Option',title_list[14930:15200]) + movie_2 = st.selectbox('Second Option',title_list[25055:25255]) + movie_3 = st.selectbox('Third Option',title_list[21100:21200]) + fav_movies = [movie_1,movie_2,movie_3] + + # Perform top-10 movie recommendation generation + # if sys == 'Content Based Filtering': + # if st.button("Recommend"): + # try: + # with st.spinner('Crunching the numbers...'): + # top_recommendations = content_model(movie_list=fav_movies, + # top_n=10) + # st.title("We think you'll like:") + # for i,j in enumerate(top_recommendations): + # st.subheader(str(i+1)+'. '+j) + # except: + # st.error("Oops! Looks like this algorithm does't work.\ + # We'll need to fix it!") + + + # if sys == 'Collaborative Filtering (SVD)': + # if st.button("Recommend"): + # try: + # with st.spinner('Crunching the numbers...'): + # top_recommendations = collab_model(movie_list=fav_movies, + # top_n=10) + # st.title("We think you'll like:") + # for i,j in enumerate(top_recommendations): + # st.subheader(str(i+1)+'. '+j) + # except: + # st.error("Oops! Looks like this algorithm does't work.\ + # We'll need to fix it!") + + # if sys == 'Movie-Mate Recommender': + if st.button("Recommend"): + try: + with st.spinner('Crunching the numbers...'): + top_recommendations = matrix_mult_model(movie_list=fav_movies, + top_n=10) + st.title("We think you'll like:") + for i,j in enumerate(top_recommendations): + st.subheader(str(i+1)+'. '+j) + except: + st.error("Oops! Looks like this algorithm does't work.\ + We'll need to fix it!") # You may want to add more sections here for aspects such as an EDA, # or to provide your business pitch. diff --git a/recommenders/collaborative_based.py b/recommenders/collaborative_based.py index 861b5d8f..ed95eb7d 100644 --- a/recommenders/collaborative_based.py +++ b/recommenders/collaborative_based.py @@ -30,73 +30,99 @@ # Script dependencies import pandas as pd import numpy as np -import pickle +# import pickle import copy -from surprise import Reader, Dataset -from surprise import SVD, NormalPredictor, BaselineOnly, KNNBasic, NMF -from sklearn.metrics.pairwise import cosine_similarity -from sklearn.feature_extraction.text import CountVectorizer +# from surprise import Reader, Dataset +# from surprise import SVD, NormalPredictor, BaselineOnly, KNNBasic, NMF +# from sklearn.metrics.pairwise import cosine_similarity +# from sklearn.feature_extraction.text import CountVectorizer -# Importing data -movies_df = pd.read_csv('resources/data/movies.csv',sep = ',') -ratings_df = pd.read_csv('resources/data/ratings.csv') -ratings_df.drop(['timestamp'], axis=1,inplace=True) - -# We make use of an SVD model trained on a subset of the MovieLens 10k dataset. -model=pickle.load(open('resources/models/SVD.pkl', 'rb')) - -def prediction_item(item_id): - """Map a given favourite movie to users within the - MovieLens dataset with the same preference. - - Parameters - ---------- - item_id : int - A MovieLens Movie ID. - - Returns - ------- - list - User IDs of users with similar high ratings for the given movie. +import pathlib +import fastai +from fastai.collab import * +from fastai.tabular.all import * - """ - # Data preprosessing - reader = Reader(rating_scale=(0, 5)) - load_df = Dataset.load_from_df(ratings_df,reader) - a_train = load_df.build_full_trainset() - predictions = [] - for ui in a_train.all_users(): - predictions.append(model.predict(iid=item_id,uid=ui, verbose = False)) - return predictions +# for windows deployment +# temp = pathlib.PosixPath +# pathlib.PosixPath = pathlib.WindowsPath -def pred_movies(movie_list): - """Maps the given favourite movies selected within the app to corresponding - users within the MovieLens dataset. - Parameters - ---------- - movie_list : list - Three favourite movies selected by the app user. +#For linux deployment +plt = platform.system() +if plt == 'Linux': + pathlib.WindowsPath = pathlib.PosixPath +else: + temp = pathlib.PosixPath + pathlib.PosixPath = pathlib.WindowsPath - Returns - ------- - list - User-ID's of users with similar high ratings for each movie. +# Importing data +# movies_df = pd.read_csv('resources/data/movies.csv',sep = ',') +# ratings_df = pd.read_csv('resources/data/ratings.csv') +# ratings_df.drop(['timestamp'], axis=1,inplace=True) - """ - # Store the id of users - id_store=[] - # For each movie selected by a user of the app, - # predict a corresponding user within the dataset with the highest rating - for i in movie_list: - predictions = prediction_item(item_id = i) - predictions.sort(key=lambda x: x.est, reverse=True) - # Take the top 10 user id's from each movie with highest rankings - for pred in predictions[:10]: - id_store.append(pred.uid) - # Return a list of user id's - return id_store +# We make use of an SVD model trained on a subset of the MovieLens 10k dataset. +# model=pickle.load(open('resources/models/SVD.pkl', 'rb')) +learn = load_learner("resources/models/learn.pkl") +dls = torch.load("resources/data/dls.pkl") + +movie_factors = learn.model.i_weight.weight +movies_title = dls.classes['title'] +movie_bias = learn.model.i_bias.weight.squeeze() + +# reader = Reader(rating_scale=(0, 5)) +# load_df = Dataset.load_from_df(ratings_df,reader) +# a_train = load_df.build_full_trainset() +# def prediction_item(item_id): +# """Map a given favourite movie to users within the +# MovieLens dataset with the same preference. + +# Parameters +# ---------- +# item_id : int +# A MovieLens Movie ID. + +# Returns +# ------- +# list +# User IDs of users with similar high ratings for the given movie. + +# """ +# # Data preprosessing + + +# predictions = [] +# for ui in a_train.all_users(): +# predictions.append(model.predict(iid=item_id,uid=ui, verbose = False)) +# return predictions + +# def pred_movies(movie_list): +# """Maps the given favourite movies selected within the app to corresponding +# users within the MovieLens dataset. + +# Parameters +# ---------- +# movie_list : list +# Three favourite movies selected by the app user. + +# Returns +# ------- +# list +# User-ID's of users with similar high ratings for each movie. + +# """ +# # Store the id of users +# id_store=[] +# # For each movie selected by a user of the app, +# # predict a corresponding user within the dataset with the highest rating +# for i in movie_list: +# predictions = prediction_item(item_id = i) +# predictions.sort(key=lambda x: x.est, reverse=True) +# # Take the top 10 user id's from each movie with highest rankings +# for pred in predictions[:10]: +# id_store.append(pred.uid) +# # Return a list of user id's +# return id_store # !! DO NOT CHANGE THIS FUNCTION SIGNATURE !! # You are, however, encouraged to change its content. @@ -118,31 +144,36 @@ def collab_model(movie_list,top_n=10): """ - indices = pd.Series(movies_df['title']) - movie_ids = pred_movies(movie_list) - df_init_users = ratings_df[ratings_df['userId']==movie_ids[0]] - for i in movie_ids : - df_init_users=df_init_users.append(ratings_df[ratings_df['userId']==i]) - # Getting the cosine similarity matrix - cosine_sim = cosine_similarity(np.array(df_init_users), np.array(df_init_users)) - idx_1 = indices[indices == movie_list[0]].index[0] - idx_2 = indices[indices == movie_list[1]].index[0] - idx_3 = indices[indices == movie_list[2]].index[0] - # Creating a Series with the similarity scores in descending order - rank_1 = cosine_sim[idx_1] - rank_2 = cosine_sim[idx_2] - rank_3 = cosine_sim[idx_3] - # Calculating the scores - score_series_1 = pd.Series(rank_1).sort_values(ascending = False) - score_series_2 = pd.Series(rank_2).sort_values(ascending = False) - score_series_3 = pd.Series(rank_3).sort_values(ascending = False) - # Appending the names of movies - listings = score_series_1.append(score_series_1).append(score_series_3).sort_values(ascending = False) - recommended_movies = [] - # Choose top 50 - top_50_indexes = list(listings.iloc[1:50].index) - # Removing chosen movies - top_indexes = np.setdiff1d(top_50_indexes,[idx_1,idx_2,idx_3]) - for i in top_indexes[:top_n]: - recommended_movies.append(list(movies_df['title'])[i]) - return recommended_movies + # indices = pd.Series(movies_df['title']) + # user_ids = pred_movies(movie_list) + # df_init_users = ratings_df[ratings_df['userId']==user_ids[0]] + # for i in user_ids[1:]: + # df_init_users = pd.concat([df_init_users, ratings_df[ratings_df['userId']==i]]) + + # # Sort the DataFrame based on the 'ratings' column in descending order + # top_rated = df_init_users.sort_values(by='rating', ascending=False) + + # top_movieIds = top_rated['movieId'].head(top_n).values + + # movie_id_mask = movies_df['movieId'].isin(top_movieIds) + + # # Filter the rows and select the 'title' column + # recommended_movies = movies_df.loc[movie_id_mask, 'title'].tolist() + + # return recommended_movies + + avail_movies = [movie for movie in movie_list if movie in movies_title] + recommendations = [] + if len(avail_movies)>0: + for movie in movie_list: + idx = movies_title.o2i[movie] + distances = nn.CosineSimilarity(dim=1)(movie_factors, movie_factors[idx][None]) + idx = distances.argsort(descending=True)[:top_n] + recommendations.extend(list(movies_title[idx])) + random.shuffle(recommendations) + return recommendations[:top_n] + else: + idxs = movie_bias.argsort(descending=True)[:top_n] + recommendations = [movies_title[i] for i in idxs] + random.shuffle(recommendations) + return recommendations diff --git a/recommenders/content_based.py b/recommenders/content_based.py index ed7df363..f3c1c8d6 100644 --- a/recommenders/content_based.py +++ b/recommenders/content_based.py @@ -59,6 +59,14 @@ def data_preprocessing(subset_size): movies_subset = movies[:subset_size] return movies_subset + +data = data_preprocessing(27000) +# Instantiating and generating the count matrix +count_vec = CountVectorizer() +count_matrix = count_vec.fit_transform(data['keyWords']) +indices = pd.Series(data['title']) +cosine_sim = cosine_similarity(count_matrix, count_matrix) + # !! DO NOT CHANGE THIS FUNCTION SIGNATURE !! # You are, however, encouraged to change its content. def content_model(movie_list,top_n=10): @@ -80,12 +88,13 @@ def content_model(movie_list,top_n=10): """ # Initializing the empty list of recommended movies recommended_movies = [] - data = data_preprocessing(27000) - # Instantiating and generating the count matrix - count_vec = CountVectorizer() - count_matrix = count_vec.fit_transform(data['keyWords']) - indices = pd.Series(data['title']) - cosine_sim = cosine_similarity(count_matrix, count_matrix) + # 27000 + # data = data_preprocessing(27000) + # # Instantiating and generating the count matrix + # count_vec = CountVectorizer() + # count_matrix = count_vec.fit_transform(data['keyWords']) + # indices = pd.Series(data['title']) + # cosine_sim = cosine_similarity(count_matrix, count_matrix) # Getting the index of the movie that matches the title idx_1 = indices[indices == movie_list[0]].index[0] idx_2 = indices[indices == movie_list[1]].index[0] @@ -98,8 +107,11 @@ def content_model(movie_list,top_n=10): score_series_1 = pd.Series(rank_1).sort_values(ascending = False) score_series_2 = pd.Series(rank_2).sort_values(ascending = False) score_series_3 = pd.Series(rank_3).sort_values(ascending = False) + # print(type(score_series_1)) + # print(type(score_series_2)) # Getting the indexes of the 10 most similar movies - listings = score_series_1.append(score_series_1).append(score_series_3).sort_values(ascending = False) + # listings = score_series_1.append(score_series_1).append(score_series_3).sort_values(ascending = False) + listings = pd.concat([score_series_1, score_series_1, score_series_3]).sort_values(ascending=False) # Store movie names recommended_movies = [] diff --git a/recommenders/matrix_mult.py b/recommenders/matrix_mult.py new file mode 100644 index 00000000..2e658b91 --- /dev/null +++ b/recommenders/matrix_mult.py @@ -0,0 +1,108 @@ +""" + + Collaborative-based filtering for item recommendation. + + Author: Explore Data Science Academy. + + Note: + --------------------------------------------------------------------- + Please follow the instructions provided within the README.md file + located within the root of this repository for guidance on how to use + this script correctly. + + NB: You are required to extend this baseline algorithm to enable more + efficient and accurate computation of recommendations. + + !! You must not change the name and signature (arguments) of the + prediction function, `collab_model` !! + + You must however change its contents (i.e. add your own collaborative + filtering algorithm), as well as altering/adding any other functions + as part of your improvement. + + --------------------------------------------------------------------- + + Description: Provided within this file is a baseline collaborative + filtering algorithm for rating predictions on Movie data. + +""" + +# Script dependencies +import pandas +import numpy as np +import pickle +import copy +from surprise import Reader, Dataset +from surprise import SVD, NormalPredictor, BaselineOnly, KNNBasic, NMF +from sklearn.metrics.pairwise import cosine_similarity +from sklearn.feature_extraction.text import CountVectorizer + +import pathlib +import fastai +from fastai.collab import * +from fastai.tabular.all import * + + +# for windows deployment +# temp = pathlib.PosixPath +# pathlib.PosixPath = pathlib.WindowsPath + + +#For linux deployment +plt = platform.system() +if plt == 'Linux': + pathlib.WindowsPath = pathlib.PosixPath +else: + temp = pathlib.PosixPath + pathlib.PosixPath = pathlib.WindowsPath + +# Importing data +# movies_df = pd.read_csv('resources/data/movies.csv',sep = ',') +# ratings_df = pd.read_csv('resources/data/ratings.csv') +# ratings_df.drop(['timestamp'], axis=1,inplace=True) + +# We make use of an SVD model trained on a subset of the MovieLens 10k dataset. +# model=pickle.load(open('resources/models/SVD.pkl', 'rb')) +learn = load_learner("resources/models/learn.pkl") +dls = torch.load("resources/data/dls.pkl") + +movie_factors = learn.model.i_weight.weight +movie_bias = learn.model.i_bias.weight.squeeze() +movies_title = dls.classes['title'] + + +# !! DO NOT CHANGE THIS FUNCTION SIGNATURE !! +# You are, however, encouraged to change its content. +def matrix_mult_model(movie_list,top_n=10): + """Performs Collaborative filtering based upon a list of movies supplied + by the app user. + + Parameters + ---------- + movie_list : list (str) + Favorite movies chosen by the app user. + top_n : type + Number of top recommendations to return to the user. + + Returns + ------- + list (str) + Titles of the top-n movie recommendations to the user. + + """ + + avail_movies = [movie for movie in movie_list if movie in movies_title] + recommendations = [] + if len(avail_movies)>0: + for movie in movie_list: + idx = movies_title.o2i[movie] + distances = nn.CosineSimilarity(dim=1)(movie_factors, movie_factors[idx][None]) + idx = distances.argsort(descending=True)[:top_n] + recommendations.extend(list(movies_title[idx])) + random.shuffle(recommendations) + return recommendations[:top_n] + else: + idxs = movie_bias.argsort(descending=True)[:top_n] + recommendations = [movies_title[i] for i in idxs] + random.shuffle(recommendations) + return recommendations diff --git a/resources/data/dls.pkl b/resources/data/dls.pkl new file mode 100644 index 00000000..997caec4 Binary files /dev/null and b/resources/data/dls.pkl differ diff --git a/resources/imgs/S1.PNG b/resources/imgs/S1.PNG new file mode 100644 index 00000000..14f6c6f0 Binary files /dev/null and b/resources/imgs/S1.PNG differ diff --git a/resources/imgs/aa.jpg b/resources/imgs/aa.jpg new file mode 100644 index 00000000..c1f774e1 Binary files /dev/null and b/resources/imgs/aa.jpg differ diff --git a/resources/imgs/aag.jpg b/resources/imgs/aag.jpg new file mode 100644 index 00000000..0d38d3f8 Binary files /dev/null and b/resources/imgs/aag.jpg differ diff --git a/resources/imgs/aag_old.jpg b/resources/imgs/aag_old.jpg new file mode 100644 index 00000000..9a12b84d Binary files /dev/null and b/resources/imgs/aag_old.jpg differ diff --git a/resources/imgs/comp.PNG b/resources/imgs/comp.PNG new file mode 100644 index 00000000..0dd2eefb Binary files /dev/null and b/resources/imgs/comp.PNG differ diff --git a/resources/imgs/moviemate.PNG b/resources/imgs/moviemate.PNG new file mode 100644 index 00000000..26630166 Binary files /dev/null and b/resources/imgs/moviemate.PNG differ diff --git a/resources/imgs/os.jpg b/resources/imgs/os.jpg new file mode 100644 index 00000000..9cd10ca6 Binary files /dev/null and b/resources/imgs/os.jpg differ diff --git a/resources/imgs/sm.jpg b/resources/imgs/sm.jpg new file mode 100644 index 00000000..ad1c5637 Binary files /dev/null and b/resources/imgs/sm.jpg differ diff --git a/resources/models/learn.pkl b/resources/models/learn.pkl new file mode 100644 index 00000000..3c93c2d0 Binary files /dev/null and b/resources/models/learn.pkl differ