Együttműködő szűrési ajánlási rendszer a Java-ban

1. Bemutatkozás

Ebben az oktatóanyagban mindent megtudhatunk a Java Slope One algoritmusáról.

Megmutatjuk a kollaboratív szűrés (CF) problémáját is - egy gépi tanulási technika ajánlási rendszerek használják.

Ez felhasználható például bizonyos elemek felhasználói érdeklődésének előrejelzésére.

2. Együttműködő szűrés

A Slope One algoritmus elemalapú együttműködési szűrőrendszer. Ez azt jelenti, hogy teljesen a felhasználói cikkek rangsorolásán alapul. Az objektumok közötti hasonlóság kiszámításakor csak a rangsor történetét ismerjük, magát a tartalmat nem. Ezt a hasonlóságot felhasználják az adatkészletben nem szereplő felhasználói cikkpárok lehetséges felhasználói rangsorának megjóslására.

Az alábbi kép az adott felhasználó értékelésének megszerzésének és kiszámításának teljes folyamatát mutatja:

Eleinte a felhasználók a rendszer különböző elemeit értékelik. Ezután az algoritmus kiszámítja a hasonlóságokat. Ezt követően a rendszer előrejelzéseket készít a felhasználói tételek értékeléséről, amelyeket a felhasználó még nem értékelt.

Az együttműködésen alapuló szűrés témaköréről a Wikipedia cikkben olvashat bővebben.

3. A Slope One algoritmus

Az 1. lejtőt a nem triviális elemalapú, osztályzatokon alapuló együttműködési szűrés legegyszerűbb formájának nevezték el. A hasonlósági mátrix kiszámításához figyelembe veszi mindazoktól az információktól, akik ugyanazt az elemet értékelték, és az ugyanazon felhasználó által minősített többi elemtől.

Egyszerű példánkban meg fogjuk jósolni a felhasználói rangsorolást az áruházban található termékekre.

Kezdjük a problémánk és a tartományunk egyszerű Java modelljével.

3.1. Java modell

Modellünkben két fő tárgy áll rendelkezésre: elemek és felhasználók. A Tétel osztály tartalmazza az elem nevét:

privát String itemName;

Másrészt a Felhasználó osztály tartalmazza a felhasználónevet:

privát String felhasználónév;

Végül van egy Beviteli adat osztály, amelyet az adatok inicializálására használunk. Tegyük fel, hogy öt különböző terméket hozunk létre az üzletben:

Lista elemek = Arrays.asList (új tétel ("Candy"), új tétel ("Ital"), új tétel ("Szóda"), új tétel ("Popcorn"), új tétel ("Snackek"));

Ezenkívül három olyan felhasználót hozunk létre, amelyek véletlenszerűen minősítették a fentiek egy részét a 0.0-1.0 skálán, ahol a 0 nem jelent érdeklődést, 0,5 valahogyan érdekelt és 1,0 azt jelenti, hogy teljesen érdekelt. Az adatok inicializálása eredményeként a Térkép felhasználói cikk-rangsorolási adatokkal:

Térkép adat;

3.2. Különbségek és gyakorisági mátrixok

A rendelkezésre álló adatok alapján kiszámoljuk az elemek közötti kapcsolatot, valamint az elemek előfordulásának számát. Minden felhasználónál ellenőrizzük a tételek értékelését:

