Empfehlungssysteme: User-based Collaborative Filtering using N Nearest Neighbors

Ashay Pathak
Ashay Pathak

Follow

Feb 25, 2019 – 9 min read

Ashay Pathak, Chatana Mandava, Ritesh Patel

Collaborative Filtering ist eine Technik, die in Empfehlungssystemen weit verbreitet ist und ein schnell fortschreitendes Forschungsgebiet darstellt. Die beiden am häufigsten verwendeten Methoden sind speicherbasiert und modellbasiert.

In diesem Beitrag werden wir uns nur auf (User-Based Collaborative Filtering) UB-CF konzentrieren, eine speicherbasierte Methode. Die Hauptidee hinter UB-CF ist, dass Menschen mit ähnlichen Merkmalen einen ähnlichen Geschmack haben. Wenn Sie beispielsweise unserem Freund Bob einen Film empfehlen wollen, nehmen wir an, dass Bob und ich viele Filme zusammen gesehen haben und sie fast identisch bewerten. Es macht Sinn zu denken, dass wir auch in Zukunft ähnliche Filme mögen werden und diese Ähnlichkeitsmetrik nutzen, um Filme zu empfehlen.

Lassen Sie uns versuchen, UB-CF zu implementieren und eine Liste von Filmen zu generieren, die unser Freund Bob a.k.a. aktiver Benutzer gerne sehen würde. Die Motivation, diesen Beitrag zu schreiben, besteht darin, tief in den Algorithmus einzutauchen und zu verstehen, wie UB-CF tatsächlich funktioniert. Der größte Teil des Inhalts dieses Beitrags ist von einem Kurs auf Coursera inspiriert.

User-User Collaborative Filtering

Die Methode identifiziert Benutzer, die dem abgefragten Benutzer ähnlich sind und schätzt die gewünschte Bewertung als gewichteten Durchschnitt der Bewertungen dieser ähnlichen Benutzer.

Collaborative Filtering : source here

Wir würden die Empfehlungen auf dem MovieLens Dataset durchführen. Die verwendete Programmiersprache ist Python und die Datenanalyse wird hauptsächlich mit der Pandas-Bibliothek durchgeführt. Die verwendete IDE ist jupyter notebook.

Bevor wir beginnen, möchte ich die Liste der verwendeten Bibliotheken aufführen:

  1. Pandas
  2. Numpy
  3. sklearn

Lassen Sie uns also fortfahren und die Konzepte hinter den Empfehlungen verstehen. Zum besseren Verständnis habe ich einige Codeschnipsel und Ausgaben im Blog angehängt. Die gesamte ipynb-Datei ist am Ende des Blogs angehängt.

Score-Funktion

Es ist einfach, eine Funktion für nicht-personalisierte kollaborative Filterung zu entwickeln (d.h. wir berücksichtigen nicht die Vorlieben, Abneigungen und Bewertungen des aktiven Benutzers aus der Vergangenheit), die eine Punktzahl für den Benutzer u und den Artikel i als Eingabeparameter liefert. Die Funktion gibt eine Punktzahl aus, die angibt, wie stark ein Nutzer u den Artikel i mag/bevorzugt.

Dies geschieht also in der Regel anhand der Bewertungen anderer Personen, die dem Nutzer ähnlich sind. Dies alles wird später im Detail besprochen. Im Moment ist die Formel, die ich verwendet habe,

Score-Funktion

wobei ‘s’ der vorhergesagte Score ist, ‘u’ der Benutzer, ‘i’ der Artikel, ‘r’ die vom Benutzer abgegebene Bewertung und ‘w’ die Gewichtung ist.

