Jeden Tag erhalten Benutzer auf der ganzen Welt eine große Anzahl unterschiedlicher Mailings - nur über den MailChimp-Dienst versenden sie täglich eine Milliarde Briefe . Davon werden 20,81% entdeckt.
Jeden Monat erhalten Benutzer unserer Websites Newsletter mit Materialien, die vom Herausgeber ausgewählt wurden. Ungefähr 21% der Leser öffnen diese Briefe.
Um diese Anzahl zu erhöhen, können Sie sie personalisieren. Eine Möglichkeit besteht darin, ein Empfehlungssystem hinzuzufügen, das Materialien auffordert, die für einen bestimmten Leser interessant sind.
In diesem Artikel werde ich darüber sprechen, wie ein Empfehlungssystem basierend auf kollaborativer Filterung von Grund auf neu implementiert wird.
Der erste Teil des Artikels enthält die theoretischen Grundlagen für die Implementierung des Empfehlungssystems. Schulmathematik reicht aus, um das Material zu verstehen.
Der zweite Teil beschreibt eine Python-Implementierung für unsere Site-Daten.
Ein bisschen kollaborative Filtertheorie
Kollaboratives Filtern ist wahrscheinlich der einfachste Ansatz in Empfehlungssystemen. Es basiert auf der Idee, dass ähnliche Benutzer ähnliche Objekte wie Artikel mögen.
Was bedeutet "ähnliche Benutzer"?

Wie kann man feststellen, wie sehr Vasily Ivan oder einem Artikel über SQL Server zu einem Artikel über PostgreSQL ähnelt?
Schauen wir uns ein Beispiel an. Nehmen wir an, wir haben vier Benutzer: Vasily, Ivan, Inna und Anna. Die Website enthält fünf Artikel: Artikel 1, Artikel 2, Artikel 3, Artikel 4 und Artikel 5. In der folgenden Tabelle gibt die Nummer an der Schnittstelle zwischen Benutzer und Artikel die Bewertung des Artikels durch den Benutzer auf einer Fünf-Punkte-Skala an. Null in der Tabelle sind Artikel, die vom Benutzer nicht bewertet wurden. Zum Beispiel mochte Vasily die Artikel 1, 3 und 4.
Tabelle 1
Intuitiv können wir davon ausgehen, dass wenn Benutzer dieselben Artikel mögen, ihr Geschmack übereinstimmt. Was denkst du, dessen Interessen den Interessen von Vasily ähnlich sind?
Vasilys Interessen ähneln eher den Interessen von Ivan und Inna und weniger den Interessen von Anna. Warum - es wird weiter erzählt.
Für die weitere Arbeit ist es notwendig, die „Ähnlichkeit“ von Vasily und Ivan oder Inna und Anna zu formalisieren und zu messen.
Der einfachste Weg, dies zu tun, besteht darin, Benutzerbewertungen als Beschreibung ihres Profils zu betrachten. Im Beispiel ist jede Zeile in der Tabelle eine Beschreibung eines Benutzers. Die erste Zeile - die Beschreibung von Basil - ist ein Vektor mit fünf Zahlen: [4, 0, 5, 5, 0]; der zweite - Ivan - [0, 0, 4, 5, 0]; der dritte ist Inna - [4, 2, 4, 0, 0]; der vierte ist Anna - [5, 5, 0, 0, 5].
Jetzt können Sie das Konzept der Benutzerbeschreibungen "Ähnlichkeitsmaß" einführen.
Eine Möglichkeit, die "Ähnlichkeit" von Benutzern zu messen, besteht darin, den Kosinusabstand zwischen den Vektoren zu berechnen, die sie beschreiben.

