seyia92coding's picture
Update app.py
5bcbd08
# -*- coding: utf-8 -*-
"""HS_Text-based_Recom_Metacritic.ipynb
Automatically generated by Colaboratory.
Original file is located at
https://colab.research.google.com/drive/1MmWRwRJT04GVAO2SKCpwSqQ2bWghVGtQ
"""
import pandas as pd
import numpy as np
from fuzzywuzzy import fuzz
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
df = pd.read_csv("Metacritic_Reviews_Only.csv", error_bad_lines=False, encoding='utf-8')
#Remove title from review
def remove_title(row):
game_title = row['Game Title']
body_text = row['Reviews']
new_doc = body_text.replace(game_title, "")
return new_doc
df['Reviews'] = df.apply(remove_title, axis=1)
#drop redundant column
df = df.drop(['Unnamed: 0'], axis=1)
df.dropna(inplace=True) #Drop Null Reviews
# Instantiate the vectorizer object to the vectorizer variable
#Minimum word count 2 to be included, words that appear in over 70% of docs should not be included
vectorizer = TfidfVectorizer(min_df=2, max_df=0.7)
# Fit and transform the plot column
vectorized_data = vectorizer.fit_transform(df['Reviews'])
# Create Dataframe from TF-IDFarray
tfidf_df = pd.DataFrame(vectorized_data.toarray(), columns=vectorizer.get_feature_names())
# Assign the game titles to the index
tfidf_df.index = df['Game Title']
# Find the cosine similarity measures between all game and assign the results to cosine_similarity_array.
cosine_similarity_array = cosine_similarity(tfidf_df)
# Create a DataFrame from the cosine_similarity_array with tfidf_df.index as its rows and columns.
cosine_similarity_df = pd.DataFrame(cosine_similarity_array, index=tfidf_df.index, columns=tfidf_df.index)
# create a function to find the closest title
def matching_score(a,b):
#fuzz.ratio(a,b) calculates the Levenshtein Distance between a and b, and returns the score for the distance
return fuzz.ratio(a,b)
# exactly the same, the score becomes 100
#Convert index to title_year
def get_title_from_index(index):
return df[df.index == index]['Game Title'].values[0]
# A function to return the most similar title to the words a user type
# Without this, the recommender only works when a user enters the exact title which the data has.
def find_closest_title(title):
#matching_score(a,b) > a is the current row, b is the title we're trying to match
leven_scores = list(enumerate(df['Game Title'].apply(matching_score, b=title))) #[(0, 30), (1,95), (2, 19)~~] A tuple of distances per index
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)~~]
closest_title = get_title_from_index(sorted_leven_scores[0][0])
distance_score = sorted_leven_scores[0][1]
return closest_title, distance_score
# Bejeweled Twist, 100
#find_closest_title('Batman Arkham Knight')
"""# Build Recommender Function
Our 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.
By combining everything we've done from building the user profile onwards we will pull out the Top 5 games we want to recommend.
1. Text Match the closest title in the dataset
2. Assign number for the final ranking
3. Create your user profile based on previous games
4. Create TFIDF subset without previously mentioned titles
5. Calculate cosine similarity based on selected titles and convert back into DataFrame
6. Sort DataFrame by similarity
7. Return most similarity game titles that don't contain keyword
"""
def recommend_games(game1, game2, game3, keyword1, keyword2, keyword3, max_results):
#Insert closest title here
title1, distance_score1 = find_closest_title(game1)
title2, distance_score2 = find_closest_title(game2)
title3, distance_score3 = find_closest_title(game3)
#Counter for Ranking
number = 1
print('Recommended because you played {}, {} and {}:\n'.format(title1, title2, title3))
list_of_games_enjoyed = [title1, title2, title3]
games_enjoyed_df = tfidf_df.reindex(list_of_games_enjoyed)
user_prof = games_enjoyed_df.mean()
tfidf_subset_df = tfidf_df.drop([title1, title2, title3], axis=0)
similarity_array = cosine_similarity(user_prof.values.reshape(1, -1), tfidf_subset_df)
similarity_df = pd.DataFrame(similarity_array.T, index=tfidf_subset_df.index, columns=["similarity_score"])
# Sort the values from high to low by the values in the similarity_score
sorted_similarity_df = similarity_df.sort_values(by="similarity_score", ascending=False)
# Inspect the most similar to the user preferences
print("Without Keywords Exclusions:")
print(sorted_similarity_df.head())
print("\n")
print("With Keywords Exclusions:\n ")
number = 0
rank = 1
for n in sorted_similarity_df.index:
if rank <= max_results:
if keyword1.lower() not in n.lower() and keyword2.lower() not in n.lower() and keyword3.lower() not in n.lower():
print("#" + str(rank) + ": " + n + ", " + str(round(sorted_similarity_df.iloc[number]['similarity_score']*100,2)) + "% " + "match")
number+=1
rank +=1
else:
continue
# recommend_games('Mortal Kombat', 'Street Fighter', 'Overwatch', 'Kombat', 'Fighter', 'Overwatch', 5)
import gradio as gr
recommender_interface = gr.Interface(fn=recommend_games,
inputs=["text","text","text","text","text","text", gr.inputs.Slider(1, 20, step=1)],
title="Text-based Recommendation Engine for Video Games",
description="""This is a Recommendation Engine based on the review texts of Metacritic critics for games between 2011-2019.
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.""",
examples= [['Mortal Kombat', 'Street Fighter', 'Overwatch', 'Kombat', 'Fighter', 'Overwatch', 5],
["Batman Arkham Knight","Dying Light","Left 4 Dead","Batman","Dying","Left", 10],
["Mario Kart","Zelda","Final Fantasy","Mario","Zelda","Final", 7]],
outputs=["dataframe"])
recommender_interface.launch(debug=True)