Zasluge: NewsWire, The TakeOut.

Kako izgraditi sustav preporuka za podatke o kupnji (korak po korak)

Primjena kolaborativnog filtriranja na temelju predmeta s Turicreate i Python

Bez obzira jeste li odgovorni za korisničko iskustvo i strategiju proizvoda u tvrtki koja je usredotočena na kupca ili sjedite na svom kauču gledajući filmove s voljenim osobama, vjerojatno ste već svjesni nekih načina na koje se tehnologija preporuke koristi za personaliziranje vašeg sadržaja i ponuda.

Sustavi preporuka jedna su od najčešćih, lako razumljivih aplikacija učenja velikih podataka i strojnog učenja. Među najpoznatijim aplikacijama su Amazonov mehanizam preporuka koji nam pruža personaliziranu web stranicu kad posjećujemo web-lokaciju i Spotifyv popis preporuka pjesama kada slušamo pomoću njihove aplikacije.

Prošli smo put trebali izgraditi Spotify’s Discover Weekly s većinom audio podataka koristeći Spark. Ovoga puta izgradit ćemo mehanizam preporuka za opipljivije predmete.

Izazov

Ako pogledate na mreži, postoji mnogo načina za izgradnju preporučnih sustava za podatke temeljene na ocjenama, poput filmova i pjesama. Problem s modelima koji se temelje na ocjenama je taj što se ne mogu lako standardizirati za podatke s ciljanim vrijednostima, a to su podaci o kupnji ili učestalosti. Na primjer, ocjene su obično od 0–5 ili 0–10 za pjesme i filmove. Međutim, podaci o kupnji su kontinuirani i bez gornje granice.

Nažalost, mnoštvo mrežnih resursa daje rezultate bez procjene njihovih modela. Za većinu znanstvenika i inženjera podataka ovo je opasno područje kada uključite milijune podataka! Samo za industriju rezultati neće dobiti bilo gdje vaše alate bez ikakve procjene.

Cilj

Rješavajući ove probleme, izgradit ćemo modele kolaborativnog filtriranja za preporuku proizvoda kupcima pomoću podataka o kupnji. Konkretno ćemo detaljno obraditi postupak korak po korak u izradi sustava preporuka s Python-om i modulom strojnog učenja Turicreate. Ovi koraci uključuju:

  • Transformacija i normalizacija podataka
  • Modeli treninga
  • Procjena performansi modela
  • Odabir optimalnog modela

pregled proizvoda

Zamislite da trgovački lanac izdaje novu mobilnu aplikaciju koja omogućuje svojim kupcima da naručuju narudžbe prije nego što uđu u trgovinu.

Postoji mogućnost da aplikacija pokaže preporuke: Kada kupac prvi put dodirne stranicu "narudžba", možemo preporučiti da u košaru doda 10 najboljih predmeta, npr. pribor za jednokratnu upotrebu, svježe meso, čips, i tako dalje.

Alat će također moći pretraživati ​​popis preporuka na temelju određenog korisnika, tako da:

  • Unos: ID kupca
  • Vraća: rangirani popis stavki (ID-ove proizvoda) koje će korisnik najvjerojatnije htjeti staviti u svoju (praznu) "košaru"

izvršenje

1. Uvoz modula

  • pande i štek za upravljanje podacima
  • koristiti za odabir i ocjenu modela
  • sklearn za dijeljenje podataka u vlak i test skup
% load_ext automatsko učitavanje
% automatsko učitavanje 2

uvesti pande kao pd
uvesti numpy kao np
vrijeme uvoza
uvoz turicreate kao tc
iz sklearn.cross_validation import train_test_split

import sys
sys.path.append ( "..")

2. Učitajte podatke

U nastavku su korištene dvije skupove podataka u .csv formatu koje ovdje možete naći u podatkovnoj mapi:

  • Recom_1.csv koji se sastoji od popisa 1000 korisničkih ID-ova koje treba preporučiti kao izlaz
  • trx_data.csv koji se sastoji od korisničkih transakcija
kupaca = pd.read_csv ('../ podaci / preporuka_1.csv')
transakcije = pd.read_csv ('../ podaci / trx_data.csv')

3. Priprema podataka