Der Kosinusabstand wird nach folgender Formel berechnet:
wo und - Benutzerbeschreibungsvektoren; - Skalarprodukt von Beschreibungsvektoren; , - Länge der Beschreibungsvektoren.
Die Bedeutung des Kosinusabstands ist wie folgt: Wenn zwei Vektoren wo sind und (Benutzerbeschreibungsvektoren) sind "ähnlich", dann tendiert der Winkel zwischen ihnen gegen Null und der Kosinus dieses Winkels gegen Eins. Im Idealfall, wenn die "Interessen" der beiden Benutzer zusammenfallen, ist der Kosinusabstand für sie Null.
Kosinusabstand zwischen Vasily und Ivan:
In ähnlicher Weise beträgt der Kosinusabstand zwischen Vasily und Anna 0,715. Das heißt, Vasilys Interessen ähneln eher Iwans Interessen als Annas.
Wie kann man Benutzerbewertungen vorhersagen?
Dieser Teil ist der interessanteste. Es gibt viele verschiedene Möglichkeiten. Nachfolgend betrachten wir zwei einfache Optionen.
Voraussichtliche Bewertung - durchschnittliche Bewertung unter "ähnlichen" Benutzern
Die einfachste Möglichkeit, die vorhergesagte Bewertung zu berechnen, besteht darin, zu sehen, welche Bewertungen die „ähnlichen“ Benutzer dem Artikel gegeben haben, und die durchschnittliche Bewertung zu ermitteln:
In dieser Formel:
- Ist die Schätzung, für die vorhergesagt wird Artikel und Benutzer ,
- - Benutzerbewertung für th Artikel
- - Viele "ähnliche" Benutzer,
- - die Anzahl der "ähnlichen" Benutzer.
Voraussichtliche Bewertung - gewichtete Durchschnittsbewertung unter „ähnlichen“ Benutzern
Eine etwas kompliziertere Option besteht darin, den Grad der Ähnlichkeit zu berücksichtigen: Bewertungen ähnlicherer Benutzer sollten die endgültige Bewertung stärker beeinflussen als Bewertungen weniger ähnlicher Benutzer:
In dieser Formel:
- Ist die Schätzung, für die vorhergesagt wird Artikel und Benutzer ,
- - Benutzerbewertung für th Artikel
- - Viele "ähnliche" Benutzer,
- - "Ähnlichkeit" (Kosinusabstand) der Benutzer und .
Wie kann die Qualität von Empfehlungen gemessen werden?

