Et samarbeidssystem for filtreringsanbefalinger i Java

1. Introduksjon

I denne opplæringen lærer vi alt om Slope One-algoritmen i Java.

Vi viser også eksemplet på implementering av problemet med Collaborative Filtering (CF) - en maskinlæringsteknikk brukes av anbefalingssystemer.

Dette kan for eksempel brukes til å forutsi brukerinteresser for bestemte varer.

2. Samarbeidsfiltrering

Slope One-algoritmen er et varebasert samarbeidsfiltreringssystem. Det betyr at det er helt basert på rangering av bruker-element. Når vi beregner likheten mellom objekter, kjenner vi bare historien til rangeringen, ikke selve innholdet. Denne likheten brukes deretter til å forutsi potensielle brukerrangeringer for bruker-elementpar som ikke er i datasettet.

Bildet nedenfor viser den komplette prosessen med å skaffe og beregne rangering for den spesifikke brukeren:

Til å begynne med rangerte brukerne forskjellige elementer i systemet. Deretter beregner algoritmen likhetene. Etter det gir systemet spådommer for rangeringer av brukerelementer, som brukeren ikke har rangert ennå.

For mer informasjon om emnet for samarbeidsfiltrering, kan vi henvise til Wikipedia-artikkelen.

3. Slope One-algoritmen

Slope One ble kåret til den enkleste formen for ikke-triviell varebasert samarbeidsfiltrering basert på rangeringer. Det tar hensyn til både informasjon fra alle brukere som vurderte samme vare og fra de andre elementene rangert av samme bruker for å beregne likhetsmatrisen.

I vårt enkle eksempel skal vi forutsi brukerrangeringer på varene i butikken.

La oss starte med en enkel Java-modell for vårt problem og domene.

3.1. Java-modell

I vår modell har vi to hovedobjekter - elementer og brukere. De Punkt klasse inneholder navnet på varen:

private String itemName;

På den annen side, den Bruker klasse inneholder brukernavnet:

privat streng brukernavn;

Endelig har vi en InputData klasse som skal brukes til å initialisere dataene. La oss anta at vi lager fem forskjellige produkter i butikken:

Listeelementer = Arrays.asList (nytt element ("Candy"), nytt element ("Drink"), nytt element ("Soda"), nytt element ("Popcorn"), nytt element ("Snacks"));

Videre oppretter vi tre brukere som tilfeldig rangert noen av de ovennevnte ved hjelp av skalaen fra 0,0-1,0, der 0 betyr ingen interesse, 0,5 på en eller annen måte interessert og 1.0 betyr helt interessert. Som et resultat av datainitialisering får vi en Kart med data om rangering av brukerelementer:

Kart data;

3.2. Forskjeller og frekvenser Matriser

Basert på tilgjengelige data beregner vi forholdet mellom elementene, samt antall forekomster av varer. For hver bruker sjekker vi hans / hennes vurdering av varene:

for (HashMap-bruker: data.values ​​()) {for (Oppføring e: user.entrySet ()) {// ...}}

I neste trinn sjekker vi om varen finnes i matrisen vår. Hvis dette er en første forekomst, oppretter vi den nye oppføringen i kartene:

hvis (! diff.containsKey (e.getKey ())) {diff.put (e.getKey (), ny HashMap ()); freq.put (e.getKey (), ny HashMap ()); } 

Den første matrisen brukes til å beregne forskjellene mellom brukervurderingene. Verdiene av det kan være positive eller negative (siden forskjellen mellom rangeringer kan være negativ), og lagres som Dobbelt. På den annen side lagres frekvensene som Heltall verdier.

I neste trinn skal vi sammenligne rangeringene for alle elementene:

for (Oppføring e2: bruker.entrySet ()) {int oldCount = 0; hvis (freq.get (e.getKey ()). inneholder Key (e2.getKey ())) {oldCount = freq.get (e.getKey ()). get (e2.getKey ()). intValue (); } dobbel oldDiff = 0,0; hvis (diff.get (e.getKey ()). inneholder Key (e2.getKey ())) {oldDiff = diff.get (e.getKey ()). get (e2.getKey ()). doubleValue (); } dobbel observertDiff = e.getValue () - e2.getValue (); freq.get (e.getKey ()). put (e2.getKey (), oldCount + 1); diff.get (e.getKey ()). put (e2.getKey (), oldDiff + observertDiff); }

Hvis noen vurderte varen før, øker vi frekvensantallet med en. Videre sjekker vi gjennomsnittsforskjellen mellom varens rangeringer og beregner den nye observerteDiff.

Vær oppmerksom på at vi legger summen av oldDiff og observerteDiff som en ny verdi av en vare.

Til slutt beregner vi likhetspoengene i matrisene:

for (Item j: diff.keySet ()) {for (Item i: diff.get (j) .keySet ()) {double oldValue = diff.get (j) .get (i). doubleValue (); int count = freq.get (j) .get (i) .intValue (); diff.get (j) .put (i, oldValue / count); }}

Hovedlogikken er å dele den beregnede vareklassifiseringsforskjellen med antall forekomster. Etter dette trinnet kan vi skrive ut vår endelige forskjellsmatrise.

3.3. Spådommer

Som hoveddelen av Slope One skal vi forutsi alle manglende rangeringer basert på eksisterende data. For å gjøre det, må vi sammenligne klassifiseringene av brukeren med differensmatrisen beregnet i forrige trinn:

for (Entry e: data.entrySet ()) {for (Item j: e.getValue (). keySet ()) {for (Item k: diff.keySet ()) {double predictedValue = diff.get (k). get (j ) .doubleValue () + e.getValue (). get (j) .doubleValue (); dobbel finalValue = predictedValue * freq.get (k) .get (j) .intValue (); uPred.put (k, uPred.get (k) + finalValue); uFreq.put (k, uFreq.get (k) + freq.get (k) .get (j) .intValue ()); }} // ...}

Etter det må vi forberede de "rene" spådommene ved hjelp av koden nedenfor:

HashMap clean = ny HashMap (); for (Item j: uPred.keySet ()) {if (uFreq.get (j)> 0) {clean.put (j, uPred.get (j) .doubleValue () / uFreq.get (j) .intValue ( )); }} for (Item j: InputData.items) {if (e.getValue (). containsKey (j)) {clean.put (j, e.getValue (). get (j)); } annet hvis (! clean.containsKey (j)) {clean.put (j, -1.0); }}

Trikset å vurdere med større datasett er å bruke bare varepostene som har stor frekvensverdi (for eksempel> 1). Vær oppmerksom på at hvis prediksjonen ikke er mulig, vil verdien av den være lik -1.

Til slutt, veldig viktig merknad. Hvis algoritmen vår fungerte riktig, vi bør motta spådommer for varer som brukeren ikke vurderte, men også gjentatte rangeringer for varene han vurderte. Disse gjentatte vurderingene bør ikke endres, ellers betyr det at det er en feil i algoritmeimplementeringen.

3.4. Tips

Det er få viktige faktorer som påvirker Slope One-algoritmen. Her er noen tips om hvordan du kan øke nøyaktigheten og behandlingstiden:

  • vurdere å skaffe bruker-varevurderinger på DB-siden for store datasett
  • angi tidsrammen for henting av rangeringer, ettersom interessene til mennesker kan endres over tid - det vil også redusere tiden det tar å behandle inngangsdata
  • dele store datasett i mindre - du trenger ikke å beregne spådommer for alle brukere hver dag; du kan sjekke om brukeren interagerte med det forutsagte elementet og deretter legge til / fjerne ham / henne fra behandlingskøen neste dag

4. Konklusjon

I denne opplæringen kunne vi lære om Slope One-algoritmen. Videre introduserte vi det samarbeidende filtreringsproblemet for vareanbefalingssystemer.

De full gjennomføring av denne veiledningen finner du i GitHub-prosjektet.


$config[zx-auto] not found$config[zx-overlay] not found