In diesem Fall ist unsere Punktzahl gleich der Summe der Bewertungen, die jeder Benutzer für diesen Gegenstand abgegeben hat, abzüglich der durchschnittlichen Bewertung dieses Benutzers, multipliziert mit einer Gewichtung, die angibt, wie sehr dieser Benutzer den Vorhersagen anderer Benutzer ähnlich ist oder zu ihnen beitragen soll. Dies ist die Gewichtung zwischen Benutzer u und v. Die Punktzahl liegt zwischen 0 und 1, wobei 0 niedrig und 1 hoch ist. Alles sieht perfekt aus, aber warum haben wir dann die durchschnittlichen Bewertungen von den Bewertungen der einzelnen Nutzer abgezogen und warum haben wir den gewichteten Durchschnitt anstelle des einfachen Mittelwerts verwendet?

Das Problem liegt in den Arten von Nutzern, die wir behandeln. Es fängt damit an, dass die Leute oft auf sehr unterschiedlichen Skalen bewerten. Ich bin vielleicht ein positiver und optimistischer Nutzer, der einen Film, der ihm gefallen hat, mit 4 von 5 Punkten bewertet, aber ein anderer Nutzer, der weniger optimistisch ist oder hohe Ansprüche hat, bewertet seinen Lieblingsfilm mit 2 von 5 Punkten. Hier ist seine 2 meine 4. Wir können die Effizienz dieses Algorithmus erhöhen, wenn wir die Bewertungen der Benutzer normalisieren. Eine Möglichkeit, dies zu tun, besteht darin, s(u,i) zu berechnen, d.h. die durchschnittliche Bewertung, die der Benutzer für jeden Artikel abgibt, plus eine gewisse Abweichung, wobei die Abweichung angibt, um wie viel dieser Artikel besser oder schlechter als der Durchschnitt ist.

Ich habe die Kosinusähnlichkeit verwendet, um die Gewichtung in der obigen Formel zu berechnen. Ich habe auch den Begriff der Nachbarschaft verwendet, der in diesem Blog im weiteren Verlauf besprochen wird.

Um die Daten auf die oben beschriebene Weise zu normalisieren, ist eine Datenanalyse in Pandas erforderlich. Sie können den gesamten Code am Ende erhalten. Für den Blog werde ich mich auf die wichtigsten Konzepte konzentrieren.

import pandas as pdmovies = pd.read_csv("movies.csv",encoding="Latin1")
Ratings = pd.read_csv("ratings.csv")
Tags = pd.read_csv("tags.csv",encoding="Latin1")Mean = Ratings.groupby(by="userId",as_index=False).mean()
Rating_avg = pd.merge(Ratings,Mean,on='userId')
Rating_avg=Rating_avg-Rating_avg
Rating_avg.head()

Normalisierte Bewertungen

So, jetzt sind wir fertig mit der Berechnung der normalisierten Bewertung für einen Benutzer. Die obigen Daten werden später verwendet, um die endgültige Punktzahl für den Benutzer zu berechnen.

Ab hier werden wir uns nun auf einige wichtige Konzepte im Zusammenhang mit Empfehlungssystemen konzentrieren.

Cosinusähnlichkeit

Für die obige Formel müssen wir die Benutzer finden, die ähnliche Gedanken haben. Das klingt so interessant, um einen Benutzer zu finden, der ähnliche Vorlieben und Abneigungen hat. Aber wie finden wir die Ähnlichkeit?

Um dies zu beantworten, verwenden wir die Cosinus-Ähnlichkeit und sehen, wie ähnlich sich die Nutzer sind. Sie wird normalerweise über die Bewertungen berechnet, die beide Benutzer in der Vergangenheit abgegeben haben.

In unserem Beispiel habe ich die Funktion cosine_similarity von sklearn verwendet, um die Ähnlichkeit zu berechnen. Zuvor müssen wir jedoch einige Vorverarbeitungen durchführen und die Daten bereinigen.

from sklearn.metrics.pairwise import cosine_similarityfinal=pd.pivot_table(Rating_avg,values='adg_rating',index='userId',columns='movieId')

Pivot-Tabelle

