Systém odporúčaní na spoluprácu pri filtrovaní v Jave

1. Úvod

V tomto tutoriáli sa dozvieme všetko o algoritme Slope One v Jave.

Ukážeme si tiež príklad implementácie problému Collaborative Filtering (CF) - techniky strojového učenia používané odporúčacími systémami.

To sa dá použiť napríklad na predpovedanie záujmov používateľov pre konkrétne položky.

2. Spoločná filtrácia

Algoritmus Slope One je systém spolupráce založený na položkách založený na spolupráci. To znamená, že je úplne založený na hodnotení položiek podľa používateľa. Keď vypočítame podobnosť medzi objektmi, poznáme iba históriu hodnotení, nie samotný obsah. Táto podobnosť sa potom použije na predpovedanie potenciálnych hodnotení používateľov pre páry používateľov a položiek, ktoré sa v množine údajov nenachádzajú.

Obrázok nižšie zobrazuje kompletný proces získania a výpočtu hodnotenia pre konkrétneho používateľa:

Používatelia najskôr hodnotia rôzne položky v systéme. Ďalej algoritmus počíta podobnosti. Potom systém predpovedá hodnotenia užívateľských položiek, ktoré používateľ zatiaľ nehodnotil.

Viac podrobností o téme spoločného filtrovania nájdete v článku Wikipedia.

3. Algoritmus sklonu jednej

Slope One bol pomenovaný ako najjednoduchšia forma netriviálneho kolaboratívneho filtrovania na základe položiek na základe hodnotení. Na výpočet matice podobnosti berie do úvahy tak informácie od všetkých používateľov, ktorí hodnotili rovnakú položku, ako aj od ostatných položiek hodnotených rovnakým používateľom.

V našom jednoduchom príklade ideme predpovedať hodnotenie používateľov položiek v obchode.

Začnime s jednoduchým modelom Java pre náš problém a doménu.

3.1. Model Java

V našom modeli máme dva hlavné objekty - položky a používateľov. The Položka trieda obsahuje názov položky:

private String itemName;

Na druhej strane Používateľ trieda obsahuje užívateľské meno:

súkromné ​​reťazcové používateľské meno;

Nakoniec tu máme a Vstupné Data triedy, ktorá sa použije na inicializáciu údajov. Predpokladajme, že v obchode vytvoríme päť rôznych produktov:

Zoznam položiek = Arrays.asList (nová položka („Candy“), nová položka („nápoj“), nová položka („Soda“), nová položka („Popcorn“), nová položka („občerstvenie“));

Ďalej vytvoríme troch používateľov, ktorí náhodne ohodnotia niektoré z vyššie spomenutých pomocou škály od 0,0 do 1,0, kde 0 znamená žiadny záujem, 0,5 nejaký záujem a 1,0 znamená úplný záujem. V dôsledku inicializácie údajov dostaneme a Mapa s údajmi o poradí podľa položiek používateľa:

Mapa údaje;

3.2. Matice rozdielov a frekvencií

Na základe dostupných údajov vypočítame vzťahy medzi položkami, ako aj počet výskytov položiek. U každého používateľa kontrolujeme jeho hodnotenie položiek:

pre (HashMap user: data.values ​​()) {for (Entry e: user.entrySet ()) {// ...}}

V ďalšom kroku skontrolujeme, či položka existuje v našich maticiach. Ak ide o prvý výskyt, vytvoríme nový záznam v mapách:

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

Prvá matica sa používa na výpočet rozdielov medzi hodnotením používateľov. Jeho hodnoty môžu byť kladné alebo záporné (pretože rozdiel medzi hodnotením môže byť záporný) a sú uložené ako Dvojitý. Na druhej strane sú frekvencie uložené ako Celé číslo hodnoty.

V ďalšom kroku sa chystáme porovnať hodnotenie všetkých položiek:

pre (Záznam e2: user.entrySet ()) {int oldCount = 0; if (freq.get (e.getKey ()). containsKey (e2.getKey ())) {oldCount = freq.get (e.getKey ()). get (e2.getKey ()). intValue (); } dvojitý oldDiff = 0,0; if (diff.get (e.getKey ()). containsKey (e2.getKey ())) {oldDiff = diff.get (e.getKey ()). get (e2.getKey ()). doubleValue (); } dvojité pozorovanéDiff = e.getValue () - e2.getValue (); freq.get (e.getKey ()). put (e2.getKey (), oldCount + 1); diff.get (e.getKey ()). put (e2.getKey (), oldDiff + ObservDiff); }

Ak niekto položku predtým hodnotil, zvýšime počet frekvencií o jednu. Ďalej skontrolujeme priemerný rozdiel medzi hodnotením položky a vypočítame novú pozorovaný rozdiel.

Upozorňujeme, že sme vložili sumu oldDiff a pozorovaný rozdiel ako nová hodnota položky.

Nakoniec vypočítame skóre podobnosti vo vnútri matíc:

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); }}

Hlavnou logikou je vydeliť rozdiel medzi vypočítaným hodnotením položky a počtom jeho výskytov. Po tomto kroku môžeme vytlačiť našu výslednú maticu rozdielov.

3.3. Predpovede

Ako hlavnú časť svahu One budeme predpovedať všetky chýbajúce hodnotenia na základe existujúcich údajov. Aby sme to dosiahli, musíme porovnať hodnotenie užívateľských položiek s maticou rozdielov vypočítanou v predchádzajúcom kroku:

pre (Vstup e: data.entrySet ()) {for (Item j: e.getValue (). keySet ()) {for (Item k: diff.keySet ()) {double predictionValue = diff.get (k) .get (j ) .doubleValue () + e.getValue (). get (j) .doubleValue (); double finalValue = predictionValue * 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 ()); }} // ...}

Potom musíme pripraviť „čisté“ predpovede pomocou kódu uvedeného nižšie:

HashMap clean = nový HashMap (); for (Item j: uPred.keySet ()) {if (uFreq.get (j)> 0) {clean.put (j, uPred.get (j) .doubleValue () / uFreq.get (j) .intValue ( )); }} pre (Položka j: InputData.items) {if (e.getValue (). containsKey (j)) {clean.put (j, e.getValue (). get (j)); } else if (! clean.containsKey (j)) {clean.put (j, -1.0); }}

Trik, ktorý je potrebné zvážiť pri väčšej množine údajov, je použiť iba položky položiek, ktoré majú veľkú hodnotu frekvencie (napríklad> 1). Upozorňujeme, že ak predpoveď nie je možná, bude sa jej hodnota rovnať -1.

Na záver veľmi dôležitá poznámka. Ak náš algoritmus fungoval správne, mali by sme dostať predpovede pre položky, ktoré používateľ nehodnotil, ale aj opakované hodnotenia položiek, ktoré hodnotil. Tieto opakované hodnotenia by sa nemali meniť, inak to znamená, že vo vašej implementácii algoritmu je chyba.

3.4. Tipy

Existuje niekoľko hlavných faktorov, ktoré ovplyvňujú algoritmus svahu jeden. Tu je niekoľko rád, ako zvýšiť presnosť a čas spracovania:

  • zvážte získanie hodnotení užívateľských položiek na strane DB pre veľké súbory údajov
  • nastaviť časový rámec pre načítanie hodnotení, pretože záujmy ľudí sa môžu časom meniť - skráti to tiež čas potrebný na spracovanie vstupných údajov
  • rozdeliť veľké súbory údajov na menšie - nemusíte každý deň počítať predpovede pre všetkých používateľov; môžete skontrolovať, či používateľ interagoval s predpovedanou položkou, a potom ho pridať / odobrať zo frontu na ďalší deň

4. Záver

V tomto tutoriáli sme sa mohli dozvedieť viac o algoritme Slope One. Ďalej sme predstavili problém filtrovania spolupráce pre systémy odporúčania položiek.

The úplná implementácia tohto tutoriálu nájdete v projekte GitHub.


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