seyia92coding/Simple-Text-based-Gaming-Recommender
1
1# -*- coding: utf-8 -*-2"""HS_Text-based_Recom_Metacritic.ipynb3 4Automatically generated by Colaboratory.5 6Original file is located at7 https://colab.research.google.com/drive/1MmWRwRJT04GVAO2SKCpwSqQ2bWghVGtQ8"""9 10import pandas as pd11import numpy as np12from fuzzywuzzy import fuzz13from sklearn.feature_extraction.text import TfidfVectorizer14from sklearn.metrics.pairwise import cosine_similarity15 16df = pd.read_csv("Metacritic_Reviews_Only.csv", error_bad_lines=False, encoding='utf-8')17 18#Remove title from review19def remove_title(row):20 game_title = row['Game Title']21 body_text = row['Reviews']22 new_doc = body_text.replace(game_title, "")23 return new_doc24 25df['Reviews'] = df.apply(remove_title, axis=1)26#drop redundant column27df = df.drop(['Unnamed: 0'], axis=1)28 29df.dropna(inplace=True) #Drop Null Reviews30 31# Instantiate the vectorizer object to the vectorizer variable32#Minimum word count 2 to be included, words that appear in over 70% of docs should not be included33vectorizer = TfidfVectorizer(min_df=2, max_df=0.7)34 35# Fit and transform the plot column36vectorized_data = vectorizer.fit_transform(df['Reviews'])37 38# Create Dataframe from TF-IDFarray39tfidf_df = pd.DataFrame(vectorized_data.toarray(), columns=vectorizer.get_feature_names())40 41# Assign the game titles to the index42tfidf_df.index = df['Game Title']43 44# Find the cosine similarity measures between all game and assign the results to cosine_similarity_array.45cosine_similarity_array = cosine_similarity(tfidf_df)46 47# Create a DataFrame from the cosine_similarity_array with tfidf_df.index as its rows and columns.48cosine_similarity_df = pd.DataFrame(cosine_similarity_array, index=tfidf_df.index, columns=tfidf_df.index)49 50# create a function to find the closest title51def matching_score(a,b):52 #fuzz.ratio(a,b) calculates the Levenshtein Distance between a and b, and returns the score for the distance53 return fuzz.ratio(a,b)54 # exactly the same, the score becomes 10055 56#Convert index to title_year57def get_title_from_index(index):58 return df[df.index == index]['Game Title'].values[0]59 60# A function to return the most similar title to the words a user type61# Without this, the recommender only works when a user enters the exact title which the data has.62def find_closest_title(title):63 #matching_score(a,b) > a is the current row, b is the title we're trying to match64 leven_scores = list(enumerate(df['Game Title'].apply(matching_score, b=title))) #[(0, 30), (1,95), (2, 19)~~] A tuple of distances per index65 sorted_leven_scores = sorted(leven_scores, key=lambda x: x[1], reverse=True) #Sorts list of tuples by distance [(1, 95), (3, 49), (0, 30)~~]66 closest_title = get_title_from_index(sorted_leven_scores[0][0])67 distance_score = sorted_leven_scores[0][1]68 return closest_title, distance_score69 # Bejeweled Twist, 10070 71#find_closest_title('Batman Arkham Knight')72 73"""# Build Recommender Function74 75Our recommender function will take in two inputs. The game title and the keyword exclusion. The keyword exclusion was added when I realised that the recommendations were returning a lot of DLCs and sequels which isn't a very useful recommender.76 77 78By combining everything we've done from building the user profile onwards we will pull out the Top 5 games we want to recommend.79 80 811. Text Match the closest title in the dataset822. Assign number for the final ranking833. Create your user profile based on previous games844. Create TFIDF subset without previously mentioned titles855. Calculate cosine similarity based on selected titles and convert back into DataFrame866. Sort DataFrame by similarity877. Return most similarity game titles that don't contain keyword88"""89 90def recommend_games(game1, game2, game3, keyword1, keyword2, keyword3, max_results):91 #Insert closest title here92 title1, distance_score1 = find_closest_title(game1)93 title2, distance_score2 = find_closest_title(game2)94 title3, distance_score3 = find_closest_title(game3)95 #Counter for Ranking96 number = 197 print('Recommended because you played {}, {} and {}:\n'.format(title1, title2, title3))98 99 list_of_games_enjoyed = [title1, title2, title3]100 games_enjoyed_df = tfidf_df.reindex(list_of_games_enjoyed)101 user_prof = games_enjoyed_df.mean()102 103 tfidf_subset_df = tfidf_df.drop([title1, title2, title3], axis=0)104 similarity_array = cosine_similarity(user_prof.values.reshape(1, -1), tfidf_subset_df)105 similarity_df = pd.DataFrame(similarity_array.T, index=tfidf_subset_df.index, columns=["similarity_score"])106 107 # Sort the values from high to low by the values in the similarity_score108 sorted_similarity_df = similarity_df.sort_values(by="similarity_score", ascending=False)109 110 # Inspect the most similar to the user preferences111 print("Without Keywords Exclusions:")112 print(sorted_similarity_df.head())113 print("\n")114 print("With Keywords Exclusions:\n ")115 116 number = 0117 rank = 1118 119 for n in sorted_similarity_df.index:120 if rank <= max_results:121 if keyword1.lower() not in n.lower() and keyword2.lower() not in n.lower() and keyword3.lower() not in n.lower():122 print("#" + str(rank) + ": " + n + ", " + str(round(sorted_similarity_df.iloc[number]['similarity_score']*100,2)) + "% " + "match")123 number+=1124 rank +=1125 else:126 continue127 128 129# recommend_games('Mortal Kombat', 'Street Fighter', 'Overwatch', 'Kombat', 'Fighter', 'Overwatch', 5)130 131import gradio as gr132 133recommender_interface = gr.Interface(fn=recommend_games, 134 inputs=["text","text","text","text","text","text", gr.inputs.Slider(1, 20, step=1)], 135 title="Text-based Recommendation Engine for Video Games", 136 description="""This is a Recommendation Engine based on the review texts of Metacritic critics for games between 2011-2019.137 You need to enter 3 games you've enjoyed playing followed by 3 keywords from those game titles so that I can avoid recommending the same games to you.""",138 examples= [['Mortal Kombat', 'Street Fighter', 'Overwatch', 'Kombat', 'Fighter', 'Overwatch', 5],139 ["Batman Arkham Knight","Dying Light","Left 4 Dead","Batman","Dying","Left", 10],140 ["Mario Kart","Zelda","Final Fantasy","Mario","Zelda","Final", 7]],141 outputs=["dataframe"])142 143recommender_interface.launch(debug=True)