Diese enthält viele NaN-Werte, da nicht jeder Benutzer alle Filme gesehen hat. Daher wird diese Art von Matrix als spärliche Matrix bezeichnet. Methoden wie die Matrixfaktorisierung werden verwendet, um mit dieser Spärlichkeit umzugehen, aber wir werden uns in diesem Blog nicht darauf konzentrieren. Der nächste und einer der wichtigsten Schritte besteht darin, diese NaN-Werte zu ersetzen.

Hierfür gibt es zwei Methoden, die üblicherweise verwendet werden:

  1. Verwenden Sie den Benutzer-Durchschnitt über die Zeile.
  2. Verwenden Sie den Film-Durchschnitt über die Spalte.

Ich habe beide Methoden verwendet, und Sie können sie im Code unten sehen. Aber zur Erklärung würde ich die Film-Durchschnittsmethode verwenden.

# Replacing NaN by Movie Average
final_movie = final.fillna(final.mean(axis=0))

Ersetzen von NaN-Werten durch Film-Durchschnitt

Der nächste Schritt ist nun die Berechnung der Ähnlichkeit zwischen den Benutzern.

# user similarity on replacing NAN by item(movie) avg
cosine = cosine_similarity(final_movie)
np.fill_diagonal(cosine, 0 )
similarity_with_movie =pd.DataFrame(cosine,index=final_movie.index)
similarity_with_movie.columns=final_user.index
similarity_with_movie.head()

Nutzer-Nutzer-Kosinus-Ähnlichkeit

Lassen Sie uns selbst überprüfen, ob das, was wir berechnet haben, wirklich Sinn macht !!

a = get_user_similar_movies(370,86309)
a = a.loc]
a.head()

Filme ähnlich

Aus dem obigen Bild können wir sehen, dass die Ähnlichkeit, die wir generiert haben, wahr ist, da die beiden gegebenen Benutzer (370,86309) fast die gleichen Bewertungen und Likes haben.

So, wir sind fertig mit der Berechnung der Ähnlichkeiten zwischen den Benutzern, aber ich bin immer noch nicht zufrieden. Den Grund dafür werde ich im nächsten Schritt erörtern.

Nachbarschaft für Benutzer (K)

Aus dem obigen Beispiel können wir ersehen, dass wir die Ähnlichkeiten für alle Benutzer berechnet haben. Aber da ich Big Data studiere, treibt mich die Komplexität des Problems immer wieder an. Damit meine ich, dass das Empfehlungssystem mit riesigen Daten arbeitet und es daher sehr wichtig ist, nur die wichtigen und notwendigen Highlights aus den Daten zu erhalten und zu erfassen.

Um dies anhand unseres Beispiels des Filmempfehlungssystems zu erklären, ist die oben erhaltene Matrix (862*862), da es 862 eindeutige Benutzer in den Daten gibt. Diese Zahl ist immer noch klein im Vergleich zu den Daten, mit denen das ursprüngliche System arbeiten würde. Denken wir an Amazon. Das Unternehmen hat mehr als Millionen von Nutzern in seiner Datenbank, so dass es bei der Berechnung der Punktzahl für einen Artikel keine gute Lösung oder Methode wäre, ständig alle anderen Nutzer zu berücksichtigen. Um dieses Problem zu lösen, entwickeln wir einen Begriff der Nachbarschaft. Dieser umfasst nur die Menge der (K) ähnlichen Benutzer für einen bestimmten Benutzer.

Nun lassen Sie uns weitere Schritte unternehmen, um die Idee zu implementieren. In unserem Beispiel habe ich den Wert von k als 30 angenommen. Wir hätten also 30 nächste Nachbarn für alle Benutzer.

Ich habe meine benutzerdefinierte Funktion find_n_neighbours verwendet, die die Ähnlichkeitsmatrix und den Wert von n als Eingabe nimmt und die nächsten n Nachbarn für alle Benutzer zurückgibt. Sie finden den Code im Notebook am Ende des Blogs.