for (HashMap felhasználó: data.values ​​()) {for (e bejegyzés: user.entrySet ()) {// ...}}

A következő lépésben ellenőrizzük, hogy az elem létezik-e a mátrixainkban. Ha ez először fordul elő, létrehozzuk az új bejegyzést a térképeken:

if (! diff.containsKey (e.getKey ())) {diff.put (e.getKey (), új HashMap ()); freq.put (e.getKey (), új HashMap ()); } 

Az első mátrix a felhasználói értékelések közötti különbségek kiszámítására szolgál. Értékei lehetnek pozitívak vagy negatívak (mivel az értékelések közötti különbség negatív lehet), és a Kettős. Másrészt a frekvenciákat úgy tároljuk Egész szám értékek.

A következő lépésben összehasonlítani fogjuk az összes elem értékelését:

for (e2 bejegyzés: user.entrySet ()) {int oldCount = 0; if (freq.get (e.getKey ()). tartalmazzaKey (e2.getKey ())) {oldCount = freq.get (e.getKey ()). get (e2.getKey ()). intValue (); } dupla oldDiff = 0.0; if (diff.get (e.getKey ()). tartalmazzaKey (e2.getKey ())) {oldDiff = diff.get (e.getKey ()). get (e2.getKey ()). doubleValue (); } kettős megfigyelt különbség = e.getValue () - e2.getValue (); freq.get (e.getKey ()). put (e2.getKey (), oldCount + 1); diff.get (e.getKey ()). put (e2.getKey (), oldDiff + novērottDiff); }

Ha valaki korábban értékelte az elemet, eggyel növeljük a frekvenciaszámot. Ezenkívül ellenőrizzük az elem értékelése közötti átlagos különbséget, és kiszámoljuk az újat megfigyeltDiff.

Kérjük, vegye figyelembe, hogy az összeg összegét feltettük oldDiff és megfigyeltDiff mint egy tétel új értékét.

Végül kiszámoljuk a mátrixokon belüli hasonlósági pontszámokat:

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

A fő logika az, hogy a számított elem besorolási különbségét el kell osztani az előfordulások számával. Ezt a lépést követően kinyomtathatjuk a végső különbségek mátrixunkat.

3.3. Jóslatok

A Slope One fő részeként meg fogjuk jósolni az összes hiányzó értékelést a meglévő adatok alapján. Ehhez össze kell hasonlítanunk a felhasználói tételek értékelését az előző lépésben számított különbségek mátrixával:

a (Belépés e: data.entrySet ()) {for (j elem: e.getValue (). keySet ()) {for (k elem: diff.keySet ()) {double predictedValue = diff.get (k) .get (j ) .doubleValue () + e.getValue (). get (j) .doubleValue (); double 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 ()); }} // ...}

Ezt követően elő kell készítenünk a „tiszta” előrejelzéseket az alábbi kód használatával:

HashMap tiszta = új HashMap (); a (j elem: uPred.keySet ()) {if (uFreq.get (j)> 0) {clean.put (j, uPred.get (j) .doubleValue () / uFreq.get (j) .intValue ( )); }} (j elem: InputData.items) {if (e.getValue (). tartalmazzaKey (j)) {clean.put (j, e.getValue (). get (j)); } else if (! clean.conkeyKey (j)) {clean.put (j, -1.0); }}

A nagyobb adathalmaznál figyelembe veendő trükk az, hogy csak azokat az elembejegyzéseket használja, amelyek nagy frekvenciaértékkel rendelkeznek (például> 1). Felhívjuk figyelmét, hogy ha az előrejelzés nem lehetséges, annak értéke -1 lesz.

Végül egy nagyon fontos megjegyzés. Ha az algoritmusunk megfelelően működött, meg kell kapnunk az előrejelzéseket azokra az elemekre, amelyeket a felhasználó nem minősített, de meg kell adnunk az általa értékelt elemek ismételt értékelését is. Ezeknek az ismételt minősítéseknek nem szabad megváltozniuk, különben ez azt jelenti, hogy az algoritmus megvalósításában van egy hiba.

3.4. Tippek

Kevés fő tényező befolyásolja a Slope One algoritmust. Íme néhány tipp, hogyan növelhető a pontosság és a feldolgozási idő:

  • fontolja meg a felhasználói elem értékelések megszerzését a DB oldalon nagy adathalmazok esetén
  • állítsa be az értékelések lekérésének időkeretét, mivel az emberek érdeklődése az idő múlásával megváltozhat - ez is csökkenti a bemeneti adatok feldolgozásához szükséges időt
  • ossza fel a nagy adatsorokat kisebbekre - nem kell minden nap kiszámítania az összes felhasználóra vonatkozó előrejelzéseket; ellenőrizheti, hogy a felhasználó interakcióba lépett-e az előre jelzett tétellel, majd felveheti / eltávolíthatja őt a következő nap feldolgozási sorából

4. Következtetés

Ebben az oktatóanyagban megismerhettük a Slope One algoritmust. Sőt, bevezettük az együttműködési szűrési problémát az elemajánló rendszerek számára.

A teljes végrehajtása az oktatóanyag a GitHub projektben található.