Naš je cilj ovdje razvrstati svaki popis stavki u stupcu proizvoda na redove i računati broj proizvoda koje je korisnik kupio

3.1. Stvorite podatke s korisničkim, stavkama i ciljnim poljem

  • Ova će tablica biti ulaz za kasnije modeliranje
  • U ovom slučaju naš korisnik je korisnički ID, productId i vrijednost kupnje
data = pd.melt (transakcije.set_index ('customerId') ['proizvodi']. primijeniti (pd.Series) .reset_index (),
             id_vars = [ 'korisnički'],
             value_name = 'proizvodi') \
    .dropna (). pad (['varijabla'], os = 1) \
    .groupby (['customerId', 'proizvodi']) \
    .agg ({'products': 'count'}) \
    .rename (stupci = {'products': 'purchase_count'}) \
    .reset_index () \
    .rename (stupci = {'products': 'productId'})
data ['productId'] = data ['productId']. astype (np.int64)

3.2. Stvorite lutku

  • Lutka za označavanje je li kupac kupio taj predmet ili ne.
  • Ako netko kupi stavku, tada buy_dummy su označeni kao 1
  • Zašto stvarate lutku, umjesto da je normalizirate, pitate? Normaliziranje broja kupnji, kaže svaki korisnik, ne bi uspjelo jer kupci mogu imati različitu učestalost kupnje nemaju isti ukus. No stavke možemo normalizirati prema učestalosti kupnje za sve korisnike, što je učinjeno u odjeljku 3.3. ispod.
def create_data_dummy (podaci):
    data_dummy = data.copy ()
    data_dummy ['purchase_dummy'] = 1
    vratiti data_dummy
data_dummy = create_data_dummy (podaci)

3.3. Normalizirajte vrijednosti stavki za sve korisnike

  • Da bismo to učinili, normaliziramo učestalost kupnje svake stavke za korisnike tako što prvo stvorimo matricu korisničkih stavki na sljedeći način
df_matrix = pd.pivot_table (podaci, vrijednosti = 'buy_count', index = 'customerId', stupci = 'productId')
df_matrix_norm = (df_matrix-df_matrix.min ()) / (df_matrix.max () - df_matrix.min ())
# stvori tablicu za unos u modeliranje
d = df_matrix_norm.reset_index ()
d.index.names = ['scaled_purchase_freq']
data_norm = pd.melt (d, id_vars = ['customerId'], value_name = 'scaled_purchase_freq'). dropna ()
ispis (data_norm.shape)
data_norm.head ()

Gornji koraci se mogu kombinirati sa funkcijom definiranom u nastavku:

def normalize_data (podaci):
    df_matrix = pd.pivot_table (podaci, vrijednosti = 'buy_count', index = 'customerId', stupci = 'productId')
    df_matrix_norm = (df_matrix-df_matrix.min ()) / (df_matrix.max () - df_matrix.min ())
    d = df_matrix_norm.reset_index ()
    d.index.names = ['scaled_purchase_freq']
    return pd.melt (d, id_vars = ['customerId'], value_name = 'scaled_purchase_freq'). dropna ()

U ovom smo koraku normalizirali povijest njihove kupovine od 0–1 (pri čemu je 1 najveći broj kupnji za stavku, a 0 je broj kupnji za tu stavku).

4. Split vlak i test set

  • Podjela podataka na skupove treninga i testiranja važan je dio procjene prediktivnog modeliranja, u ovom slučaju kolaborativnog modela filtriranja. Tipično koristimo veći dio podataka za trening i manji dio za testiranje.
  • Mi koristimo omjer 80:20 za našu veličinu vlaka-test set.
  • Naš dio treninga koristit će se za razvoj prediktivnog modela, a drugi za ocjenu učinkovitosti modela.

U nastavku definirajmo funkciju dijeljenja.

def split_data (podaci):
    „””
    Podijeli skup podataka na set za trening i test.
    
    args:
        podaci (pandas.DataFrame)
        
    vraća
        vlak_data (tc.SFrame)
        test_data (tc.SFrame)
    „””
    vlak, test = vlak_test_split (podaci, test_size = .2)
    train_data = tc.Stranica (vlak)
    test_data = tc.Sokvir (test)
    povratni vlak_data, test_data