Wenn Sie ein Empfehlungssystem erstellen, sollten Sie die Metrik bestimmen, anhand derer Sie die Qualität unseres Modells bewerten können - wie gut das System dem Benutzer neue Materialien bietet. Zum Beispiel der quadratische Mittelwertfehler ( ) Ist die Quadratwurzel des durchschnittlichen Fehlers für alle Benutzerbewertungen. Formal wird diese Maßnahme durch die Formel beschrieben:
In dieser Formel
- - die Menge aller Benutzerbewertungen für Artikel,
- - vorhergesagte Benutzerbewertung Artikel ,
- - echte Benutzerbewertung Artikel .
Im Idealfall, wenn die vorhergesagten Bewertungen mit denen des Benutzers übereinstimmen gleich Null.
Betrachten Sie ein Beispiel. Zwei Referenzsysteme machten Vorhersagen für Vasily. Das Ergebnis ist in der folgenden Tabelle aufgeführt.
Es ist intuitiv klar, dass das zweite Empfehlungssystem Bewertungen besser vorhersagte als das erste. Zählen ::
Der Fehler bei der Bewertung des zweiten Empfehlungssystems wird voraussichtlich erheblich geringer sein.
Implementierung
Wir verfügen über die meisten Daten zu Artikeln und Benutzern der Website: Informationen zu Artikeln, Tags, Benutzer-Likes usw.
Um eine kollaborative Filterung zu implementieren, sind Benutzerbewertungen ausreichend.
HaftungsausschlussIm Folgenden wird der Code „in die Stirn“ geschrieben, um die Logik des Empfehlungssystems zu demonstrieren. Im wirklichen Leben ist es besser, alle Funktionen von numpy
und pandas
.
import pandas as pd import numpy as np import os ratings_df = pd.read_csv('./input/Ratings.csv') print(' :', ratings_df.shape[0]) print(' :', ratings_df[ratings_df['Rate']].shape[0]) unique_user_ids = ratings_df[ratings_df['Rate']]['UserId'].unique() print(' :', len(unique_user_ids)) ratings_df.head()
Ausgabe [1]Gesamtdaten: 15313
Positive Bewertungen: 15121
Aktive Benutzer: 1007
1007 aktive Benutzer gaben 15313 "Bewertungen". Davon „mag“ 15121.
Die Daten enthalten vier Spalten: die Zeilen-ID aus der Datenbank ( ID- Spalte), die Objekt-ID ( DocumentId- Spalte), ein Zeichen dafür, dass dem Benutzer der Artikel gefallen hat ( Rate- Spalte) und die Benutzer- ID ( UserId- Spalte).
Fügen Sie der Einfachheit halber die Spalte RateInt hinzu . 1 in dieser Spalte bedeutet, dass dem Benutzer der Artikel gefallen hat. -1 - das hat nicht gefallen.
ratings_df['RateInt'] = ratings_df['Rate'].apply(lambda x: 1 if x else -1) ratings_df.head()
Für weitere Arbeiten ist es erforderlich, den Datensatz in Training und Test zu unterteilen: Das Training wird zum Trainieren des Modells verwendet, und der Test bestimmt die Qualität der Vorhersagen.
from sklearn.model_selection import train_test_split train, test = train_test_split(ratings_df, test_size=0.2)
Der Einfachheit halber transformieren wir jeden Satz in eine Tabelle, in der in den Zeilen die Bezeichner der Benutzer und in den Spalten die Bezeichner der Artikel in Analogie zum Beispiel am Anfang des Artikels angegeben sind.
def create_matrix(df): ratings_per_user = [] post_ids = df['DocumentId'].unique() for user_id in tqdm_notebook(all_users_ids, ''): row = {'user_id': user_id} ratings = df[df['UserId'] == user_id]['DocumentId'].values for post_id in post_ids: row[str(post_id)] = 1 if post_id in ratings else 0 ratings_per_user.append(row) return pd.DataFrame(ratings_per_user) train_df = create_matrix(train) test_df = create_matrix(test)
Mit Matrix-Matching-Benutzern und Lieblingsartikeln können Sie den Kosinusabstand zwischen Benutzern berechnen:
from scipy import spatial def cos_distance(x1, x2): return spatial.distance.cosine(x1, x2) at_least_one_fav_post_users = list(train_valuable_df['user_id'].values) def calculate_distances(df): columns = df.columns[:-1] cp = at_least_one_fav_post_users.copy() data = [] for user_id_1 in tqdm_notebook(at_least_one_fav_post_users, ''): row = {'user_id': user_id_1} for user_id_2 in cp: x1 = df[df['user_id'] == user_id_1][columns].values[0] x2 = df[df['user_id'] == user_id_2][columns].values[0] row[str(user_id_2)] = cos_distance(x1, x2) data.append(row) return pd.DataFrame(data) train_distances = calculate_distances(train_valuable_df)
Jetzt ist alles bereit, um Benutzer zu Artikeln aufzufordern, die ihnen unserer Meinung nach gefallen werden.
Wir implementieren die beiden Strategien zur Berechnung der oben beschriebenen Empfehlungen: die durchschnittliche und die gewichtete durchschnittliche Bewertung unter ähnlichen Benutzern.
Erster Weg
Wir nehmen 10 Benutzer, die dem aktuellen am nächsten kommen, und prognostizieren die Bewertung als Durchschnitt für ähnliche Benutzer für den Artikel:
from tqdm import tqdm_notebook import heapq def rmse(predicted, actual): return ((predicted - actual) ** 2).mean() ** 0.5 def get_similar(id, n): df = train_distances[train_distances['user_id'] == id] d = df.to_dict('records')[0] top_similar_ids = heapq.nsmallest(n+1, d, key=d.get) top_similar = df[top_similar_ids] return top_similar.to_dict('records')[0] def get_predictions(id, n): top_similar_users = get_similar(id, n) top_similar_users_ids = list([int(x) for x in top_similar_users.keys()]) ratings_for_top_similar = train_df[train_df['user_id'].isin(top_similar_users_ids)] predicted_ratings = {} for article_id in train_df.columns[:-1]: predicted_ratings[article_id] = ratings_for_top_similar[article_id].mean() return predicted_ratings rand_n_users = train_distances.sample(50)['user_id'].values err = 0 for u in tqdm_notebook(rand_n_users): pred = get_predictions(u, 10) err += rmse(test_df[test_df['user_id'] == u][list(pred.keys())].values, pd.DataFrame(pred, index=[0]).values) print(err / len(rand_n_users))
Für den ersten Ansatz haben wir einen Fehler von 0,855 erhalten.
Empfehlungen für den Gelegenheitsnutzer Zweiter Weg
Die zweite Methode berücksichtigt den Ähnlichkeitsgrad der Benutzer. Die Implementierung ist fast identisch mit der ersten:
def get_predictions(id, n): similar_users = get_similar(u, 10) prediction = {} user_ids = list(similar_users.keys()) user_similarities = [] for user_id in user_ids: user_similarities.append(similar_users[user_id]) predicted_ratings = {} for article_id in train_df.columns[:-1]: prediction_for_article = 0 numerator = 0 denominator = 0 for user_id in user_ids: rating = train_df[train_df['user_id'] == int(user_id)][article_id].values[0] numerator += rating * (1 - similar_users[user_id]) denominator += np.abs(similar_users[user_id]) predicted_ratings[article_id] = numerator / denominator return predicted_ratings err = 0 for u in tqdm_notebook(rand_n_users): pred = get_predictions(u, 10) err += rmse(test_df[test_df['user_id'] == u][list(pred.keys())].values, pd.DataFrame(pred, index=[0]).values) print(err / len(rand_n_users))
In diesem Fall wurde der Fehler 0.866 angezeigt. Der Fehler ist etwas größer als im ersten Fall.
Empfehlungen für denselben zufälligen Benutzer Die Ergebnisse können in verschiedenen Szenarien verwendet werden. Zum Beispiel in Newslettern mit neuen Artikeln pro Monat oder fügen Sie auf der Website den Abschnitt "Sie könnten interessiert sein" hinzu.
Zusammenfassung
In diesem Artikel habe ich anhand des Beispiels einer realen Aufgabe ausführlich versucht, herauszufinden, wie ein Empfehlungssystem auf der Grundlage einer kollaborativen Filterung erstellt werden kann.
Der Vorteil dieses Ansatzes ist seine Vielseitigkeit - die Empfehlungen berücksichtigen nicht, welche Objekte empfohlen werden. Ein System kann sowohl für Blog-Artikel als auch für Produkte im Online-Shop verwendet werden.
Die Nachteile umfassen Folgendes:
- Bei einer großen Anzahl von Objekten für Empfehlungen wird die Benutzer-Objekt-Matrix spärlich und es wird schwieriger, ausreichend ähnliche Benutzer zu finden (weniger Benutzer-Objekt-Paare stimmen überein).
- Kaltstartproblem - Es ist für einen neuen Benutzer unmöglich, ähnliche Benutzer zu finden (es gibt Strategien, um diese Einschränkung zu umgehen, aber sie sind kein Allheilmittel).
- Ein System, das auf kollaborativer Filterung basiert, empfiehlt häufig beliebte Objekte, weil Die überwiegende Mehrheit der Benutzer wird solche Objekte zu schätzen wissen.
Im nächsten Artikel wird ein anderer Ansatz betrachtet - basierend auf einer Analyse der Objekte selbst.