Wir werden die Informationen von Kaggle aktualisieren, der in der Vergangenheit teilgenommen hat. Hier werden wir die Dateneinführung von Instacart Market Basket Analysis und die wichtigsten Diskussionen im Forum aufgreifen. Ich werde den Ansatz des Gewinners in einem anderen Artikel vorstellen. Da der Code des Notebooks eingeführt wird, ändern Sie bitte% matplotlib inline usw. entsprechend.
Das Data Science-Team von Instacart entwickelt viel. Erstellen Sie beispielsweise ein Vorhersagemodell eines Benutzers, der einen Artikel, einen neuen Benutzer oder einen Artikel zurückkauft, der als Nächstes in den Warenkorb gelegt werden soll. In jüngerer Zeit hat Instacart sogar detaillierte Transaktionsinformationen öffentlich zugänglich gemacht. In diesem Wettbewerb werden wir unter Verwendung dieser offenen Daten um die Genauigkeit des Vorhersagemodells konkurrieren. Der Inhalt der Prognose lautet "Vorhersage des nächsten Produkts, das der Benutzer aus dem zuvor gekauften Produkt bestellen wird". Auch wenn Instacart nicht direkt mit der Konkurrenz zusammenhängt, sucht es derzeit nach hervorragenden Ingenieuren für maschinelles Lernen. ](Https://boards.greenhouse.io/instacart/jobs/590555#.WXBm_tPyjOQ) Wenn Sie interessiert sind, überprüfen Sie es bitte.
Instacart verwendet XGBoost und word2vec, um vorherzusagen, was Benutzer als Nächstes kaufen werden. -Darstellungen-von-Wörtern-und-Phrasen-und-deren-Kompositionalität.pdf) und Ärgerlich. Empfehlen Sie ein ähnliches Produkt wie das, das Sie mit "Nochmals kaufen" gekauft haben.
Darüber hinaus empfehlen wir die vom erstellten Modell vorhergesagten Ergebnisse.
Mit diesen öffentlich verfügbaren Daten bietet Instacart den Verbrauchern das Potenzial, neue Lebensmittel zu entdecken.
Die Merkmale dieser Zeit sind wie folgt.
Dieser Bewertungsindex verwendet den allgemeinen F1-Score als Index für binäre Klassifizierungsprobleme.
Bitte laden Sie die Daten von [diesem Link] herunter (https://www.kaggle.com/c/instacart-market-basket-analysis/data).
Diesmal gibt es 7 Arten von Daten. Jordan Tremoureux visualisiert die Zuordnung relationaler Daten.
AISLES.csv und DEPARTMENTS.csv sind Informationen zur Produktkategorie und Informationen wie Gemüse, Fleisch und Süßigkeiten. PRODUCTS.csv zeigt die spezifische Zuordnung zwischen dem Produktnamen und diesen Kategoriedaten. ORDER_PRODUCTS_ {PRIOR, TRAIN} .csv sind die wichtigsten Trainingsdaten. PRIOR ist die vorherige Bestellinformation und TRAIN ist die aktuelle Bestellinformation. Diese Daten enthalten ein 0-1-Flag mit der Bezeichnung "Nachbestellt". Wenn dies 1 ist, kaufen Sie denselben Artikel. Die Erklärung hier ist etwas kompliziert, daher werden wir sie in der nächsten EDA ausführlich betrachten. SAMPLE_SUBMISSION.csv ist eine Demo-Datei, die das Übermittlungsformat zeigt. Schließlich enthält ORDERS.csv Zeitreiheninformationen, die ORDER_PRODUCTS__ {PRIOR, TRAIN} .csv zugeordnet sind. Obwohl es sich um eine Zeitreihe handelt, handelt es sich nicht um einen Zeitstempel, sondern um Zeitunterschiedsinformationen wie "bis zum nächsten Kauf? Tag".
Was die Daten insgesamt betrifft, so sind mehr als 200.000 Artikel für die Kaufhistorie eines Benutzers für einen Monat ordentlich und organisiert organisiert. Indem Zeit als Zeitunterschied ausgedrückt wird, kann komplexe Analyse aus anderen Wettbewerben weggelassen werden.
Zwei Analyseinformationen
Obwohl hier nicht vorgestellt, ist Philipp Rachtholz Analyseergebnis in R geschrieben auch wunderbar. Der Inhalt entspricht fast dem der Analyse in 1), aber die Informationen sind in einer Baumkarte organisiert, damit sie leicht zu sehen sind. Überprüfen Sie sie daher bitte, wenn Sie interessiert sind.
Importieren Sie zunächst die Bibliothek
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt
import seaborn as sns
color = sns.color_palette()
%matplotlib inline
pd.options.mode.chained_assignment = None # default='warn'
Die häufig auftretende Warnung wird in der letzten Optionseinstellung deaktiviert. Bitte ändern Sie diesen Bereich als Hobby. Lassen Sie uns die Anordnung der Daten überprüfen.
from subprocess import check_output
print(check_output(["ls", "../input"]).decode("utf8"))
#aisles.csv
#departments.csv
#order_products__prior.csv
#order_products__train.csv
#orders.csv
#products.csv
#sample_submission.csv
Es wird davon ausgegangen, dass die Daten im Eingabeordner in der nächsthöheren Hierarchie installiert sind, in der das Notizbuch geöffnet ist. Wenn es als # ~ angezeigt wird, ist es normal.
Importieren Sie dann die Daten.
order_products_train_df = pd.read_csv("../input/order_products__train.csv")
order_products_prior_df = pd.read_csv("../input/order_products__prior.csv")
orders_df = pd.read_csv("../input/orders.csv")
products_df = pd.read_csv("../input/products.csv")
aisles_df = pd.read_csv("../input/aisles.csv")
departments_df = pd.read_csv("../input/departments.csv")
Überprüfen Sie den gelesenen Inhalt und sehen Sie.
orders_df.head()
order_products_prior_df.head()
order_products_train_df.head()
Es scheint, dass orders_df fast alle Informationen enthält. order_products_prior_df und order_products_train_df haben genau die gleichen Spalten. Was ist der Unterschied zwischen den beiden Dateien? Dieses Mal werden wir den nächsten Einkauf aus der vergangenen Kaufhistorie vorhersagen. Mit anderen Worten, die vorherige Datei enthält die Kaufhistorie von Zug und Test, und order_products_train_df sind die richtigen Antwortdaten für das Training. DBEN erklärt es in einem leicht verständlichen Diagramm.
Beispielsweise gibt es in orders_df 10 Daten für user_id = 1 in eval_set = prior, 1 in eval_set = train und 0 in eval_set = test. Andererseits gibt es 5 Daten von user_id = 4 in eval_set = prior, 0 in eval_set = train und 1 in eval_set = test. Diese "Neuordnung" von eval_set = test ist das diesmal vorherzusagende Ziel, und es wird geschätzt, ob user_id = 4 den zuvor gekauften Artikel zurückgekauft hat.
Schauen wir uns zur Bestätigung die Anzahl der Prioritäten, Züge und Tests an, die in orders_df enthalten sind.
cnt_srs = orders_df.eval_set.value_counts()
plt.figure(figsize=(12,8))
sns.barplot(cnt_srs.index, cnt_srs.values, alpha=0.8, color=color[1])
plt.ylabel('Number of Occurrences', fontsize=12)
plt.xlabel('Eval set type', fontsize=12)
plt.title('Count of rows in each dataset', fontsize=15)
plt.xticks(rotation='vertical')
plt.show()
Da Zug und Test von mehreren Priors vorhergesagt werden, können wir sehen, dass es überwiegend viele Priors gibt.
Aus dem Inhalt von 5.1.1. Können Sie ersehen, dass etwas analysiert werden kann, indem Sie es mit eval_set visualisieren und neu anordnen.
Lassen Sie uns zunächst sehen, wie viele Benutzer sich in den vorherigen Versionen befinden, trainieren und testen. Gruppieren Sie orders_df mit eval_set und zählen Sie user_ids innerhalb jeder Gruppe ohne Duplizierung.
def get_unique_count(x):
return len(np.unique(x))
cnt_srs = orders_df.groupby("eval_set")["user_id"].aggregate(get_unique_count)
cnt_srs
Aggregat ist eine Methode, mit der verschiedene Funktionen gruppenweise auf eine Gruppe angewendet werden.
eval_set
prior 206209
test 75000
train 131209
Name: user_id, dtype: int64
Sie können sehen, dass insgesamt 206.209 Personen anwesend sind, von denen 131.209 im Zug und 75.000 im Test sind. Wie oft erscheint der Benutzer?
cnt_srs = orders_df.groupby("user_id")["order_number"].aggregate(np.max).reset_index()
cnt_srs = cnt_srs.order_number.value_counts()
plt.figure(figsize=(12,8))
sns.barplot(cnt_srs.index, cnt_srs.values, alpha=0.8, color=color[2])
plt.ylabel('Number of Occurrences', fontsize=12)
plt.xlabel('Maximum order number', fontsize=12)
plt.xticks(rotation='vertical')
plt.show()
Ich habe das Produkt mindestens 4 Mal und höchstens 100 Mal gekauft.
Wahrscheinlich gibt es am Wochenende viele Bestellungen. Teilen wir die Anzahl der Bestellungen durch die Tagesinformationen. Die Tagesinformation lautet 'order_dow'.
plt.figure(figsize=(12,8))
sns.countplot(x="order_dow", data=orders_df, color=color[0])
plt.ylabel('Count', fontsize=12)
plt.xlabel('Day of week', fontsize=12)
plt.xticks(rotation='vertical')
plt.title("Frequency of order by week day", fontsize=15)
plt.show()
Wie Sie sehen können, scheinen Wochentag = 0 und 1 Samstag bzw. Sonntag zu treffen. Die Anzahl der Bestellungen an Wochentagen unterscheidet sich geringfügig. Schauen wir uns auch die Anzahl der Bestellungen nach Zeit an.
plt.figure(figsize=(12,8))
sns.countplot(x="order_hour_of_day", data=orders_df, color=color[1])
plt.ylabel('Count', fontsize=12)
plt.xlabel('Hour of day', fontsize=12)
plt.xticks(rotation='vertical')
plt.title("Frequency of order by hour of day", fontsize=15)
plt.show()
Vielleicht, weil wir samstags und sonntags nachsehen, ist die am häufigsten bestellte Zeit tagsüber (10 und 15 Uhr). Es gibt nur wenige Bestellungen am Morgen und die Anzahl der Bestellungen nimmt ab, wenn die Zeit spät abends wird.
Die Beziehung zwischen der Anzahl der Bestellungen für den Tag und die Uhrzeit scheint tief zu sein. Visualisieren wir sie mit einer Heatmap.
grouped_df = orders_df.groupby(["order_dow", "order_hour_of_day"])["order_number"].aggregate("count").reset_index()
grouped_df = grouped_df.pivot('order_dow', 'order_hour_of_day', 'order_number')
plt.figure(figsize=(12,6))
sns.heatmap(grouped_df)
plt.title("Frequency of Day of week Vs Hour of day")
plt.show()
Pivot konzentriert sich nur auf die beiden Achsen des DataFrame und erstellt einen neuen Frame.
Es gibt einen deutlichen Unterschied zwischen Wochentagen und Feiertagen. An Wochentagen gibt es keinen großen Unterschied zwischen den Tagen, und die Bestellungen sind von 9 bis 16 Uhr hoch. Die Feiertage variieren samstags und sonntags erheblich. Bestellungen werden meistens samstags nachmittags aufgegeben und Bestellungen werden bis spät in die Nacht fortgesetzt. Sonntags haben die meisten Bestellungen am Morgen.
Schauen wir uns als nächstes das Zeitintervall der Bestellung an.
plt.figure(figsize=(12,8))
sns.countplot(x="days_since_prior_order", data=orders_df, color=color[3])
plt.ylabel('Count', fontsize=12)
plt.xlabel('Days since prior order', fontsize=12)
plt.xticks(rotation='vertical')
plt.title("Frequency distribution by days since prior order", fontsize=15)
plt.show()
Die Anzahl der Tage von der vorherigen Bestellung bis zur nächsten Bestellung wird durch "Tage_ seit_Vorrang_bestellung" angegeben. Der Höhepunkt ist am 7. und 30. und nach dem 7. gibt es jede Woche eine Periodizität, wie zum Beispiel den 14., 21. und 28 ..
Nachdem die Beziehung zwischen Zeit und Auftragsanzahl klar ist, werfen wir einen Blick auf die vorhersehbaren Rückkäufe in diesem Wettbewerb.
print(order_products_prior_df.reordered.sum() / order_products_prior_df.shape[0])
print(order_products_train_df.reordered.sum() / order_products_train_df.shape[0])
0.589697466792
0.598594412751
Es ist ersichtlich, dass die Rückkaufrate sowohl für den Vorgänger als auch für den Zug bei 59% liegt. Fast die restlichen 40% waren Bestellungen ohne Rückkauf, daher enthält sie wahrscheinlich eine Bestellung (order_id), die keinen Rückkauf enthält.
grouped_df = order_products_prior_df.groupby("order_id")["reordered"].aggregate("sum").reset_index()
grouped_df["reordered"].ix[grouped_df["reordered"]>1] = 1
grouped_df.reordered.value_counts() / grouped_df.shape[0]
1 0.879151
0 0.120849
Name: reordered, dtype: float64
12% der Bestellungen wurden zuvor nicht zurückgekauft.
grouped_df = order_products_train_df.groupby("order_id")["reordered"].aggregate("sum").reset_index()
grouped_df["reordered"].ix[grouped_df["reordered"]>1] = 1
grouped_df.reordered.value_counts() / grouped_df.shape[0]
1 0.93444
0 0.06556
Name: reordered, dtype: float64
Bestellungen, die nicht im Zug zurückgekauft wurden, betragen 6%, was die Hälfte der Priorität darstellt.
Wie viel bestellen Sie in einer Bestellung? Lassen Sie uns ein Histogramm machen.
grouped_df = order_products_train_df.groupby("order_id")["add_to_cart_order"].aggregate("max").reset_index()
cnt_srs = grouped_df.add_to_cart_order.value_counts()
plt.figure(figsize=(12,8))
sns.barplot(cnt_srs.index, cnt_srs.values, alpha=0.8)
plt.ylabel('Number of Occurrences', fontsize=12)
plt.xlabel('Number of products in the given order', fontsize=12)
plt.xticks(rotation='vertical')
plt.show()
SRK zählt order_id nicht, berechnet jedoch die Anzahl der Bestellungen gleichzeitig aus dem Maximalwert von add_to_cart_order. Am häufigsten sind 5 gleichzeitige Ordnungen, die eine Abnahme der rechtsschwänzigen Poisson-Verteilung zeigen.
Daten über Produkte werden auf Produkte, Gänge und Abteilungen verteilt. Zunächst werden wir diese Informationen kombinieren.
order_products_prior_df = pd.merge(order_products_prior_df, products_df, on='product_id', how='left')
order_products_prior_df = pd.merge(order_products_prior_df, aisles_df, on='aisle_id', how='left')
order_products_prior_df = pd.merge(order_products_prior_df, departments_df, on='department_id', how='left')
order_products_prior_df.head()
Diese Daten wurden unter Verwendung von product_id, aisle_id und department_id als Schlüssel kombiniert.
** Analyse nach Produktname ** Was ist der am häufigsten bestellte Produktname?
cnt_srs = order_products_prior_df['product_name'].value_counts().reset_index().head(20)
cnt_srs.columns = ['product_name', 'frequency_count']
cnt_srs
Bananen sind oben, und danach stehen verschiedene Lebensmittel in einer Reihe, die sich auf Früchte konzentrieren. Darüber hinaus sind fast alle Produkte Bio-Produkte.
** Analyse nach Produktkategorie (Gang) ** Welche Produkte stehen in einer Reihe? Informationen zum Produkttyp finden Sie im Gang.
cnt_srs = order_products_prior_df['aisle'].value_counts().head(20)
plt.figure(figsize=(12,8))
sns.barplot(cnt_srs.index, cnt_srs.values, alpha=0.8, color=color[5])
plt.ylabel('Number of Occurrences', fontsize=12)
plt.xlabel('Aisle', fontsize=12)
plt.xticks(rotation='vertical')
plt.show()
Die beiden häufigsten sind frisches Obst und frisches Gemüse.
** Analyse nach Abteilung **
Werfen wir einen Blick auf die Produktabteilung.
plt.figure(figsize=(10,10))
temp_series = order_products_prior_df['department'].value_counts()
labels = (np.array(temp_series.index))
sizes = (np.array((temp_series / temp_series.sum())*100))
plt.pie(sizes, labels=labels,
autopct='%1.1f%%', startangle=200)
plt.title("Departments distribution", fontsize=15)
plt.show()
Produzieren ist die häufigste Abteilung.
** Abteilungs-Rückkauf-Verhältnis **
Welche Abteilungen werden voraussichtlich zurückgekauft?
grouped_df = order_products_prior_df.groupby(["department"])["reordered"].aggregate("mean").reset_index()
plt.figure(figsize=(12,8))
sns.pointplot(grouped_df['department'].values, grouped_df['reordered'].values, alpha=0.8, color=color[2])
plt.ylabel('Reorder ratio', fontsize=12)
plt.xlabel('Department', fontsize=12)
plt.title("Department wise reorder ratio", fontsize=15)
plt.xticks(rotation='vertical')
plt.show()
Körperpflege wird am wenigsten zurückgekauft und tägliche Eier werden am meisten zurückgekauft.
** Produktkategorie-Rückkauf-Verhältnis ** Betrachten wir die Abteilung und die Produktkategorie (Gang) nach Rückkaufverhältnis.
grouped_df = order_products_prior_df.groupby(["department_id", "aisle"])["reordered"].aggregate("mean").reset_index()
fig, ax = plt.subplots(figsize=(12,20))
ax.scatter(grouped_df.reordered.values, grouped_df.department_id.values)
for i, txt in enumerate(grouped_df.aisle.values):
ax.annotate(txt, (grouped_df.reordered.values[i], grouped_df.department_id.values[i]), rotation=45, ha='center', va='center', color='green')
plt.xlabel('Reorder Ratio')
plt.ylabel('department_id')
plt.title("Reorder ratio of different aisles", fontsize=15)
plt.show()
Die vertikale Achse ist die Abteilung und die horizontale Achse ist die Rückkaufquote. Die Punkte auf derselben Höhe sind Produkte in verschiedenen Kategorien in derselben Kategorie.
** Bestellung zum Warenkorb-Rückkaufpreis hinzufügen **
order_products_prior_df["add_to_cart_order_mod"] = order_products_prior_df["add_to_cart_order"].copy()
order_products_prior_df["add_to_cart_order_mod"].ix[order_products_prior_df["add_to_cart_order_mod"]>70] = 70
grouped_df = order_products_prior_df.groupby(["add_to_cart_order_mod"])["reordered"].aggregate("mean").reset_index()
plt.figure(figsize=(12,8))
sns.pointplot(grouped_df['add_to_cart_order_mod'].values, grouped_df['reordered'].values, alpha=0.8, color=color[2])
plt.ylabel('Reorder ratio', fontsize=12)
plt.xlabel('Add to cart order', fontsize=12)
plt.title("Add to cart order - Reorder ratio", fontsize=15)
plt.xticks(rotation='vertical')
plt.show()
Apropos natürlich, aber je mehr Produkte Sie zu Beginn in den Warenkorb legen, desto mehr kaufen Sie zurück. Sie können sehen, dass die Artikel, die Sie ständig kaufen, zuerst in den Warenkorb gelegt werden.
** Zeitrückkaufrate ** Schauen wir uns den Rückkaufsatz für den Tag und die Tageszeit an. Erstellen Sie die drei in 5.1.2 erstellten Diagramme. Verwenden Sie den Durchschnittswert von neu angeordnet als Index.
order_products_train_df = pd.merge(order_products_train_df, orders_df, on='order_id', how='left')
grouped_df = order_products_train_df.groupby(["order_dow"])["reordered"].aggregate("mean").reset_index()
plt.figure(figsize=(12,8))
sns.barplot(grouped_df['order_dow'].values, grouped_df['reordered'].values, alpha=0.8, color=color[3])
plt.ylabel('Reorder ratio', fontsize=12)
plt.xlabel('Day of week', fontsize=12)
plt.title("Reorder ratio across day of week", fontsize=15)
plt.xticks(rotation='vertical')
plt.ylim(0.5, 0.7)
plt.show()
Es scheint, dass die Rückkaufrate an einem bestimmten Tag nicht steigt oder fällt.
grouped_df = order_products_train_df.groupby(["order_hour_of_day"])["reordered"].aggregate("mean").reset_index()
plt.figure(figsize=(12,8))
sns.barplot(grouped_df['order_hour_of_day'].values, grouped_df['reordered'].values, alpha=0.8, color=color[4])
plt.ylabel('Reorder ratio', fontsize=12)
plt.xlabel('Hour of day', fontsize=12)
plt.title("Reorder ratio across hour of day", fontsize=15)
plt.xticks(rotation='vertical')
plt.ylim(0.5, 0.7)
plt.show()
Am Morgen bestellte Artikel werden wahrscheinlich zurückgekauft.
grouped_df = order_products_train_df.groupby(["order_dow", "order_hour_of_day"])["reordered"].aggregate("mean").reset_index()
grouped_df = grouped_df.pivot('order_dow', 'order_hour_of_day', 'reordered')
plt.figure(figsize=(12,6))
sns.heatmap(grouped_df)
plt.title("Reorder ratio of Day of week Vs Hour of day")
plt.show()
Insgesamt ist die morgendliche Rückkaufrate hoch. Es ist besonders hoch um 6-8 Uhr am Wochenende und 5-6 Uhr am Dienstag und Mittwoch. In 5.1.2. Gab es am Samstag- und Sonntagmorgen und -nachmittag viele Bestellungen. In Bezug auf den Rückkauf stellte ich jedoch fest, dass es am frühen Morgen viele gibt, unabhängig von Wochentagen und Feiertagen.
In Medium's Artikel führt Instacart offene Daten ein. Die im Artikel verwendeten Daten scheinen mit den in diesem Wettbewerb behandelten Daten übereinzustimmen. Neben der Einführung der Daten werden auch einige Analyseergebnisse veröffentlicht. Hier werde ich die beiden im Artikel vorgestellten Figuren erläutern.
Diese Abbildung ist ein Streudiagramm, in dem die Anzahl der Käufe und die Rückkaufrate pro Gang dargestellt sind. Frisches Obst hat eine höhere Rückkaufrate als frisches Gemüse. Gemüse ist mehr für Rezepte als für Obst und kann das Ergebnis von zeitweiligen Einkäufen sein. Auch Lebensmittel wie Suppen- und Brotteigzutaten weisen die niedrigsten Rückkaufraten auf. Wahrscheinlich, weil die Nachfragefrequenz in erster Linie niedrig ist.
Gesunde Snacks und Hauptnahrungsmittel werden oft morgens gekauft, und Eis (insbesondere Half Baked, The Tonight Dough) wird oft abends gekauft. Von den 25 zuletzt (abends) bestellten Artikeln waren 24 Eiscreme und 25 Tiefkühlpizza.
Chippy gibt die zweite Hälfte der Abbildung wieder. Diese Figur ist in R geschrieben und hat ein Volumen von ca. 300 Zeilen. Wenn Sie interessiert sind, überprüfen Sie es bitte.
(Ich werde es später hinzufügen.)
Recommended Posts