Sada kada imamo tri skupa podataka s brojenjem kupnje, lutkom kupnje i smanjenim brojem kupnji, željeli bismo podijeliti svaki za modeliranje.

vlak_data, test_data = split_data (podaci)
vlak_data_dummy, test_data_dummy = split_data (podaci_dummy)
vlak_data_norm, test_data_norm = split_data (data_norm)

5. Definirajte modele pomoću biblioteke Turicreate

Prije pokretanja složenijeg pristupa, poput kolaborativnog filtriranja, trebali bismo pokrenuti osnovni model za usporedbu i procjenu modela. Kako se osnovna linija obično koristi vrlo jednostavnim pristupom, trebale bi se odabrati tehnike koje se koriste izvan tog pristupa ako pokazuju relativno bolju točnost i složenost. U ovom slučaju koristit ćemo model popularnosti.

Kompliciraniji, ali uobičajeni pristup predviđanju predmeta kupnje je kolaborativno filtriranje. Više ću o modelu popularnosti i kolaborativnom filtriranju raspravljati u kasnijem odjeljku. Za sada, definirajmo naše varijable koje ćemo koristiti u modelima:

# stalne varijable za definiranje naziva polja uključuju:
user_id = 'customerId'
item_id = 'productId'
users_to_recommend = popis (kupci [user_id])
n_rec = 10 # broj stavki koje treba preporučiti
n_display = 30 # za prikaz prvih nekoliko redaka u izlaznom skupu podataka

Turicreate nam je vrlo jednostavno nazvao tehniku ​​modeliranja, pa ćemo definirati našu funkciju za sve modele na sljedeći način:

def model (vlak_data, ime, user_id, item_id, target, users_to_recommend, n_rec, n_display):
    ako je ime == 'popularnost':
        model = tc.popularity_recommender.create (vlak_data,
                                                    user_id = user_id,
                                                    ITEM_ID = ITEM_ID,
                                                    target = meta)
    elif name == 'kosinus':
        model = tc.item_s подобниity_recommender.create (vlak_data,
                                                    user_id = user_id,
                                                    ITEM_ID = ITEM_ID,
                                                    target = meta,
                                                    similarity_type = 'kosinus')