# top 30 neighbours for each user
sim_user_30_m = find_n_neighbours(similarity_with_movie,30)
sim_user_30_m.head()

Top 30 Nachbarn für Benutzer

So, wenn Sie jetzt denken, dann haben wir die Anzahl der unnötigen Berechnungen stark reduziert. Jetzt sind wir bereit, die Punktzahl für ein Element zu berechnen.

Erstellen der endgültigen Punktzahl S(u,i)

Wow! wir sind mit dem Prozess fertig. Ich weiß, dass wir uns durch einige wirklich technische Dinge durchgekämpft haben, aber die Zeit, die wir investiert haben, ist es wert, da wir den letzten Schritt erreicht haben.

Hier werden wir versuchen, die Punktzahl für den Film vorherzusagen, den der gegebene Benutzer noch nicht gesehen hat.

score = User_item_score(320,7371)
print(score)

Vorhersage der Punktzahl

Unser System hat also eine Punktzahl von 4,25 vorhergesagt, was wirklich gut ist. Ich denke, dass Benutzer (370) den Film mit der ID (7371) mögen könnte.

Nun wollen wir unserem System den letzten Schliff geben. Ich denke, die meisten von uns hätten Netflix oder Hotstar benutzt. Wenn wir also die App öffnen, zeigt sie den Artikel an, den wir mögen.

Ich bin immer fasziniert von den Empfehlungen, da sie sich als die Filme herausstellen, die ich mag. Das alles geschieht durch das Empfehlungssystem selbst. Wir werden nun das Gleiche tun und versuchen, die 5 besten Filme vorherzusagen, die dem jeweiligen Benutzer gefallen könnten.

Die Logik ist nicht so schwierig. Wir haben bereits die Punktzahl für ein Element ermittelt. In ähnlicher Weise können wir die Punktzahl für die anderen Elemente mit dem gleichen Benutzer generieren.

Aber, jetzt wieder unter Berücksichtigung von Big Data, macht es Sinn, die Punktzahl für alle anderen Elemente zu generieren?

Ich denke NOOOOOO!!!

Betrachten wir den Benutzer (U) und den Benutzer (K). Nehmen wir an, K ist nicht in der Nachbarschaft von U, ist es möglich, dass Benutzer U einen Film mag, den K gesehen und bewertet hat. Meistens nein.

Ich glaube, Sie haben den Trick verstanden. Ja, wir sind nur daran interessiert, die Punkte für die Artikel zu berechnen, die ihre Nachbarnutzer gesehen haben.

Wir sind wirklich erfolgreich. Wir haben die Berechnung von 2500 auf N reduziert (wobei N die Menge der Filme ist, die meine Nachbarschaft mochte), und das ist sehr viel weniger als 2500.

Lassen Sie uns also endlich die Filme empfehlen.

User_item_score1 ist meine benutzerdefinierte Funktion, die unsere obige Diskussion nutzt, um Vorhersagen zu berechnen

user = int(input("Enter the user id to whom you want to recommend : "))
predicted_movies = User_item_score1(user)
print(" ")
print("The Recommendations for User Id : ",user)
print(" ")
for i in predicted_movies:
print(i)

Am Ende!!!! Wir haben es geschafft. Wir haben unser eigenes Empfehlungssystem.

Die Darstellung des untenstehenden Codes ist vielleicht nicht ganz einfach zu lesen, daher gehen Sie bitte auf mein GitHub-Repository, um auf den Code zuzugreifen.

Die benötigten Datensätze können von hier bezogen werden.

Ich hoffe, der Blog hat Ihnen gefallen. Bei Fragen könnt ihr mir gerne eine Mail schreiben. Bleiben Sie dran für weitere Blogs, da dies eines meiner Interessensgebiete ist und ich auf jeden Fall einige neue Sachen posten werde.

Danke!!!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.