Empfehlungs-Tutorial mit Assoziationsanalyse (Python-Implementierung)

Über diesen Artikel

Ich habe einen Artikel geschrieben, weil es nicht viele Tutorials auf der Welt gab, die anhand von Beispieldaten zu Empfehlungen implementiert wurden.
Es gibt Methoden wie maschinelles Lernen, um Empfehlungen zu erstellen. Dies ist jedoch ein Artikel zum Erstellen von Empfehlungen mithilfe statistischer Methoden.
Ich werde mit Python und Open Dataset erklären.

Dies ist ein Artikel über die Implementierung durch Python. In den folgenden Artikeln finden Sie das Konzept der Empfehlungen. Empfehlungs-Tutorial mit Assoziationsanalyse (Konzept)

Es wird gemäß dem Ablauf des Artikels der Concept Edition implementiert.

Wenn Sie diese Implementierung ausprobieren möchten, ohne eine Umgebung zu erstellen

Es wird eine Gebühr erhoben, aber wir haben eine Ausführungsumgebung für Google Colaboratory unter [hier] vorbereitet (https://note.com/mlpanda/n/n74e0557d6960).

** Erforderliche Bibliotheken importieren **

Importieren Sie die erforderlichen Bibliotheken.

#Bibliothek importieren
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

** Laden des Datensatzes **

Laden Sie den in diesem Lernprogramm verwendeten Datensatz. Dadurch wird ein Datensatz aus dem Github-Repository geladen.

#Datensatz laden
import urllib.request
from io import StringIO

url = "https://raw.githubusercontent.com/tachiken0210/dataset/master/dataset_cart.csv"

#Funktion zum Lesen von CSV
def read_csv(url):
    res = urllib.request.urlopen(url)
    res = res.read().decode("utf-8")
    df = pd.read_csv(StringIO( res) )
    return df

#Lauf
df_cart_ori = read_csv(url)

** Überprüfen Sie den Inhalt des Datensatzes **

Überprüfen Sie den Inhalt des diesmal verwendeten Datensatzes.

df_cart_ori.head()
cart_id goods_id action create_at update_at last_update time
0 108750017 583266 UPD 2013-11-26 03:11:06 2013-11-26 03:11:06 2013-11-26 03:11:06 1385478215
1 108750017 662680 UPD 2013-11-26 03:11:06 2013-11-26 03:11:06 2013-11-26 03:11:06 1385478215
2 108750017 664077 UPD 2013-11-26 03:11:06 2013-11-26 03:11:06 2013-11-26 03:11:06 1385478215
3 108199875 661648 ADD 2013-11-26 03:11:10 2013-11-26 03:11:10 2013-11-26 03:11:10 1385478215
4 105031004 661231 ADD 2013-11-26 03:11:41 2013-11-26 03:11:41 2013-11-26 03:11:41 1385478215

** Über den in diesem Tutorial verwendeten Datensatz **

Dieser Datensatz enthält die Protokolldaten, wenn ein Kunde auf einer bestimmten EC-Site ein Produkt in den Warenkorb legt.

** ・ card_id: Mit dem Kunden verknüpfte Warenkorb-ID (Es ist in Ordnung, sie als Kunden-ID zu betrachten, daher wird sie unten als Kunde bezeichnet.)
**** ・ Waren-ID: Produkt-ID
**** ・ Aktion: Kundenaktion (HINZUFÜGEN: Zum Warenkorb hinzufügen, ENTF: Aus dem Warenkorb löschen usw.)
**** ・ create_at: Zeitpunkt, zu dem das Protokoll erstellt wurde
**** ・ update_at: Das Protokoll wird aktualisiert Zeit (diesmal nicht verwendet)
**** ・ last_update: Zeit, zu der das Protokoll aktualisiert wurde (diesmal nicht verwendet)
**** ・ Zeit: Zeitstempel
**

Darüber hinaus enthalten allgemeine offene Datensätze, einschließlich des diesmal verwendeten Datensatzes, selten bestimmte Namen wie Produktnamen im Datensatz und werden im Wesentlichen durch die Produkt-ID ausgedrückt. Daher ist es schwierig zu wissen, um welche Art von Produkt es sich handelt. Bitte beachten Sie jedoch, dass dies auf den Inhalt der Daten zurückzuführen ist.

Schauen wir uns als nächstes den Inhalt dieser Daten an. Dieser Datensatz enthält Daten für alle Kunden als chronologisches Protokoll. Konzentrieren wir uns also auf nur einen Kunden. Lassen Sie uns zunächst den Kunden mit der größten Anzahl von Protokollen in den Daten extrahieren.

df_cart_ori["cart_id"].value_counts().head()
#Ausgabe
110728794    475
106932411    426
115973611    264
109269739    205
112332751    197
Name: cart_id, dtype: int64

Es gibt 475 Protokolle für 110728794 Benutzer, was am meisten protokolliert zu sein scheint. Lassen Sie uns das Protokoll dieses Kunden extrahieren.

df_cart_ori[df_cart_ori["cart_id"]==110728794].head(10)
cart_id goods_id action create_at update_at last_update time
32580 110728794 664457 ADD 2013-11-26 22:54:13 2013-11-26 22:54:13 2013-11-26 22:54:13 1385478215
32619 110728794 664885 ADD 2013-11-26 22:55:09 2013-11-26 22:55:09 2013-11-26 22:55:09 1385478215
33047 110728794 664937 ADD 2013-11-26 22:58:52 2013-11-26 22:58:52 2013-11-26 22:58:52 1385478215
33095 110728794 664701 ADD 2013-11-26 23:00:25 2013-11-26 23:00:25 2013-11-26 23:00:25 1385478215
34367 110728794 665050 ADD 2013-11-26 23:02:40 2013-11-26 23:02:40 2013-11-26 23:02:40 1385478215
34456 110728794 664989 ADD 2013-11-26 23:05:03 2013-11-26 23:05:03 2013-11-26 23:05:03 1385478215
34653 110728794 664995 ADD 2013-11-26 23:07:00 2013-11-26 23:07:00 2013-11-26 23:07:00 1385478215
34741 110728794 664961 ADD 2013-11-26 23:09:41 2013-11-26 23:09:41 2013-11-26 23:09:41 1385478215
296473 110728794 665412 DEL 2013-12-03 17:17:30 2013-12-03 17:17:30 2013-12-03 07:41:13 1386083014
296476 110728794 665480 DEL 2013-12-03 17:17:37 2013-12-03 17:17:37 2013-12-03 07:42:29 1386083014

Wenn Sie sich diesen Kunden ansehen, können Sie feststellen, dass er den ganzen Tag über kontinuierlich Einkaufswagen zu seinen Produkten hinzufügt. Wenn man dies für andere Kunden auf die gleiche Weise analysiert, ist es leicht zu erkennen, dass das Produkt y wahrscheinlich in den Warenkorb neben dem im Allgemeinen vorhandenen Produkt x gelegt wird.
Auf diese Weise besteht der Zweck dieser Zeit darin, das Muster zu analysieren, dass ** "Produkt y wahrscheinlich neben einem bestimmten Produkt x" aus diesem Datensatz in den Warenkorb gelegt wird. **

Wir werden die Daten ab dem nächsten tatsächlich verarbeiten, aber die oben genannten in der Ecke Ihres Kopfes behalten.

** Datenvorverarbeitung **

Von hier aus werden wir die Daten vorverarbeiten. Wenn Sie sich die Spalte "Aktion" ansehen, gibt es zunächst verschiedene Dinge wie HINZUFÜGEN und ENTF. Konzentrieren wir uns zunächst auf das Protokoll ADD (dem Warenkorb hinzugefügt). Dies bedeutet, dass Sie sich nur auf die Produktnachfrage des Kunden konzentrieren.

df = df_cart_ori.copy()
df = df[df["action"]=="ADD"]
df.head()
cart_id goods_id action create_at update_at last_update time
3 108199875 661648 ADD 2013-11-26 03:11:10 2013-11-26 03:11:10 2013-11-26 03:11:10 1385478215
4 105031004 661231 ADD 2013-11-26 03:11:41 2013-11-26 03:11:41 2013-11-26 03:11:41 1385478215
6 110388732 661534 ADD 2013-11-26 03:11:55 2013-11-26 03:11:55 2013-11-26 03:11:55 1385478215
7 110388740 662336 ADD 2013-11-26 03:11:58 2013-11-26 03:11:58 2013-11-26 03:11:58 1385478215
8 110293997 661648 ADD 2013-11-26 03:12:13 2013-11-26 03:12:13 2013-11-26 03:12:13 1385478215

Sortieren Sie anschließend den Datensatz so, dass die Reihenfolge, in der die Artikel für jeden Kunden in den Warenkorb gelegt wurden, chronologisch ist.

df = df[["cart_id","goods_id","create_at"]]
df = df.sort_values(["cart_id","create_at"],ascending=[True,True])
df.head()
cart_id goods_id create_at
548166 78496306 661142 2013-11-15 23:07:02
517601 79100564 662760 2013-11-24 18:17:24
517404 79100564 661093 2013-11-24 18:25:29
23762 79100564 664856 2013-11-26 13:41:47
22308 79100564 562296 2013-11-26 13:44:20

Der Prozess von hier aus formatiert die Daten so, dass sie in die Assoziationsanalysebibliothek passen.

Für jeden Kunden fügen wir die Artikel im Warenkorb der Reihe nach der Liste hinzu.

df = df[["cart_id","goods_id"]]
df["goods_id"] = df["goods_id"].astype(int).astype(str)
df = df.groupby(["cart_id"])["goods_id"].apply(lambda x:list(x)).reset_index()
df.head()
 |   cart_id | goods_id                                                                                                                                     |

|---:|----------:|:---------------------------------------------------------------------------------------------------------------------------------------------| | 0 | 78496306 | ['661142'] | | 1 | 79100564 | ['662760', '661093', '664856', '562296', '663364', '664963', '664475', '583266'] | | 2 | 79455669 | ['663801', '664136', '664937', '663932', '538673', '663902', '667859'] | | 3 | 81390353 | ['663132', '661725', '664236', '663331', '659679', '663847', '662340', '662292', '664099', '664165', '663581', '665426', '663899', '663405'] | | 4 | 81932021 | ['662282', '664218']
Als nächstes überprüfen wir den Inhalt des obigen Datenrahmens.
Beachten Sie den Kunden in der zweiten Zeile (79100564).
Zunächst wird nach dem ersten Produkt 663801 664136 in den Warenkorb gelegt. Das heißt, X = "663801" und Y = "664136". < Nach 664136 wird 664937 in den Warenkorb gelegt. Für diese ist X = "664136" und Y = "664937". Auf diese Weise ist es durch Anordnen dieses XY-Paares für jeden Kunden möglich, eine Assoziationsanalyse durchzuführen.

Formatieren wir nun die Daten so, dass dieses XY gepaart ist.

def get_combination(l):
    length = len(l)
    list_output = []
    list_pair = []
    for i in range(length-1):
        if l[i]==l[i+1]:
            pass
        else:
            list_pair =[l[i],l[i+1]]
            list_output.append(list_pair)
    return list_output

df["comb_goods_id"] = df["goods_id"].apply(lambda x:get_combination(x))

#Erstellen Sie eine Liste der Zuordnungseingaben
dataset= []
for i,contents in enumerate(df["comb_goods_id"].values):
    for c in contents:
        dataset.append(c)

print("Die Anzahl der XY-Paare beträgt",len(dataset))
print("Inhalt des XY-Paares",dataset[:5])
#Ausgabe
Die Anzahl der XY-Paare beträgt 141956
Inhalt des XY-Paares[['662760', '661093'], ['661093', '664856'], ['664856', '562296'], ['562296', '663364'], ['663364', '664963']]

** Assoziationsanalyse durchführen **

Das Obige wird als Eingabe für die Assoziationsanalyse verwendet. Ich habe eine Methode erstellt, die eine Assoziationsanalyse als Assoziationsmethode durchführt, daher werde ich diese verwenden.

#Vereinsbibliothek
def association(dataset):
    df = pd.DataFrame(dataset,columns=["x","y"])
    num_dataset = df.shape[0]
    df["sum_count_xy"]=1
    print("calculating support....")
    df_a_support = (df.groupby("x").sum()/num_dataset).rename(columns={"sum_count_xy":"support_x"})
    df_b_support = (df.groupby("y").sum()/num_dataset).rename(columns={"sum_count_xy":"support_y"})
    df = df.groupby(["x","y"]).sum()
    df["support_xy"]=df["sum_count_xy"]/num_dataset
    df = df.reset_index()
    df = pd.merge(df,df_a_support,on="x")
    df = pd.merge(df,df_b_support,on="y")
    print("calculating confidence....")
    df_temp = df.groupby("x").sum()[["sum_count_xy"]].rename(columns={"sum_count_xy":"sum_count_x"})
    df = pd.merge(df,df_temp,on="x")
    df_temp = df.groupby("y").sum()[["sum_count_xy"]].rename(columns={"sum_count_xy":"sum_count_y"})
    df = pd.merge(df,df_temp,on="y")
    df["confidence"]=df["sum_count_xy"]/df["sum_count_x"]
    print("calculating lift....")
    df["lift"]=df["confidence"]/df["support_y"]
    df["sum_count"] = num_dataset
    df_output = df
    return df_output
#Wenden Sie den Datensatz auf die Assoziationsanalyse an
df_output = association(dataset)
df_output.head()
x y sum_count_xy support_xy support_x support_y sum_count_x sum_count_y confidence lift sum_count
0 485836 662615 1 7.04444e-06 7.04444e-06 0.000147933 1 21 1 6759.81 141956
1 549376 662615 1 7.04444e-06 2.11333e-05 0.000147933 3 21 0.333333 2253.27 141956
2 654700 662615 1 7.04444e-06 0.000464933 0.000147933 66 21 0.0151515 102.421 141956
3 661475 662615 1 7.04444e-06 0.000965088 0.000147933 137 21 0.00729927 49.3417 141956
4 661558 662615 1 7.04444e-06 0.000408577 0.000147933 58 21 0.0172414 116.548 141956

Ich habe das Ergebnis. Der Inhalt jeder Spalte ist wie folgt ** ・ x: Bedingungsteil X
・ y: Schlussfolgerungsteil Y
・ sum_count_xy: Anzahl der für XY geltenden Daten
・ support_xy: XY-Unterstützung
・ support_x: X-Unterstützung
> ・ Support_y: Y-Unterstützung
・ sum_count_x: Anzahl der für X geltenden Daten
・ sum_count_y: Anzahl der für Y geltenden Daten
・ Vertrauen: Vertrauen
・ Aufzug: Aufzug
**

** Nachbearbeitung von Assoziationsergebnissen **

Nun, die Ausführung des Vereins ist beendet, aber es gibt eine Einschränkung.
** Grundsätzlich scheint ein hoher Hubwert von hoher Relevanz zu sein. Wenn jedoch die Anzahl der Daten gering ist, besteht der Verdacht, dass dies versehentlich passiert ist. **
Nehmen Sie zum Beispiel die oberste Zeile. Dies ist der Teil von x = "485836", y = "662615".
Dies hat einen sehr hohen Hubwert von 6760, aber dies ist nur einmal passiert (= support_xy). Unter der Annahme, dass die Anzahl der Daten ausreicht, ist es sehr wahrscheinlich, dass dies versehentlich passiert ist.
Wie leiten Sie den support_xy-Schwellenwert ab, der bestimmt, ob er versehentlich ist oder nicht?

.. .. .. In Wirklichkeit ist es schwierig, diese Schwelle abzuleiten. (Es gibt keine richtige Antwort)

Hier überprüfen wir das Histogramm von support_xy einmal.

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.hist(df_output["sum_count_xy"], bins=100)
ax.set_title('')
ax.set_xlabel('xy')
ax.set_ylabel('freq')
#Es ist schwer zu erkennen, also begrenzen Sie den Bereich der y-Achse
ax.set_ylim(0,500)
fig.show()

Sie können sehen, dass bei den meisten Daten die x-Achse support_xy nahe 0 konzentriert ist.
In diesem Lernprogramm werden alle Daten in der Nähe von 0 als Zufall betrachtet und gelöscht.
Beim Einstellen des Schwellenwerts wird der Bruch verwendet und der Schwellenwert so eingestellt, dass die Daten der unteren 98% als Zufall angesehen werden können.

df = df_output.copy()
df = df[df["support_xy"]>=df["support_xy"].quantile(0.98)]
df.head()
x y sum_count_xy support_xy support_x support_y sum_count_x sum_count_y confidence lift sum_count
58 662193 667129 8 5.63555e-05 0.0036138 0.00281073 513 399 0.0155945 5.54822 141956
59 665672 667129 12 8.45332e-05 0.00395193 0.00281073 561 399 0.0213904 7.61026 141956
60 666435 667129 30 0.000211333 0.0082279 0.00281073 1168 399 0.0256849 9.13817 141956
62 666590 667129 7 4.93111e-05 0.00421257 0.00281073 598 399 0.0117057 4.16464 141956
63 666856 667129 8 5.63555e-05 0.00390966 0.00281073 555 399 0.0144144 5.12835 141956

Dadurch wurden mir die Daten für das xy-Paar gespeichert, von denen ich dachte, dass sie zufällig passiert sind.
Dann der letzte Prozess, bei dem nur y übrig bleibt, was für x relevant ist. Wie bereits erläutert, bedeutet dies, dass nur noch xy-Paare mit hohen Auftriebswerten übrig bleiben müssen.
Hier lassen wir nur Paare mit einem Auftrieb von 2,0 oder höher.

** Übrigens ist es ein Bild der Bedeutung von Auftrieb (Hubwert), aber es ist ein Wert, der zeigt, wie einfach es ist, y Produkte in den Warenkorb zu legen, wenn x Produkte in den Warenkorb gelegt werden, verglichen mit anderen Produkten. **

Wenn beispielsweise im Inhalt des obigen Datenrahmens das Produkt "662193" (x) zum Warenkorb hinzugefügt wird, ist das Produkt "667129" (y) ** 5,5-mal einfacher zum Warenkorb hinzuzufügen * * Es bedeutet.

df = df[df["lift"]>=2.0]
df_recommendation = df.copy()
df_recommendation.head()
x y sum_count_xy support_xy support_x support_y sum_count_x sum_count_y confidence lift sum_count
58 662193 667129 8 5.63555e-05 0.0036138 0.00281073 513 399 0.0155945 5.54822 141956
59 665672 667129 12 8.45332e-05 0.00395193 0.00281073 561 399 0.0213904 7.61026 141956
60 666435 667129 30 0.000211333 0.0082279 0.00281073 1168 399 0.0256849 9.13817 141956
62 666590 667129 7 4.93111e-05 0.00421257 0.00281073 598 399 0.0117057 4.16464 141956
63 666856 667129 8 5.63555e-05 0.00390966 0.00281073 555 399 0.0144144 5.12835 141956

** Verwendung von Assoziationsergebnissen (= Empfehlungsdaten) **

Damit ist die Generierung grundlegender Empfehlungsdaten abgeschlossen.
Die spezifische Verwendung ist so einfach wie die Bewerbung des Produkts "667129" bei der Person, die beispielsweise das Produkt "662193" in den Warenkorb gelegt hat.
Tatsächlich werden die Daten dieser Empfehlung in der Datenbank gespeichert, so dass y ausgegeben wird, wenn x eingegeben wird.

Probleme mit dieser Empfehlung

Nachdem ich die Empfehlungsdaten erstellt habe, zeige ich Ihnen die Probleme mit dieser Empfehlung (ohne sie auszublenden).

Das heißt ** es ist nicht möglich, alle Eingabeprodukte (x) anzuvisieren. **

Lassen Sie uns dies überprüfen.
Lassen Sie uns zunächst überprüfen, wie viele Arten von x in den ursprünglichen Transaktionsdaten enthalten sind.

#x ist die Ware der Originaldaten_Da es sich um eine ID handelt, wird die eindeutige Anzahl aggregiert.
df_cart_ori["goods_id"].nunique()
#Ausgabe
8398

Ursprünglich gibt es 8398 Arten von x.
Mit anderen Worten, wir sollten in der Lage sein, hochrelevante Produkte (y) für diese 8398 Arten von Eingaben (x) zu empfehlen.

Überprüfen wir nun, wie viel Eingabe (x) der vorherigen Ausgabe entspricht.

#Aggregieren Sie die eindeutige Anzahl von x im Empfehlungsergebnis.
df_recommendation["x"].nunique()
#Ausgabe
463

Die Eingabe (x), die von den obigen ** Empfehlungsdaten unterstützt wird, unterstützt nur 463 Typen. ** (463/8392, also ungefähr 5%)

Dies ist eine Schwäche der Empfehlungen zum Benutzerverhalten. Vielleicht muss dies in der Realität angegangen werden.
Folgendes kann als Gegenmaßnahme angesehen werden.

Zusammenfassung

Für Empfehlungen, die Assoziationen verwenden, ist es relativ einfach, Empfehlungsdaten zu erstellen, wenn Transaktionsdaten akkumuliert werden. Wenn Sie versuchen, eine Empfehlungs-Engine für Ihre eigentliche Arbeit zu erstellen, probieren Sie es bitte aus!

Recommended Posts

Empfehlungs-Tutorial mit Assoziationsanalyse (Python-Implementierung)
Empfehlungs-Tutorial mit Assoziationsanalyse (Konzept)
Assoziationsanalyse in Python
Datenanalyse mit Python-Pandas
Gehirnwellenanalyse mit Python: Python MNE-Tutorial
Implementierung von Desktop-Benachrichtigungen mit Python
Empfehlung zur Datenanalyse mit MessagePack
Python-Tutorial
[In-Database Python Analysis-Lernprogramm mit SQL Server 2017] Schritt 6: Verwenden des Modells
[In-Database Python Analysis Tutorial mit SQL Server 2017]
Python: Negative / Positive Analyse: Twitter Negative / Positive Analyse mit RNN-Teil 1
Zeitvariationsanalyse von Schwarzen Löchern mit Python
Python Django Tutorial (5)
Python Django Tutorial (2)
Zusammenfassung des Python-Tutorials
Datenanalyse Python
Starten Sie Python
Führen Sie eine Entitätsanalyse mit spaCy / GiNZA in Python durch
Python Django Tutorial (8)
Python Django Tutorial (6)
PRML Kapitel 12 Bayesianische Hauptanalyse Python-Implementierung
[Umgebungskonstruktion] Abhängigkeitsanalyse mit CaboCha mit Python 2.7
[In-Database Python Analysis-Lernprogramm mit SQL Server 2017] Schritt 2: Importieren Sie Daten mit PowerShell in SQL Server
Python Django Tutorial (7)
Python Django Tutorial (1)
Python Django Tutorial Tutorial
Scraping mit Python
Python Django Tutorial (3)
Python Django Tutorial (4)
[In-Database Python Analysis Tutorial mit SQL Server 2017] Schritt 4: Feature-Extraktion von Daten mit T-SQL
[Python] Implementierung von Clustering mit einem gemischten Gaußschen Modell
Erläuterung des Konzepts der Regressionsanalyse mit Python Teil 2
[Python] [Word] [python-docx] Einfache Analyse von Diff-Daten mit Python
Führen Sie die Sortierimplementierung / Berechnungsmengenanalyse zusammen und experimentieren Sie in Python
Erläuterung des Konzepts der Regressionsanalyse mit Python Teil 1
Hauptkomponentenanalyse mit Python von nim mit nimpy
Erläuterung des Konzepts der Regressionsanalyse mit Python Extra 1
[Technisches Buch] Einführung in die Datenanalyse mit Python -1 Kapitel Einführung-
Datenanalyse mit Python 2
Python: Zeitreihenanalyse
Datenanalyse mit xarray
[Docker] Tutorial (Python + PHP)
Bearbeiten Sie Redmine mit Python Redmine
RNN-Implementierung in Python
Fibonacci-Sequenz mit Python
ValueObject-Implementierung in Python
Datenanalyse Übersicht Python
Sprachanalyse mit Python
Datenbereinigung mit Python
Verwenden von Python # externen Paketen
WiringPi-SPI-Kommunikation mit Python
Altersberechnung mit Python
Python-Datenanalysevorlage
Python OpenCV Tutorial Memo
Suchen Sie Twitter mit Python
[Python-Tutorial] Datenstruktur
Orthologe Analyse mit OrthoFinder
Namensidentifikation mit Python
Hinweise zur Verwendung von Python-Unterprozessen
Cloud Run Tutorial (Python)