elif name == 'pearson':
        model = tc.item_s подобниity_recommender.create (vlak_data,
                                                    user_id = user_id,
                                                    ITEM_ID = ITEM_ID,
                                                    target = meta,
                                                    similarity_type = 'Pearsonov)
        
    preporuči = model.recommend (users = users_to_recommend, k = n_rec)
    recom.print_rows (n_display)
    model povratka

Dok sam pisao skripte python-a za sve gore navedene procese, uključujući pronalaženje sličnosti pomoću skripti python (koje možete pronaći ovdje, za sada koristimo biblioteku turicreate za brže hvatanje različitih mjera i procjenu modela.

6. Model popularnosti kao osnovna vrijednost

  • Model popularnosti uzima za preporuku najpopularnije artikle. Ovi artikli su proizvodi s najvećim brojem prodaje u odnosu na kupce.
  • Podaci o obuci koriste se za odabir modela

ja. Upotreba broja računa

name = 'popularnost'
target = 'buy_count'
popularnost = model (vlak_data, ime, user_id, item_id, target, users_to_recommend, n_rec, n_display)

ii. Korištenje lutke za kupnju

name = 'popularnost'
target = 'purchase_dummy'
pop_dummy = model (vlak_data_dummy, ime, korisnik_id, stavka_id, cilj, korisnici_to_rekomencija, n_rec, n_display)

iii. Upotreba smanjenog broja kupnji

name = 'popularnost'
target = 'scaled_purchase_freq'
pop_norm = model (vlak_data_norm, ime, korisnik_id, stavka_id, cilj, korisnici_to_rekomencija, n_rec, n_display)

6.1. Osnovni sažetak

  • Jednom kada smo kreirali model, predvidjeli smo stavke preporuka koristeći rezultate prema popularnosti. Kao što možete reći za rezultate svakog modela iznad, redovi prikazuju prvih 30 zapisa od 1000 korisnika s 10 preporuka. Ovih 30 zapisa uključuju 3 korisnika i njihove preporučene stavke, zajedno s rezultatima i silaznim redovima.
  • Kao rezultat, iako različiti modeli imaju različit popis preporuka, svakom korisniku se preporučuje isti popis od 10 stavki. To je zato što se popularnost izračunava uzimajući najpopularnije artikle kod svih korisnika.
  • Ako je primjer grupiranja u nastavku, proizvodi 132, 248, 37 i 34 najpopularniji su (najprodavaniji) kod kupaca. Pomoću broja njihovih kupnji podijeljenih s brojem kupaca, vidimo da se ovi proizvodi najmanje kupuju u prosjeku 3 puta u sklopu obučnog skupa transakcija (isto kao prva mjera popularnosti u varijabli kupnja_broj)

7. Model kolaborativnog filtriranja

U kolaborativnom filtriranju preporučujemo stavke na temelju toga kako slični korisnici kupuju stavke. Na primjer, ako su klijent 1 i kupac 2 kupili slične stvari, npr. 1 kupljeno X, Y, Z i 2 kupljeno X, Y, kupcu 2 preporučujemo artikl Z.

7.1. Metodologija

Da bismo definirali sličnost među korisnicima, koristimo sljedeće korake:

1. Napravite matricu korisničkih stavki, gdje vrijednosti indeksa predstavljaju jedinstvene ID-ove klijenta, a vrijednosti stupca predstavljaju jedinstvene ID-ove proizvoda

2. Napravite matricu sličnosti između predmeta. Ideja je izračunati koliko je proizvod sličan drugom proizvodu. Postoji nekoliko načina izračunavanja toga. U koracima 7.2 i 7.3 koristimo mjeru sličnosti kosinusa ili kruna.

  • Da biste izračunali sličnost proizvoda X i Y, pogledajte sve kupce koji su ocijenili oba ova predmeta. Na primjer, i X i Y ocijenili su kupci 1 i 2.
  • Zatim kreiramo dva predmeta-vektore, v1 za stavku X i v2 za stavku Y, u korisničkom prostoru (1, 2), a zatim pronalazimo kut kosinusa ili kruna / udaljenost između tih vektora. Nulti kut ili preklapajući se vektori kosinus vrijednosti 1 znače potpunu sličnost (ili po korisniku u svim stavkama postoji ista ocjena), a kut od 90 stupnjeva značio bi kosinus od 0 ili nema sličnosti.

3. Za svakog kupca predviđamo njegovu vjerojatnost da će kupiti proizvod (ili njegova kupnja) za proizvode koje nije kupio.

  • Za naš primjer, u slučaju točke Z (ciljna stavka) izračunat ćemo ocjenu za korisnika 2. Da bismo to izračunali, važemo tek izračunatu mjeru sličnosti između ciljne stavke i ostalih predmeta koje je kupac već kupio. Faktor vaganja je broj kupnji koji korisnik daje artiklima koje je već kupio.
  • Zatim skaliramo ovaj ponderirani zbroj mjera sličnosti, tako da izračunata ocjena ostaje unutar unaprijed definiranih granica. Dakle, predviđena ocjena za stavku Z za korisnika 2 izračunala bi se primjenom mjera sličnosti.

7.2. Kozin sličnost

  • Sličnost je kosusni kut između dvaju vektora predmetnih vektora A i B
  • Definirana je sljedećom formulom
  • Bliži vektori, manji će biti kut i veći kosinus

ja. Upotreba broja računa

name = 'kosinus'
target = 'buy_count'
cos = model (vlak_data, ime, user_id, item_id, target, users_to_recommend, n_rec, n_display)

ii. Korištenje lutke za kupnju

name = 'kosinus'
target = 'purchase_dummy'
cos_dummy = model (vlak_data_dummy, ime, user_id, item_id, target, users_to_recommend, n_rec, n_display)

iii. Upotreba smanjenog broja kupnji

name = 'kosinus'
target = 'scaled_purchase_freq'
cos_norm = model (vlak_data_norm, ime, korisnik_id, stavka_id, cilj, korisnici_to_rekomencija, n_rec, n_display)

7.3. Pearsonova sličnost

  • Sličnost je koeficijent kruška između dva vektora.
  • Definirana je sljedećom formulom

ja. Upotreba broja računa

name = 'kruška'
target = 'buy_count'
kruška = model (vlak_data, ime, user_id, item_id, target, users_to_recommend, n_rec, n_display)

ii. Korištenje lutke za kupnju

name = 'kruška'
target = 'purchase_dummy'
pear_dummy = model (vlak_data_dummy, ime, korisnik_id, stavka_id, cilj, korisnici_to_rekomencija, n_rec, n_display)

iii. Upotreba smanjenog broja kupnji

name = 'kruška'
target = 'scaled_purchase_freq'
pear_norm = model (vlak_data_norm, ime, korisnik_id, stavka_id, cilj, korisnici_to_rekomencija, n_rec, n_display)

8. Procjena modela

Za procjenu preporučnih motora možemo upotrijebiti koncept RMSE i preciznog opoziva.

ja. RMSE (Root Srednje pogreške u kvadraturi)

  • Mjeri pogrešku predviđenih vrijednosti
  • Manje vrijednosti RMSE, bolje preporuke

ii. Podsjetiti

  • Koliki se postotak proizvoda koje korisnik kupuje zapravo preporučuje?
  • Ako kupac kupi 5 proizvoda i preporukom je odlučio pokazati ih 3, tada opoziv iznosi 0,6

iii. Preciznost

  • Od svih preporučenih stavki, koliko se korisniku zapravo svidjelo?
  • Ako se kupcu preporuči 5 proizvoda od kojih je kupio 4, preciznost je 0,8

Zašto su i opoziv i preciznost važni?

  • Razmislite o slučaju gdje preporučujemo sve proizvode, tako da će naši kupci sigurno pokriti predmete koji su im se svidjeli i kupili. U ovom slučaju imamo 100% opoziva! Znači li to da je naš model dobar?
  • Moramo razmotriti preciznost. Ako preporučamo 300 predmeta, ali korisnik ih voli i kupi ih ​​samo 3, preciznost je 0,1%! Ova vrlo niska preciznost ukazuje na to da model nije sjajan, usprkos izvrsnom opozivu.
  • Stoga nam cilj mora biti optimiziranje i opoziva i preciznosti (kako bi bilo što bliže 1).

Prvo napravimo početne varijable koje se mogu pozivati ​​za evaluaciju modela:

models_w_counts = [popularnost_model, cos, kruška]
models_w_dummy = [pop_dummy, cos_dummy, pear_dummy]
models_w_norm = [pop_norm, cos_norm, pear_norm]
names_w_counts = ['Model popularnosti u brojevima kupnji', 'Kosin sličnost u brojevima kupnji', 'Pearson-ova sličnost u brojevima kupovine']
names_w_dummy = ['Model popularnosti na lutki za kupnju', 'Sličnost kozina na lutki za kupnju', 'Sličnost Pearsona kod lutke za kupnju']
names_w_norm = ['Model popularnosti za skalirane brojeve kupnje', 'Kosin sličnost u skaliranim brojevima kupovine', 'Pearson-ova sličnost u skaliranim otkupnim brojevima kupnje']

Usporedimo sve modele koje smo izgradili na temelju RMSE i karakteristika preciznog opoziva:

eval_counts = tc.recommender.util.compare_models (test_data, models_w_counts, model_names = names_w_counts)
eval_dummy = tc.recommender.util.compare_models (test_data_dummy, models_w_dummy, model_names = names_w_dummy)
eval_norm = tc.recommender.util.compare_models (test_data_norm, models_w_norm, model_names = names_w_norm)

8.1. Rezultat evaluacije

  • Na temelju RMSE-a
  • Na temelju preciznosti i opoziva

8.2. Sažetak evaluacije

  • Popularnost v. Kolaborativno filtriranje: Možemo vidjeti da algoritmi kolaborativnog filtriranja djeluju bolje od modela popularnosti za kupnju. Doista, model popularnosti ne daje nikakve personalizacije jer svakom korisniku daje isti popis preporučenih stavki.
  • Preciznost i opoziv: Promatrajući gornji sažetak, vidimo da su preciznost i opoziv za brojeve kupnje> lutka kupnje> normalizirane mjere kupnje. No, budući da je rezultat preporuka za normalizirane podatke o kupnji nula i postojan, mi biramo lutku. Zapravo se RMSE ne razlikuje mnogo između modela na lutki i onih na normaliziranim podacima.
  • RMSE: Budući da je RMSE veći pomoću biskonske udaljenosti od viskoze, odabrali bismo model manjih pogrešaka srednjeg kvadrata, što bi u ovom slučaju bilo kosinus.
Stoga za svoj konačni model odabiremo Cosine sličnost u Purchase Dummy pristupu.

9. Konačni rezultat

Konačno, želimo manipulirati formatom za izlaz preporuke jednom koji možemo izvesti u csv, a također i funkcijom koja će vratiti popis preporuka s obzirom na korisnički ID.

Moramo prvo pokrenuti model pomoću čitavog skupa podataka, jer smo došli do konačnog modela pomoću podataka vlaka i ocijenili se s testnim skupom.

final_model = tc.item_s подобниity_recommender.create (tc.SFrame (data_norm),
                                            user_id = user_id,
                                            ITEM_ID = ITEM_ID,
                                            target = 'purchase_dummy', sličnost_type = 'kosinus')
Recom = final_model.recommend (users = users_to_recommend, k = n_rec)
recom.print_rows (n_display)

9.1. CSV izlazna datoteka

Ovdje želimo manipulirati našim rezultatom na csv izlaz. Da vidimo što imamo:

df_rec = Recom.to_dataframe ()
ispis (df_rec.shape)
df_rec.head ()

Definirajmo funkciju za stvaranje željenog izlaza:

def create_output (model, users_to_recommend, n_rec, print_csv = Istina):
    preporuka = ​​model.recommend (users = users_to_recommend, k = n_rec)
    df_rec = preporuka.to_dataframe ()
    df_rec ['RecommendedProducts'] = df_rec.groupby ([korisnik_id]) [item_id] \
        .transform (lambda x: '|' .join (x.astype (str)))
    df_output = df_rec [['customerId', 'RecommendedProducts']] drop_duplicates () \
        .sort_values ​​( 'korisnički'). set_index ( 'korisnički')
    ako print_csv:
        df_output.to_csv ( '../ izlaz / option1_recommendation.csv')
        ispis ("Izlazna datoteka se može naći u mapi 'izlaz' s imenom 'opcija1_recommendation.csv'")
    vrati df_output

Omogućuje ispis dolje ispisa i postavite true na ovaj način, doslovno bismo mogli ispisati našu izlaznu datoteku u csv-u, a tu također možete pronaći.

df_output = create_output (pear_norm, users_to_recommend, n_rec, print_csv = True)
ispis (df_output.shape)
df_output.head ()

9.2. Funkcija preporuke kupca

Definirajmo funkciju koja će vratiti popis preporuka s obzirom na korisnički ID:

def customer_recomendation (kupac_id):
    ako customer_id nije na df_output.index:
        print ("Kupca nije pronađeno.")
        vrati customer_id
    vratiti df_output.loc [kupac_id]

Bingo!

Sažetak

U ovom smo članku uspjeli preći korak po korak davanja preporuka kupcima. Koristili smo pristupe kolaborativnog filtriranja s mjerenjem Cosine i Pearson i usporedili modele s našim osnovnim modelom popularnosti.

Pripremili smo i tri skupa podataka koji uključuju redovito brojanje kupovine, kupnju lutke, kao i normaliziranu učestalost kupovine kao našu ciljnu varijablu. Koristeći RMSE, preciznost i opoziv, procijenili smo naše modele i uočili utjecaj personalizacije. Napokon, odabrali smo Cosine pristup pomoću obrasnih podataka kao našeg najboljeg modela sustava preporuka.

Nadam se da ćete uživati ​​čitajući ovaj članak i da ste sada spremni stvoriti vlastiti gumb "dodaj u košaricu". Molimo vas da date 50 claps i komentar u nastavku ako želite još ovakvih čitanja :) Uživajte u hakiranju!

Moorissa je znanstvenik s podacima i vođa društvenih poduzeća. U prosincu 2017. diplomirala je na Sveučilištu Columbia sa studijom znanosti o podacima i strojnom učenju. Nada se da će uvijek iskoristiti svoje vještine za stvaranje svijeta boljim mjestom, jednog dana u dan.