62
SVEUČILIŠTE U ZAGREBU FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA DIPLOMSKI RAD br. 1022 PROGRAMSKI MODUL ZA PREPORUČIVANJE SADRŽAJA NA WEB-PORTALIMA Martin Kurtoić Zagreb, srpanj 2016

WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

SVEUČILIŠTE U ZAGREBU

FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA

DIPLOMSKI RAD br. 1022

PROGRAMSKI MODUL ZA

PREPORUČIVANJE SADRŽAJA NA

WEB-PORTALIMA

Martin Kurtoić

Zagreb, srpanj 2016

Page 2: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka
Page 3: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka
Page 4: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

Sadržaj

1 Uvod ........................................................................................................................................... 1

2 Osnovne tehnike preporučivanja sadržaja ................................................................................. 2

2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) ............................................... 2

2.2 Preporuke prema suradnji korisnika (engl. Collaborative Filtering) .................................. 4

3 Java knjižnice korištene prilikom razvoja programskog modula ................................................ 7

3.1 Programska knjižnica Apache Lucene ................................................................................. 7

3.2 Programska knjižnica Apache Mahout ............................................................................. 11

4 Implementirane tehnike određivanja sličnosti ........................................................................ 13

4.1 Određivanje sličnosti korisnika (engl. User-based similarity) .......................................... 13

4.2 Određivanje sličnosti članaka prema sadržaju pomoću knjižnice Apache Lucene (engl.

Content-based) ............................................................................................................................. 15

5 Arhitektura i implementacija programskog modula ............................................................... 18

5.1 Opis klasa i metoda razvijenog programskog modula ..................................................... 19

5.1.1 Klase NewsItem i Text ........................................................................................... 19

5.1.2 Klasa Indexer ......................................................................................................... 20

5.1.3 Klasa MatrixGeneratorWithTopDocs................................................................ 24

5.1.4 Klasa ItemSimilarityFromTopDocsMatrix ..................................................... 25

5.1.5 Klasa ItemRecommenderFromTopDocsMatrix .................................................. 27

5.1.6 Klasa ItemRecommenderFromDataModelTopDocs ............................................ 28

5.1.7 Klasa DataModelGenerator ................................................................................. 29

6 Slučajevi uporabe (engl. use cases) i metode sučelja .............................................................. 31

6.1 Inicijalizacija sustava i dodavanje novog članka u sustav ................................................. 31

6.2 Brisanje postojećeg članka iz sustava............................................................................... 32

6.3 Pridjeljivanje ocjene članku .............................................................................................. 33

6.4 Generiranje preporuka ..................................................................................................... 33

7 Zaključak ................................................................................................................................... 35

8 Literatura .................................................................................................................................. 36

9 Sažetak ..................................................................................................................................... 37

10 Dodatak: programski kod ..................................................................................................... 38

Page 5: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

1

1 Uvod

Preporučiteljski sustav (engl. recommendation systems) vlasniku određenog

sadržaja omogućuje stvaranje dodatne vrijednosti tog sadržaja. Način na koji

preporučiteljski sustav stvara dodatnu vrijednost sadržaja jest da različitim

metodama usporedbi kreira različite korelacije sličnosti između sadržaja, ali i

korisnika koji na očigled nisu povezani. Takav pristup omogućuje vlasniku

sadržaja da korisniku za kojeg je zabilježeno da je zainteresiran za određen tip

sadržaja, prilikom posjete portalu preporučuje sadržaj sličan onome za koji je

zabilježen korisnikov interes, ali i interes njemu sličnih korisnika. Svaki

preporučiteljski sustav djeluje na temelju pretpostavke da postoji korisnik

pojedinac, izdvojen iz cjelokupne baze korisnika sustava, i podskup sadržaja,

izdvojen iz cjelokupnog skupa sadržaja sustava, koji može biti preporučen tom

korisniku.

Unutar svakog preporučiteljskog sustava postoji skup funkcija čije se

međudjelovanje svodi na računanje faktora korisnosti preporučivanja određenog

sadržaja određenom korisniku portala. Takve funkcije najčešće predstavljaju

Kartezijev produkt skupa korisnika sa skupom sadržaja gdje je svaki par (korisnik,

sadržaj) prikazan kao pozitivan cijeli ili realni broj (R0) u unaprijed određenom

rasponu.

(korisnik, sadržaj) R0

Danas gotovo svaki vlasnik sadržaja koji je ponuđen korisnicima preko Interneta,

teži što boljoj realizaciji preporučivanja sadržaja kao dodatne usluge web-portala.

Preporučivanje sadržaja kao dodatna usluga prvenstveno je namijenjeno web-

portalima s vijestima, portalima za prodaju, distribuciju videa i slično.

Najvažnije funkcije preporučiteljskog sustava (na primjeru portala s vijestima) :

otkriti korisniku vijesti koje ga zanimaju, a koje sam ne bi lako pronašao,

navoditi korisnika da otvori i pročita što više vijesti te se tako što duže

zadrži na portalu,

Page 6: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

2

donositi vlasniku što više dobiti koja je posljedica otvaranja što više članaka

uz koje se nalaze razne reklame koji se mogu naplatiti po otvaranju članka

od strane korisnika.

Osnovne karakteristike preporučiteljskog sustava:

personaliziranost – preporuke moraju biti što je bolje moguće prilagođene

korisnikovom profilu,

raznolikost – korisniku moraju biti preporučene sve sfere njegovih interesa.

U preporučiteljskim sustavima postoje dva osnovna pristupa stvaranju preporuka,

a to su preporuke prema sličnosti sadržaja (engl. Content-based recommendation)

i preporuke prema suradnji korisnika (engl. Collaborative Filtering

recommendation). Kod preporuka prema sličnosti sadržaja korisniku se nude

članci slični onima koje korisnik upravo ima otvorene i čita ih jer se za kreiranje

preporuka, kao što sam naziv govori, isključivo koristi sličnost sadržaja. Kod

preporuka prema suradnji, koristi se pak potpuno drugačiji pristup te se korisničke

preporuke kreiraju tako da se u datoteci u kojoj su zabilježene korisničke akcije

pronalaze slični korisnici te se trenutnom korisniku nude oni članci koje su ranije

čitali njemu slični korisnici.

Vrlo je često slučaj da se u preporučiteljskom sustavu kombiniraju dvije navedene

vrste kreiranja preporuka, a takvi sustavi nose naziv hibridni preporučiteljski

sustavi.

2 Osnovne tehnike preporučivanja sadržaja

2.1 Preporuke prema sličnosti sadržaja (engl. Content-based)

Najosnovniji pristup pri stvaranju preporuka u preporučiteljskim sustavima su

preporuke prema sličnosti sadržaja (engl. Content-based). Kao što je u uvodu već

spomenuto, navedena metoda kreira preporuke tako da se korisniku nude članci

koji su prema sadržaju ili određenim opisnim podacima slični onima koje sam

korisnik trenutno čita, odnosno ima otvorene. Opisni podaci svakog članka mogu,

Page 7: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

3

ali i ne moraju biti niz unaprijed definiranih atributa kojima se prilikom unosa

članka na portal definiraju vrijednosti. Skup vrijednosti koje mogu biti pridružene

pojedinom atributu također se može unaprijed definirati, iako ni to nije nužno. Na

primjer, svaki članak uz sebe može imati podatke o državi ili gradu za koji je

vezan, kojoj kategoriji (npr. vijest, sport, crna kronika) pripada i slično.

Prednosti preporuka prema sličnosti sadržaja:

nema potrebe za informacijama o drugim korisnicima,

dobre preporuke korisnicima jedinstvenog profila,

dobro preporučuje nove i slabije popularne članke,

korisniku je lako objasniti zašto je članak preporučen izlistavanjem atributa

koji su ključni za stvaranje preporuke.

Nedostaci:

dobro samo za usluge koje mogu biti prikazane zadanim skupom atributa,

tehnike pretraživanja usluga ne mogu uzeti u obzir multimedijske

informacije te ostale aspekte koji utječu na ocjenjivanje poput vremena

preuzimanja sadržaja i slično,

teško je iskoristiti ocjenu kvalitete koju su dali drugi korisnici.

Može se primijetiti da nedostaci kod preporuka na temelju sličnosti sadržaja ne bi

značajno trebali dolaziti do izražaja u slučaju web-portala s različitim člancima te bi

bilo legitimno koristiti i samo takav način preporučivanja.

Kod preporuka na temelju sličnosti sadržaja funkcija korisnosti u(s1,s2) definirana

je kao:

u(s1,s2) = podudarnost(sadržaj(s1), sadržaj(s2))

gdje su i sadržaj s1 prvog dokumenta i sadržaj s2 drugog dokumenta prikazani kao

TF-IDF (engl. Term Frequency-Inverse Document Frequency) vektori težine

ključnih riječi. TF-IDF jest statistički pristup čija je funkcija prikazati koliku važnost

ima određena riječ u svakom pojedinom dokumentu iz skupa dokumenata.

Page 8: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

4

TF (engl. Term Frequency) je broj pojavljivanja određenog pojma u dokumentu koji

se u daljnji račun može uzeti kao original ili normaliziran na jedan od više načina

koji postoje za normalizaciju broja TF. Primjer normalizacije jest binarni prikaz gdje

nula označava da pojam uopće ne postoji u dokumentu, a jedan da se nalazi

jedan ili više puta.

𝑤𝑡,𝑑 = log(1 + 𝑡𝑓𝑡,𝑑) ∗ 𝑖𝑑𝑓𝑡

Gdje je tft,d broj pojavljivanja pojma u promatranom dokumentu, a idft je izračun

frekvencije dokumenata u kolekciji u kojima se pojavljuje promatrani pojam.

U slučaju preporuka prema sličnosti sadržaja ti su dokumenti najčešće indeksirani

tekstualni zapisi ključnih riječi ili svih riječi koje se nalaze u sadržaju svih članaka.

Funkcija korisnosti se najčešće implementira pomoću neke od heurističkih metoda

poput, na primjer, kosinusne sličnosti te se u tom slučaju računa na sljedeći način:

𝑢(𝑐, 𝑠) = cos(𝑤𝑐 , 𝑤𝑠) =𝑤𝑐 × 𝑤𝑠

(||𝑤𝑐|| || 𝑤𝑠||)= (∑ 𝑤𝑖𝑐𝑤𝑖𝑠) ÷ (√∑ 𝑤𝑖𝑐

2

𝐾

𝑖=1

𝐾

𝑖=1

∗ √∑ 𝑤𝑖𝑠2

𝐾

𝑖=1

)

Gdje su wc i ws vektori dva članka koje želimo usporediti.

2.2 Preporuke prema suradnji korisnika (engl. Collaborative Filtering)

Preporuke prema suradnji korisnika kreiraju se tako da se skupljaju podaci o

ocjenama koje su ostali, trenutno aktivnom korisniku što sličniji korisnici, pridijelili

od strane trenutno aktivnog korisnika nepročitanim člancima.

Preporučiteljski sustavi koji preporuke kreiraju prema suradnji korisnika za

kreiranje preporuka koriste dio ili cijelu bazu povezanosti korisnika i članaka.

Prema bazi povezanosti korisnika i članaka se za svaka dva korisnika može

odrediti točan koeficijent sličnosti interesa te se prema tom koeficijentu kasnije

kreiraju i same preporuke.

Računanje sličnosti između članaka ili korisnika u preporučiteljskim sustavim s

preporuka prema suradnji korisnika je ključan i kritičan korak.

Page 9: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

5

Postoje dva osnovna pristupa kod kreiranja preporuka prema suradnji korisnika, a

to su preporuke zasnovane na sličnosti članaka (engl. item-based

recommendations) i preporuke zasnovane na sličnosti korisnika (engl. user-based

recommendations).

Osnovna ideja kod kreiranja preporuka zasnovanih na sličnosti članaka jest prvo u

bazi korisničke suradnje pronaći korisnike koji imaju ocijenjena oba članka koja se

uspoređuju i nakon toga odrediti funkciju koja će se koristiti za izračun koeficijenta

sličnosti, wi,j, dvaju uspoređivanih članaka koje su korisnici čitali i ocijenili. Nakon

što se odredi sličnost članaka, u sljedećem se koraku kreiranja preporuka

zasnovanih na sličnosti članaka može upotrijebiti proračun prosjeka težina (engl.

simple weighted average) kako bi se odredila korisnost preporučivanja određenog

članka (k) određenom korisniku (u):

𝑃𝑢,𝑖 =∑ 𝑟𝑢,𝑛𝑤𝑘,𝑛𝑛∈𝑁

∑ |𝑤𝑘,𝑛|𝑛∈𝑁

gdje se sumira po svim ostalim ocijenjenim člancima n ∈ N korisnika u, a wk,n je

sličnost između članaka k i n. ru,n je ocjena članka n koju je pridijelio korisnik u.

Kod kreiranja preporuka zasnovanih na sličnosti korisnika potrebno je izračunati

sličnost između dva korisnika, wu,v, koji su oboje ocijenili iste članke.

Kako je danas uglavnom potrebno kreirati više od jedne preporuke pomoću

preporučiteljskog sustava, u nastavku će biti razmotreni načini kreiranja preporuka

top-N zasnovanih na sličnosti korisnika, ali i preporuka top-N zasnovanih na

sličnosti članaka koji rješava problem skalabilnosti koji se pojavljuje kod kreiranja

preporuka top-N zasnovanih na sličnosti korisnika.

Prilikom kreiranja preporuka top-N zasnovanih na sličnosti korisnika prvo je

potrebno pronaći k najsličnijih korisnika (engl. nearest neighbours) trenutno

aktivnom korisniku koristeći Pearsonovu korelaciju (engl. Pearson correlation) ili

model vektor-prostor (engl. vector-space model) u kojem je svaki korisnik prikazan

kao vektor u m-dimenzionalnom prostoru članaka i sličnost između trenutno

aktivnog i ostalih korisnika se računa kao sličnost vektora. Nakon što se odredi k

najsličnijih korisnika, njihovi m-dimenzionalni vektori članaka se objedinjuju u

matricu kako bi se odredio skup članaka, C, korištenih od strane cijele grupe, svaki

Page 10: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

6

s pojedinačnom učestalošću. Kada je poznat skup članaka, C, tada preporučitelj

zasnovan na sličnosti korisnika može preporučiti top-N najučestaliji članaka koji se

nalaze u matrici, a da ih aktivni korisnik još nije koristio. Kreiranje preporuka

zasnovanih na sličnosti korisnika ima ograničenja koja se odnose na skalabilnost i

performanse u pružanju usluga u stvarnom vremenu.

Kako bi se riješio problem skalabilnosti koji se javlja kod preporuka zasnovanih na

temelju sličnosti korisnika, razvijen je pristup kreiranja preporuka na temelju

sličnosti članaka. Kod kreiranja preporuka na temelju sličnosti članaka prvo je

potrebno pronaći k najsličnijih članaka za svaki članak prema unaprijed određenim

kriterijima sličnosti. Nakon toga je potrebno kreirati skup, C, članaka za

potencijalno preporučivanje određujući uniju k najsličnijih članaka i uklanjanjem

svakog članka iz skupa, U, koje je aktivni korisnik već čitao. Tada je potrebno

izračunati koeficijent sličnosti između svakog članka iz skupa C sa svakim

člankom iz skupa U. Konačni skup članaka u C, sortiran po sličnosti jest preporuka

top-N temeljna na sličnosti članaka. Slikoviti prikaz korištenja ovakvog pristupa u

kreiranju preporuka može biti preporučivanje prilikom kupovine kino karata. Svaki

novi film se u tom slučaju uspoređuje sa svim filmovima za koje je korisnik do sada

kupovao karte te mu se na temelju parametara usporedbe dodijeli određeni

koeficijent sličnosti, nakon čega se kreira lista novih filmova tako da se oni s

najpovoljnijim koeficijentom sličnosti nalaze najviše na listi, odnosno lista se sortira

padajuće.

Page 11: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

7

3 Java knjižnice korištene prilikom razvoja programskog

modula

U programskom modulu kao podloga koriste se programske knjižnice (engl.

library) Apache Lucene i Apace Mahout implementirane u programskom jeziku

Java. Razlog zbog kojeg se koriste baš navedene knjižnice jest da je

povezivanjem tih dviju knjižnica u jedan programski modul moguće vrlo efikasno

kreirati preporuke na web-portalima. Funkcije pojedine knjižnice implementirane u

razvijenom programskom modulu bit će detaljnije razmotrene u nastavku.

3.1 Programska knjižnica Apache Lucene

Apache Lucene je knjižnica za dohvaćanje informacija (engl. information retrieval),

a glavne su joj karakteristike visoke performanse i skalabilnost. Pri razvoju

programskog modula za preporučivanje sadržaja na web-portalima knjižnica

Apache Lucene se koristi za indeksiranje (engl. indexing) članaka s web-portala.

Indeksiranje je proces koji je vrlo preporučljivo provesti prije bilo kakvog daljnjeg

manipuliranja člancima jer se tako omogućuje brže manipuliranje člancima. Indeks

(engl. index) omogućuje brži pristup informacijama iz članaka od slijednog čitanja.

Na taj je način moguće znatno brže postaviti preduvjete za uspoređivanje sličnosti

članaka. Informacije o sličnosti članaka su od velike važnosti kasnije u procesu

preporučivanja kako bi prilikom kreiranja krajnjih preporuka bili u mogućnosti

uključiti faktor koji se odnosi isključivo na međusobnu sličnost članaka.

Apache Lucene može indeksirati i omogućiti pretraživanje bilo kakvih podataka

koje je moguće izvesti iz teksta članaka koji su indeksirani Apache Lucenom.

Apache Lucene također može kreirati indeks nad kolekcijom članaka neovisno o

samim člancima ili njihovom formatu dok god se članci mogu prikazati kao tekst. S

obzirom na tu mogućnost, moguće je indeksirati dokumente koji su pohranjeni

lokalno, jednostavne tekstualne datoteke, Microsoft Word, XML, HTML ili PDF

dokumente i slične.

Page 12: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

8

U nastavku će Slika 1 više puta biti korištena kao referenca prilikom opisivanja

funkcije pojedinog modula knjižnice Apache Lucene kako bi kasnije prilikom

opisivanja razvijenog programskog modula bila jasna uloga knjižnice Apache

Lucene u ostvarivanju funkcionalnosti programskog modula.

Neobrađeni

sadržaj

Učitavanje

dokumenta

Indeks

Kreiranje

dokumenta

Analiziranje

dokumenta

Indeksiranje

dokumenta

Izvršavanje

upita

Kreiranje

upita

Povrat

rezultata

Korisničko sučelje

za pretraživanje

Korisnik

Slika 1 Arhitektura knjižnice Apache Lucene

Page 13: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

9

Prvi korak prilikom indeksiranja sadržaja klasama knjižnice Apache Lucene na

Slika 1 se nalazi pri dnu slike, odmah iznad „Neobrađenog sadržaja“. Radi se o

učitavanju neobrađenog sadržaja u sustav. Kako bi se omogućilo što efikasnije

učitavanje neobrađenog sadržaja u sustav po mogućnosti je potrebno organizirati

dokumente u neki od strukturiranih formata, poput XML-a. Format XML omogućuje

brže i efikasnije parsiranje dokumenata te samim time od samog početka

povećava efikasnost cjelokupnog sustava. Što je više podataka potrebno učitati u

sustav to efikasnost ove komponente više dolazi do izražaja. Još jedna važna

činjenica jest da ova komponenta, kao važan dio cjelokupnog sustava, mora biti

građena tako da se pomoću nje može efikasno učitati novi sadržaj za vrijeme rada

sustava.

Kada prethodno opisana komponenta sustava izvrši učitavanje neobrađenog

sadržaja u sustav, potrebno je parsirati neobrađeni sadržaj. Učitavanjem

neobrađenog sadržaja u sustav se često učita i velika količina metapodataka od

kojih prilikom preporučivanja nema koristi. Kako bismo izbjegli „smeće“ unutar

sustava koje čak i šteti prilikom kreiranja preporuka potrebno je obratiti pažnju na

dizajn parsera neobrađenog sadržaja. Prilikom dizajniranja parsera neobrađenog

sadržaja potrebno je prepoznati podatke koji će biti korisni prilikom kreiranja

preporuka te je takve podatke potrebno pohraniti u dokumente od kojih se gradi

indeks. Metapodatke za koje se zaključi da nisu od koristi nije potrebno

pohranjivati u sustav kako bi se sačuvala efikasnost sustava. Dokumenti koji se

pohranjuju u sustav kako bi bili korišteni unutar metoda (engl. method) knjižnice

Apache Lucene sastoje se od polja i vrijednosti pridruženih tim poljima. Ako se

sadržaj u sustav učitava u formatu XML, tada imena polja mogu biti oznake XML,

a vrijednosti polja vrijednosti koje se nalaze unutar oznaka. U postupku parsiranja i

kreiranja dokumenata je važno da se, koliko god se može, ima na umu da neka

riječ u polju s puno riječi, odnosno velikim sadržajem, ima puno manju važnost od

riječi unutar polja s malo sadržaja. Tako zbog velike količine sadržaja u pojedinim

poljima neke riječi neopravdano mogu izgubiti na važnosti.

Nakon što su dokumenti kreirani, isti nisu odmah i indeksirani. Kao što se na Slika

1 može primijetiti, indeksiranje dokumenata je posljednja komponenta u nizu

prilikom korištenja knjižnice Apache Lucene. Sljedeći korak jest analiziranje

dokumenata. Analiziranje dokumenata izvršava se kako bi sve bilo spremno za

Page 14: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

10

kreiranje indeksa nad dokumentima. Naime, niti jedan sustav za indeksiranje

dokumenata, pa tako ni knjižnica Apache Lucene, ne indeksira tekst direktno iz

dokumenata već ga prije indeksiranja analizira. Analiziranje teksta jest postupak

gdje se tekst lomi na svoje gradivne jedinice, odnosno na riječi jezika u kojem je

pisan. Korištenje knjižnice Apache Lucene ovdje jako dolazi do izražaja, budući da

se kroz Apache Lucene korisniku nudi niz ugrađenih analizatora teksta, gdje je na

korisniku odluka koji analizator želi koristiti ili mogućnost implementacije vlastitog

analizatora u svoj sustav. Nakon što ih se provede kroz analizator, dokumenti su

spremni za kreiranje indeksa.

Na posljetku je od učitanih podataka i kreiranih dokumenta potrebno izgraditi

indeks. U ovom koraku unutar cjelokupnog sustava najviše do izražaja dolaze

prednosti korištenja knjižnice Apache Lucene jer omogućuje efikasno i brzo

kreiranje indeksa nad analiziranim dokumentima za sve sustave kojima je indeks

potreban, a indeksiranje nije primarna funkcionalnost. Unutar programskog

modula za preporučivanje sadržaja na web-portalima potrebno je imati kreirani

indeks nad svim člancima koji se nalaze na web-portalu. Kreirani indeks

omogućuje pretraživanje svih članaka prema različitim kriterijima te kreiranje svih

preduvjeta koji su potrebni kako bi se ostvario kvalitetan programski modul za

preporučivanje sadržaja.

Programski modul za preporučivanje sadržaja na web-portalima nije klasična

aplikacija za pretraživanje sadržaja, gdje korisnik upiše pojam i očekuje da mu

aplikacija vrati određenu količinu sadržaja koji se nalazi unutar određenog sustava

i koji je na neki način povezan s pojmom koji je korisnik unio u aplikaciju. Nakon

što je unutar sustava kreiran indeks svih dokumenata, programski modul se

ponaša kao „Korisnik“ na Slika 1 te koristi metode knjižnice Apache Lucene

pomoću kojih gradi upite (engl. query) nad kreiranim indeksom, a rezultate upita

koristi za daljnje postupke unutar sustava koji će kasnije biti detaljnije objašnjeni.

Tako je u slučaju programskog modula za preporučivanje sadržaja na web-

portalima „Korisnik“ knjižnice Apache Lucene sam modul unutar kojega je

implementirana i funkcionalnost koju pruža knjižnica Apache Lucene, odnosno

Lucene je samo jedan korak u modulu prilikom kreiranja preporuka koje se

poslužuju vanjskom sustavu, odnosno krajnjem korisniku.

Page 15: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

11

3.2 Programska knjižnica Apache Mahout

Apache Mahout je knjižnica otvorenog koda za razvoj sustava strojnog učenja.

Algoritmi koji su implementirani unutar biblioteke spadaju u široko područje

strojnog učenja i inteligencije prikupljanja podataka. Kako unutar navedenih

područja postoji velika širina upotrebe u rješavanju različitih problema važno je

napomenuti da se algoritmi implementirani u knjižnici Apache Mahout

upotrebljavaju ponajprije za razvoj preporučiteljskih sustava, grupiranja

(klasteriranja) te klasificiranja podataka. Apache Mahout također ima i podršku za

skalabilnost i ako je potrebno koristiti algoritme strojnog učenja na velikoj količini

podataka, puno većoj od količine podataka koju može obraditi jedno računalo,

Apache Mahout bi mogao biti dobar izbor. Skalabilno strojno učenje Apache

Mahoutom koristi projekt Apache Hadoop za računanje ravnomjerne distribucije

posla poslužiteljima. Korištenje Apache Hadoopa uključuje i korištenje radnog

okvira MapReduce za računanje distribuiranog izvršavanja zadataka na

poslužiteljima, koji je postao popularan kada ga je počeo koristiti Google, uz

Amazon najveći svjetski razvijatelj algoritama strojnog učenja. MapReduce je

programska paradigma koja rješava probleme kod kojih je ulaz u sustav par ključ-

vrijednost. Funkcija Map pretvara parove ključ-vrijednost u druge, posredničke,

parove ključ-vrijednost, dok funkcija Reduce spaja sve vrijednosti za svaki

posrednički ključ kako bi proizvela izlaz. Kako je paradigma MapReduce vrlo

složena i u ovom kontekstu se spominje samo kao prednost knjižnice Apache

Mahout u slučaju da količina podataka prekorači količinu obradivu na jednom

računalu u prihvatljivom vremenu, ovdje je naveden samo osnovni princip

funkcioniranja paradigme i neće se ulaziti u detalje.

Page 16: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

12

Slika 2 Arhitektura sustava koji koristi knjižnicu Apache Mahout

Kako bi se dobile što je moguće bolje preporuke, preporučiteljske sustave je

potrebno promatrati kao komponente kreiranja modela preporučivanja, a upravo to

omogućuje Mahoutova komponenta za sličnost sadržaja koja može kreirati

preporuke na načelu „drugi korisnici su također čitali članak poput ovog“ uz pomoć

kojih je u suradnji sa skalabilnim alatom za pretraživanje poput Apache Lucena

moguće kreirati personalizirane preporuke za svakog pojedinog korisnika.

Kod implementiranja Mahouta unutar nekog sustava potrebno je prikupljati

korisničke akcije u bazu podataka u formatu poznatom Mahoutu. Najjednostavniji

način bilježenja korisničkih akcija u formatu poznatom Mahoutu jest bilježenje

korisničkih akcija u datoteku CSV u formatu ''id-korisnika, id-članka, mjera-

zadovoljstva-korisnika-člankom''. U bazi podataka potrebno je čuvati posljednjih n

korisničkih akcija koje čine jedan dio upita prilikom kreiranja nove preporuke. Kada

programski modul unutar kojeg je implementirana knjižnica Apache Mahout ima

potrebu kreirati novu preporuku za pojedinog korisnika, uzima zadnje zapise iz

baze podataka i šalje upit sustavu za pretraživanje s preuzetom poviješću

korisničkih akcija. Sustav pretraživanja vraća poredanu listu id-članaka i to su

tražene preporuke. Dobivenu listu moguće je dodatno uređivati tako da je neke

stavke moguće ukloniti iz liste i slično.

Page 17: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

13

4 Implementirane tehnike određivanja sličnosti

Kako bi programski modul imao što bolju efikasnost te kako bi njime osigurali da u

svakom trenutku, svaki korisnik koji otvori određeni članak na web-portalu dobije

na ponudu određeni broj preporuka, potrebno je unutar modula implementirati više

načina određivanja sličnosti. Kvaliteta preporuke poslužene korisniku jednako ovisi

o načinima na koje se unutar preporučiteljskog sustava određuje sličnost kao i o

podacima dostupnim o korisniku koji je otvorio članak te o samom članku koji je

korisnik otvorio. Unutar razvijenog programskog modula implementirana su dva

osnovna načina određivanja sličnosti koja su opisana u nastavku, koje je unutar

modula moguće koristiti odvojeno te kombinirano kao hibridni način kreiranja

preporuka.

4.1 Određivanje sličnosti korisnika (engl. User-based similarity)

Određivanje sličnosti korisnika jest način određivanja sličnosti koji je unutar

razvijenog programskog modula implementiran uz pomoć metoda knjižnice

Apache Mahout, a ovaj je način razmotren prvi budući da taj način određivanja

sličnosti uopće ne uzima u obzir sličnost sadržaja članaka. Naime, iz podataka

skupljenih unutar datoteke u kojoj se bilježe korisničke akcije, pomoću metode

PearsonCorrelationSimilarity knjižnice Apache Mahout, računa se

Pearsonov korelacijski koeficijent (engl. Pearson correlation coefficient) između

akcija svakih dvaju korisnika te se kreira „susjedstvo“ (engl. neighbourhood) među

korisnicima. „Susjedstvo“ se kreira tako da se svakom paru korisnika pridruži

koeficijent sličnosti iz intervala [-1, 1] gdje -1 označava potpunu različitost dvaju

korisnika, a 1 potpunu podudarnost dvaju korisnika, dok je 0 neutralna, odnosno 0

govori da korisnici imaju zabilježene interaktivnosti, odnosno ocjene, za različite

članke i da nije moguće utvrditi njihovu sličnost. Kao što čitatelj može pretpostaviti,

u stvarnom sustavu je izrazito teško dobiti kako -1, tako i 1 kao koeficijent sličnosti,

a vrlo često se taj koeficijent kreće oko vrijednosti 0. Tako je koeficijent sličnosti

već u iznosu od npr. 0.3 između dva korisnika vrlo korisna informacije jer postoji

Page 18: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

14

vrlo velika mogućnost da bi korisnicima međusobno mogli biti interesantni članci

koje je onaj drugi čitao i eventualno dobro ocijenio.

Metoda knjižnice Apache Mahout računa Pearsonov koeficijent sličnosti sljedećom

formulom:

𝑟 =∑ 𝑋𝑖𝑖=𝑗 𝑌𝑗

√∑ 𝑋𝑖2

𝑖 ∗ ∑ 𝑌𝑗2

𝑗

Gdje su X i Y vektori korisničkih interakcija zabilježenih unutar datoteke CSV koja

je dio sustava. U brojniku navedene formule nalazi se suma umnožaka svih ocjena

za članke koji su u danom trenutku izračuna sličnosti ocijenjeni od strane jednog i

drugog korisnika koje promatramo. U nazivniku se pak nalaze sume kvadrata svih

ocjena jednog i drugog korisnika, koje su spojene u produkt, iz kojeg je na

posljetku izračunan kvadratni korijen.

Važno je napomenuti da podatke koje metoda dobije, prvo pretvori tako da im

srednja vrijednost iznosi 0. Drugim riječima, ako su unutar datoteke s korisničkim

interakcijama zabilježene ocjene za pojedine članke u rasponu [1, 5], metoda prvo

pretvori te podatke u raspon [-2.5, 2.5]. Navedeno centriranje podataka je nužno

kako metoda ne bi ovisila o rasponu ocjena koje se bilježe unutar datoteke s

korisničkim interakcijama, već koji god raspon bio, metoda ga uvijek pretvori u

raspon kojem je srednja vrijednost 0. S obzirom na navedenu pretvorbu podataka

vrijednost koju je gornjom formulom moguće dobiti nalazi se upravo u ranije

navedenom intervalu [-1, 1] i predstavlja Pearsonov koeficijent sličnosti korisnika.

Page 19: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

15

4.2 Određivanje sličnosti članaka prema sadržaju pomoću knjižnice

Apache Lucene (engl. Content-based)

Kao što je ranije navedeno, osim što pruža mogućnost indeksiranja sadržaja,

knjižnica Apache Lucene također pruža mogućnost pretraživanja indeksiranog

sadržaja prema traženom upitu unesenom iz korisničkog sučelja, kao što se i

može vidjeti iz arhitekture na Slika 1. U slučaju razvijenog programskog modula ne

postoji korisničko sučelje za pretraživanje indeksa, već pretraživanje izvršava sam

programski modul prilikom kreiranja matrice sličnosti sadržaja. Iako će

funkcionalnosti implementirane unutar pojedinih metoda biti detaljno opisane

kasnije u radu, kako je generiranje matrice sličnosti ključ ovog poglavlja, opis

metode unutar koje se generiranje izvršava slijedi.

Generiranje matrice sličnosti izvršava se unutar metode initialGenerator (int

num) klase (engl. class) MatrixGeneratorWithTopDocs. Unutar metode

initalGenerator vrši se prolazak kroz sve članke koji se nalaze u indeksu te se

za svaki članak dohvaća num najsličnijih članka, gdje se za traženi upit prvo uzima

tekst indeksiranog članka. Ako zbog složenosti upita unutar kojeg se nalazi cijeli

tekst indeks ne može pronaći niti jedan članak sličan članku za koji se pretraga

vrši, slijedi novo pretraživanje gdje se kao upit uzima naslov članka. Kako je

naslov članka puno jednostavniji upit od cjelokupnog teksta, s gotovo potpunom

sigurnošću se može tvrditi da će unutar indeksa zadovoljavajuće veličine postajati

barem jedan prema naslovu sličan članak članku za kojeg izvršavamo pretragu.

Na temelju pretrage indeksa dobivamo num najsličnijih dokumenata dokumentu za

kojeg smo izvršili upit. Vrijednosti pozicija iz indeksa na kojima se nalaze

pronađeni najsličniji članci se pohranjuju unutar retka članka za koji se izvršila

pretraga u matricu sličnih indeksa, a koeficijenti sličnosti se pohranjuju unutar istog

retka u matricu koeficijenata sličnosti. Na taj se način generiraju dvije matrice,

matrica koja sadrži pozicije iz indeksa za num najsličnijih članaka svakom članku i

matrica koja sadrži koeficijente sličnosti num najsličnijih članaka za svaki članak u

indeksu.

Page 20: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

16

Nakon što je kreiran upit nad indeksom s tekstom ili naslovom određenog članka

za kojeg se u danom trenutku dohvaća num najsličnijih članaka, upit se i izvršava,

a rezultat izvršavanja upita pohranjuje se u instancu klase TopDocs programske

knjižnice Apache Lucene. Klasa TopDocs omogućava efikasno manipuliranje i

dohvaćanje pojedinih članaka iz cijele skupine članaka koji su vraćeni kao rezultat.

Rezultati su unutar instance klase TopDocs poredani padajuće prema

relevantnosti, odnosno reference na najsličnije članke nalaze se na početnim

pozicijama polja TopDocs. Klasa TopDocs ima implementirane tri metode koje

omogućuju dohvaćanje rezultata pretraživanja. Metoda totalHits, kao što i samo

ime metode kaže, vraća ukupan broj članaka koji su pronađeni kao slični traženom

članku. Metoda scoreDocs vraća polje svih članaka koji su pronađeni kao slični

članku za kojeg je izvršena pretraga, a članak je prema metodi scoreDocs sličan

ako mu je sličnost s upitom prema zadanim kriterijima veća od nule. Svaka

instanca polja scoreDocs sadrži dvije vrijednosti, score koja je tipa float i sadrži

koeficijent sličnosti članaka te doc koja je tipa int i sadrži referencu na poziciju

pronađenog sličnog članka u indeksu. Posljednja metoda klase TopDocs je

getMaxScore, kao što i sam čitatelj prema imenu metode može pretpostaviti,

navedena metoda vraća koeficijent sličnosti najsličnijeg članka s upitom prema

String q = reader.document(i).getField("text").stringValue();

...

if (q.length()!=0) {

Query query = new QueryParser("text", new

StopAnalyzer()).parse(QueryParser.escape(q));

...

solution = 1;

} else {

q = reader.document(i).getField("title").stringValue();

Query query = new QueryParser("title", new

StopAnalyzer()).parse(QueryParser.escape(q));

...

solution = 2;

}

if (docs.scoreDocs.length<(num+1) && solution == 1) {

q = reader.document(i).getField("title").stringValue();

Query query = new QueryParser("title", new

StopAnalyzer()).parse(QueryParser.escape(q));

...

}

. . .

Kod 1 Logika kojom se pokušava osigurati minimalno num TopDocs sličnih članaka svakom članku u matrici sličnosti

Page 21: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

17

zadanim kriterijima, odnosno koeficijent sličnosti članka koji se nalazi na prvom

mjestu u polju koje vraća metoda scoreDocs.

Formula prema kojoj knjižnica Apache Lucene na temelju upita računa koeficijente

n najsličnijih članaka, a provede se nad svakim člankom (d) koji sadrži barem

jednu riječ iz upita (q), jest:

∑ (𝑡𝑓(𝑡 𝑖𝑛 𝑑) ∗ 𝑖𝑑𝑓(𝑡)2

𝑡 𝑖𝑛 𝑞∗ 𝑏𝑜𝑜𝑠𝑡(𝑡. 𝑓𝑖𝑒𝑙𝑑 𝑖𝑛 𝑑) ∗ 𝑙𝑒𝑛𝑔𝑡ℎ𝑁𝑜𝑟𝑚 (𝑡. 𝑓𝑖𝑒𝑙𝑑 𝑖𝑛 𝑑)

∗ 𝑐𝑜𝑜𝑟𝑑(𝑞, 𝑑) ∗ 𝑞𝑢𝑒𝑟𝑦𝑁𝑜𝑟𝑚 (𝑞)

Gdje je tf (t in d) faktor TF (Term Frequency) za riječ t u članku d, odnosno broj

ponavljanja riječi t u članku d, idf(t) je ranije, u poglavlju 2.1, objašnjen faktor IDF

(Inverse Document Frequency), koeficijent težine riječi u dokumentu, odnosno

mjera koliko je riječ jedinstvena. Ovaj koeficijent je važan jer riječi koji su česte

imaju niži koeficijent težine budući da nisu toliko relevantne ako se nalaze u

dokumentu, od riječi koje su rijetke, odnosno specifične za određenu temu. Boost

(t.field in d) jest mogućnost povećanja težine važnosti određenog polja u

indeksiranom članku. Koeficijent Boost je inicijalno postavljen na jedan, što znači

da ne utječe na ukupan produkt, a inicijalna vrijednost je korištena i u razvijenom

programskom modulu. lengthNorm (t.field in d) jest normalizacijska vrijednost

polja, a odnosi se na količinu teksta indeksiranog u pojedinom polju. Navedena

vrijednost se generira prilikom indeksiranja, a kraća polja, koja sadrže manje riječi,

imaju pridruženu veću normalizacijsku vrijednost upravo kroz ovaj član u produktu.

Coord (q,d) jest koordinacijski faktor koji se temelji na broju riječi iz upita (q) koje

sadrži članak (d). Koordinacijski faktor je veći upravo za članke koji sadrže više

riječi iz upita te im tako dodatno povećava važnost. queryNorm (q) jest

normalizacijska vrijednost za upit, a vrijednost joj ovisi od sumi kvadrata težina

svih riječi koje se nalaze u upitu. Koeficijent QueryNorm u razvijenom

programskom modulu nije relevantan budući da je jednak za sve članke iz

rezultata jer se unutar programskog modula za svaki članak koristi jedinstven upit

na temelju kojeg se dobivaju njemu slični članci, a koeficijent queryNorm dolazi do

izražaja samo kad se koriste složeni upiti.

Page 22: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

18

5 Arhitektura i implementacija programskog modula

Slika 3 Arhitektura programskog modula za preporučivanje

Kao što se može vidjeti na Slika 3, razvijeni programski modul pruža sučelje

prema web-portalu uz pomoć kojeg se njegove funkcionalnosti integriraju unutar

portala, a željena akcija se pokreće preko javnih metoda koje su izložene preko

sučelja.

Funkcionalnosti koje su implementirane unutar programskog modula su učitavanje

članka u formatu XML u indeks te generiranje matrice sličnosti članaka iz

prethodno generiranog indeksa, bilježenje korisničkih ocjena za članke, brisanje

članka iz indeksa i matrice sličnosti te brisanje zapisa korisničkih ocjena iz

datoteke CSV korisničkih interakcija. Najvažnija akcija, prema kojoj je programski

modul dobio i ime, jest generiranje preporuke koja će se prikazati korisniku na

poziv metode od strane web-portala, a preporuka se generira na temelju ranije

generirane matrice sličnosti članaka te zapisa zabilježenih unutar datoteke CSV

korisničkih interakcija.

Page 23: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

19

5.1 Opis klasa i metoda razvijenog programskog modula

Programski modul za preporučivanje podijeljen je u više klasa prema

funkcionalnostima koje su implementirane unutar modula. Klase koje su

implementirane unutar modula su NewsItem, Text, Indexer,

MatrixGeneratorWithTopDocs, ItemRecommenderFromDataModelTopDocs,

ItemRecommenderFromTopDocsMatrix, ItemSimilarityFromTopDocsMatrix te

DataModelGenerator. Klase NewsItem i Text predstavljaju članke i tekst koji se u

njima nalazi. Unutar klase Indexer implementirane su metode koje se odnose na

spremanje članaka u indeks, metode klase MatrixGeneratorWithTopDocs

koriste se koriste za generiranje matrica sličnosti na temelju podataka iz indeksa.

Zatim slijede klase ItemRecommenderFromDataModelTopDocs i

ItemRecommenderFromTopDocsMatrix koje generiraju preporuke na temelju

podataka iz matrice sličnosti i datoteke CSV korisničkih interakcija, odnosno na

temelju sličnosti definirane u klasi ItemSimilarityFromTopDocsMatrix. Unutar

klase DataModelGenerator implementirane su metode za manipuliranje

datotekom CSV korisničkih interakcija.

5.1.1 Klase NewsItem i Text

Klase NewsItem i Text su vrlo jednostavne klase koje su implementirane jer su

potrebne kako bi se unutar programskog modula mogla koristiti Javina

programska knjižnica Apache Commons Digester kao parser za parsiranje ulaznih

članka u formatu XML. Klasa Text se sastoji od privatne varijable _p tipa String

koja predstavlja odlomak u tekstu koji se parsira budući da je u testnim podacima

zamijećeno da se tekst koji se nalazi unutar oznake text u datoteci XML članka

često sastoji od više odlomaka odvojenih oznakama p. Osim privatne varijable

unutar klase Text još su implementirane i javne metode getP i setP, gdje metoda

getP vraća sav tekst zapisan u privatnu varijablu _p i stoga je tipa String, a

metoda setP na postojeći tekst koji se nalazi zapisan u varijabli _p konkatenira

novi tekst koji joj se preda kao parametar pri pozivu. Metoda setP je tipa void,

odnosno ne vraća nikakav rezultat.

Page 24: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

20

Klasa NewsItem se sastoji od dvije privatne varijable, _title tipa String i _txt

tipa Text, te također javnih metoda getTitle, setTitle i getText, setText,

gdje je metoda getTitle tipa String i vraća naslov članka koji se nalazi zapisan

u _title varijabli. Metoda getText je tipa Text, odnosno vraća instancu klase

Text koja je prethodno opisana, a koja je pohranjena u varijabli _txt. Metode Set

u oba slučaja ne vraćaju nikakav rezultat te su tipa void, a ovisno o tome radi li se

o metodi setTitle ili setText kao parametar primaju varijablu tipa String,

odnosno Text te primljenu vrijednost pohranjuju u privatnu varijablu _title

odnosno _txt.

5.1.2 Klasa Indexer

Unutar klase Indexer implementirane su metode koje pokrivaju čak pet procesa

navedenih na Slika 3. Procesi koje pokrivaju metode klase Indexer su učitavanje

članka u formatu XML, parsiranje članka, kreiranje dokumenta Apache Lucene,

indeksiranje dokumenta te djelomično brisanje članka.

Unutar klase Indexer su, osim navedenih metodi, implementirane i dvije

konstante kojima se postavlja konfiguracija indeksa te globalna varijabla tempMap

koja je tipa HashMap i koja se koristi prilikom inicijalnog kreiranja indeksa, kako bi

identifikatore članaka u indeksu povezali s potpunim putanjama do članaka koje se

predaju kao parametar prilikom indeksiranja, ali i prilikom poziva svih ostalih akcija

koje su povezane s člancima, poput dohvaćanja preporuke za određeni članak i

slično.

Javna metoda koja se koristi prilikom učitavanja članka te aktivira sve akcije sa

Slika 3 do generiranja matrice sličnosti je metoda addNewsItem (String

dataPath). Metoda addNewsItem ne vraća nikakav rezultat, a kao parametar

prima ili putanju prema direktoriju unutar kojeg se može nalaziti čitava struktura

private static final StandardAnalyzer analyzer = new

StandardAnalyzer();

private static final IndexWriterConfig config = new

IndexWriterConfig(analyzer);

Kod 2 Konstante konfiguracije indeksa Apache Lucene

Page 25: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

21

datoteki za indeksiranje i direktorija u kojima se one nalaze ili prema datoteci XML

koju se želi pohraniti u indeks te dodati u matricu sličnosti. Unutar addNewsItem

metode otvara se kanal IndexWriter za pisanje u indeks, s konfiguracijom koja je

određena ranije navedenim konstantama.

Metodom je razvijena logika koja sprječava kreiranje indeksa od jedne datoteke

budući da takav indeks, odnosno matrica sličnosti koja se kreira iz takvog indeksa

nema smisla. Tako je unutar metode postavljen uvjet da je prilikom prvog poziva,

dok u sustavu još ne postoji kreirana matrica sličnosti, kao parametar potrebno

predati putanju do direktorija koji sadrži skup datoteka XML od kojih je onda

moguće kreirati smislenu matricu sličnosti. Nakon što je u sustavu jednom kreirana

matrica sličnosti metoda se može pozivati samo s datotekama XML prilikom

dodavanja novog članka na web-portal. To je napravljeno kako ne bi došlo do

nekonzistencije web-portala s indeksom članaka, budući da se članci na web-

portal ne dodaju u folderima, već pojedinačno.

Nakon što provjeri konzistentnost, metoda addNewsItem poziva privatnu metodu

index (IndexWriter writer, File dataDir), koja je samo kontrolna metoda

unutar koje se računa i ispisuje vrijeme potrebno za indeksiranje predane strukture

direktorija ili datoteke, izvršava pohranu promjena iz spremnika u indeks te poziva

privatnu rekurzivnu metodu indexDirectory (IndexWriter writer, File

if (dataDir.getName().endsWith(".xml") && matrix != null) {

...

} else if(dataDir.isDirectory() && matrix == null) {

...

} else {

...

System.out.println ("You must set folder as path for fisrt

time. Otherwise XML file is needed.");

}

Kod 4 Uvjeti kojima se postiže konzistentnost

Directory indexDir = getIndexDir();

IndexWriter writer = new IndexWriter (indexDir, config);

Kod 3 Otvaranje kanala za pisanje u indeks Apache Lucene

Page 26: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

22

dataDir) koja prolazi kroz cijelu predanu strukturu i kad u strukturi pronađe

datoteku XML poziva privatnu metodu indexFile (IndexWriter writer, File

f). Kada se izvrši metoda indexDirectory, metoda index poziva metodu

addingNewsItem() odnosno initialGenerator(n), kojom ili dodaje novo

indeksirani dokument u postojeću matricu sličnosti ili kreira matricu sličnosti u kojoj

će za svaki članak biti zapisano n najsličnijih članaka, što ovisi o tome postoji li već

matrica sličnosti u sustavu ili ne te je li putanja koja je predana u metodu

addNewsItem putanja do datoteke ili putanja do direktorija, što se može vidjeti u

uvjetima koji su navedeni u Kod 4 Uvjeti kojima se postiže konzistentnost.

U metodi indexFile je implementirana sva logika indeksiranja datoteke, od

parsiranja XML-a, izdvajanja bitnog sadržaja, kreiranja dokumenta Apache

Lucene, upisivanja izdvojenog sadržaja u polja dokumenta Apache Lucene te

pohranjivanja kreiranog dokumenta u indeks.

U Kod 5 je prikazano na koji način se koriste implementirane klase

NewsitemNewsItem i Text prilikom parsiranja datoteka XML, također je prikazano

korištenje dvije različite vrste polja koja se mogu pohraniti u indeks. Za polje tipa

digester.addObjectCreate ("newsitem", Newsitem.class);

digester.addObjectCreate ("newsitem/text", Text.class);

...

Newsitem newsitem = (Newsitem) digester.parse(f);

...

ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS

_AND_OFFSETS);

...

ft2.setIndexOptions(IndexOptions.DOCS);

Field titleField = new Field ("title", newsitem.getTitle(),

ft);

doc.add(titleField);

...

Field nameField = new Field ("name", f.getName(), ft2);

doc.add(nameField);

writer.addDocument(doc);

Kod 5 Osnovna logika indexFile metode

Page 27: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

23

ft se indeksira cjelokupni sadržaj, frekvencije pojavljivanja riječi u tekstu, pozicije

riječi i odmaci, a za polje tipa ft2 indeksira se samo sadržaj jer ostali podaci u

slučaju razvijenog modula nisu bitni za sadržaj koji indeksiramo u poljima tog tipa.

Sljedeća metoda implementirana unutar klase Indexer jest javna metoda sučelja

programskog modula koju je potrebno pozvati prilikom brisanja članka s web-

portala. Metoda removeNewsItem (String absolutePath) iz indeksa briše

članak čija joj je apsolutna putanja proslijeđena kao parametar. Nakon što obriše

članak iz indeksa, poziva metodu kojom se članak briše iz matrice sličnosti

članaka te metodu koja briše sve zapise o ocjenjivanju članka iz datoteke CSV s

korisničkim interakcijama, također briše zapis o članku iz HashMape u kojoj su

apsolutne putanje do članka povezane s identifikatorom članka u indeksu. Važno

je napomenuti kako iz indeksa Apache Lucene nije moguće brisati prema

identifikatoru članka u indeksu, već se brisanje izvršava prema određenoj

vrijednosti u polju dokumenta u indeksu, pa je tako potrebno imati jedno polje

jedinstvene vrijednosti po kojem će biti omogućeno brisanje dokumenata iz

indeksa.

U klasi Indexer implementirane su još tri pomoćne metode koje služe za

održavanje konzistencije sustava te dohvaćanje i spremanje datoteka koje su

potrebne za pravilan rad sustava. Metoda getIndexDir() tipa Directory vraća

apsolutnu putanju do direktorija u kojem se nalazi indeks, metoda setIndexMap

(HashMap <String,Integer> outputMap) zapisuje HashMapu u kojoj su

povezane apsolutne putanje do članaka s identifikatorima članaka u indeksu u

datotečni sustav, a metoda getIndexMap() dohvaća navedenu HashMapu iz

datotečnog sustava, na temelju čega i sam čitatelj može zaključiti da navedena

metoda mora biti tipa HashMap <String,Integer>. Tri posljednje metode su

javne jer se koriste za dohvaćanje i postavljanje navedenih datoteka i iz drugih

klasa. Na taj se način čuva konzistencija sustava.

Page 28: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

24

5.1.3 Klasa MatrixGeneratorWithTopDocs

Klasa MatrixGeneratorWithTopDocs sadrži metode unutar kojih je

implementirana sva manipulacija matricom sličnosti članaka. Sadrži tri glavne

javne metode, jednu pomoćnu metodu koja se koristi za dohvaćanje TopDocs

najsličnijih članaka svakom članku koji se smješta u matricu i tri pomoćne metode

koje se koriste za pohranjivanje matrica u datotečni sustav i dohvaćanje istih iz

datotečnog sustava.

Javna metoda initialGenerator(int n) služi za inicijalno kreiranje matrice

sličnosti i poziva se prilikom prvog poziva metode addNewsItem kada je kao

parametar pri pozivu metode addNewsItem predana apsolutna putanja do

direktorija koji sadrži inicijalni skup članaka koje želimo indeksirati i smjestiti u

matricu sličnosti. Metoda initialGenerator prima parametar tipa integer kojim

se pri inicijalnom generiranju matrice može odabrati za svaki članak u matrici s

koliko će članaka biti definiran koeficijent sličnosti, odnosno broj stupaca matrice.

Jednom kad je taj broj definiran pri inicijalnom generiranju matrice, svaki novi

članak koji se dodaje u matricu sličnosti će u matrici imati pohranjeno n najsličnijih

članaka.

Javna metoda addingNewsItem() ne prima nikakve parametre jer se u index

metodi klase Indexer poziva neposredno nakon indeksiranja članka te samo

uzima posljednji članak iz indeksa i kreira redak s njemu sličnim člancima u matrici

sličnosti.

for (i=0; i<reader.numDocs(); i++) {

TopDocs docs = getTopDocs (reader, is, i, num);

for (j=1; j<docs.scoreDocs.length; j++) {

System.out.println (docs.scoreDocs[j].doc+"

"+docs.scoreDocs[j].score);

similarityIndexesMatrix[i][j-1]=docs.scoreDocs[j].doc;

similarityValuesMatrix[i][j-1]=docs.scoreDocs[j].score;

}

}

Kod 6 Petlje za generiranje inicijalne matrice sličnosti

Page 29: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

25

U javnoj metodi removingNewsItem (docId) implementirano je brisanje zapisa iz

matrice sličnosti za članak koji se u indeksu nalazi kao dokument pod docId

identifikatorom. Ovakav način brisanja članka iz matrice sličnosti je omogućen jer

su članci u retke matrice sličnosti pohranjeni istim redoslijedom kao i dokumenti u

indeksu, te je identifikator dokumenta iz indeksa moguće iskoristiti kao identifikator

retka u kojem se članak nalazi u matrici.

Sljedeća metoda koja je implementirana u navedenoj klasi jest privatna metoda

getTopDocs (IndexReader reader, IndexSearcher is, int i, int num)

koja je tipa TopDocs te vraća minimalno num TopDocs najsličnijih članaka za

članak koji se u indeksu iz kojeg čitamo readerom nalazi pod identifikatorom i.

Detalji logike kojom se kreira TopDocs polje najsličnijih članaka su opisani ranije u

poglavlju 4.2.

Unutar dane klase implementirane su još privatna metoda outputtingMatrix

(int[][] similarityIndexesMatrix,float[][] similarityValuesMatrix)

te javne metode getSimilarityIndexesOutput() i

getSimilarityValuesOutput(), koje se koriste za pohranjivanje u, odnosno

dohvaćanje matrica sličnosti iz datotečnog sustava.

5.1.4 Klasa ItemSimilarityFromTopDocsMatrix

Unutar klase ItemSimilarityFromTopDocsMatrix implementirane su metode

sučelja Apache Mahout ItemSimilarity. Osnovne metode koje su

implementirane su javne metode itemSimilarity(long itemID1, long

itemID2), itemSimilarities(long itemID1, long[] itemID2s) te metoda

allSimilarItemIDs(long itemID). Klasa sadrži još i varijablu matrixIndexes

koja je dvodimenzionalno polje tipa integer te varijablu matrixValue koja je

dvodimenzionalno polje tipa float. Budući da će kasnije pri kreiranju preporuka

IndexReader reader = DirectoryReader.open(fsDir);

IndexSearcher is = new IndexSearcher (reader);

...

TopDocs docs = getTopDocs (reader, is, reader.numDocs()-1,num);

Kod 7 Dohvaćanje TopDocs najsličnijih za posljednji dokument u indeksu

Page 30: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

26

biti potrebno koristiti objekt tipa ItemSimilarty, unutar klase

ItemSimilarityFromTopDocs implementiran je i konstruktor

ItemSimilarityFromTopDocsMatrix (int[][] matrixIndexes, float[][]

matrixValues) pri pozivu kojeg je potrebno predati implementaciju matrice

sličnosti, odnosno dvije ranije već više puta opisane matrice, unutar kojih se

nalaze identifikatori iz indeksa za slične članke svakom članku, odnosno

vrijednosti tih sličnosti. U konstruktoru klase predane matrice pohranjuju se u

ranije navedene privatne varijable.

Metoda itemSimilarity (long itemID1, long itemID2) prima identifikatore

iz indeksa za dva članka te prolazi kroz redak članka koji ima referencu itemID1 u

matrici identifikatora (matrixIndexes) i traži postoji li u tom retku identifikator

itemID2. Ako postoji, prolazi kroz redak članka itemID1 u matrici vrijednosti

sličnosti (matrixValues) i traži vrijednost koja se nalazi na poziciji članka

itemID2 te vraća tu vrijednost. Ako pak zapis za itemID2 ne postoji u retku

članka itemID1 unutar matrice identifikatora, metoda vraća nulu.

Metoda itemSimilarities (long itemID1, long[] itemID2s) funkcionira na

sličan način kao i metoda itemSimilarity. Princip je preuzet iz metode

ItemSimilarity, a razlika je u tome što ova metoda u retku članka s

identifikatorom itemID1 unutar matrice identifikatora traži niz referenci iz polja

identifikatora itemID2s te ako identifikator postoji vraća vrijednosti sličnosti s iste

pozicije iz matrice vrijednosti sličnosti, a ako ne postoji vraća nulu.

for (int i=0; i<length; i++) {

contains = false;

for (int j=0; i<matrixIndexesRow.length; i++) {

if (matrixIndexesRow[i]==(((int)itemID2s[j])-1)) {

ind = i;

contains = true;

}

}

if (contains) {

result[i] = matrixValuesLocal[((int)itemID1)-1][ind];

} else {

result[i] = 0;

}

}

return result;

Kod 8 Logika implementirana u itemSimilarites metodi

Page 31: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

27

Metoda allSimilarItemIDs (long itemID) jednostavno izdvoji redak članka

itemID iz matrice identifikatora (matrixIndexes) i vrati navedeni redak, unutar

kojeg se nalaze identifikatori svih članaka koji su zabilježeni kao slični članku

itemID, kao rezultat.

5.1.5 Klasa ItemRecommenderFromTopDocsMatrix

Unutar klase ItemRecommenderFromTopDocsMatrix implementirana je metoda

getTopNRecommendationsFromMatrix (String absolutePath, int N) koja

na temelju apsolutne putanje do članka, i broja N koji je broj preporuka koji se želi

dohvatiti, dohvaća preporuke na temelju sadržaja matrice identifikatora. Naime,

na temelju apsolutne putanje do članka, metoda iz ranije kreirane HashMape koja

povezuje identifikatore članaka i njihove apsolute putanje dohvaća identifikator

članka iz indeksa te budući da je taj identifikator jednak retku matrice identifikatora

u kojoj se nalaze identifikatori članaka sličnih traženom članku, dohvaća prvih N

identifikatora iz tog retka. Nakon dohvaćanja pretražuje HashMapu te nalazi

putanje koje su povezane s pronađenim identifikatorima i sprema ih u skup (engl.

set) koji na kraju izvršavanja vraća korisniku. Vraćeni skup tada se može iskoristiti

za posluživanje preporuka korisniku. Važno je napomenuti da je način

implementiran unutar metode getTopNRecommendationsFromMatrix

ekvivalentan načinu koji je teoretski opisan ranije u poglavlju 2.1, odnosno radi se

čisto o preporukama prema sličnosti sadržaja.

for (int j=0; j< numOfRecommends; j++) {

for (String absPath : indexMap.keySet()) {

int recId = inMatrix[itemId][j];

if (indexMap.get(absPath).equals(recId)) {

shouldRecommend.add(absPath);

}

}

}

Kod 9 Osnova logika ItemRecommenderFromTopDocsMatrix

Page 32: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

28

5.1.6 Klasa ItemRecommenderFromDataModelTopDocs

Unutar klase ItemRecommenderFromDataModelTopDocs implementirana je

metoda getTopNRecommendations, koja s obzirom na primljeni broj parametara

ima različite implementacije. Navedene mogućnosti poziva metode

getTopNRecommendationsFromDataModelTopDocs su poziv s apsolutnom

putanjom članka i brojem željenih preporuka, jednak kao poziv metode

getTopNRecommendationsFromMatrix u prethodnom poglavlju, poziv s

identifikatorom korisnika (user-id iz datoteke CSV interakcija) i brojem željenih

preporuka te poziv s apsolutnom putanjom članka, identifikatorom korisnika i

brojem željenih preporuka kao kombinacija prethodna dva poziva.

Prilikom poziva metode na prvi navedeni način dohvaćaju se preporuke samo na

temelju predane putanje do članka te se radi o preporukama sličnim onima iz

metode getTopNRecommendationsFromMatrix iz prethodnog poglavlja, iako ne

nužno istima. Naime klasa ItemRecommenderFromDataModelTopDocs instancira

preporučitelje knjižnice Apache Mahout te u stvaranju preporuka na ovaj način nije

bitna samo sličnost članaka, već je uvijek potrebno imati i datoteku CSV

korisničkih interakcija odnosno DataModel. Osim datoteke CSV korisničkih

interakcija potrebno je instancirati i objekt klase koja implementira klasu Apache

Mahout ItemSimilarity, što je u slučaju razvijenog programskog modula objekt

klase ItemSimilarityFromTopDocsMatrix, pri pozivu čijeg je konstruktora

potrebno predati ranije kreirane matrice sličnosti članaka. Na temelju DataModela

i ItemSimilarity objekta instancira se objekt klase

GenericItemBasedRecommender čijom se metodom mostSimilarItems

(itemID, N) koristi logika preporučitelja Apache Mahout i korisniku poslužuje N

najsličnijih članaka članku čija je apsolutna putanja predana. Kao rezultat također

se vraćaju apsolutne putanje do najsličnijih članaka kako bi se zadržala

konzistencija sustava i omogućilo što jednostavnije serviranje preporuka korisniku.

Kada se metoda pozove s parametrima koji su navedeni kao drugi način poziva,

preporuke se kreiraju čisto na temelju sličnosti korisnika iz datoteke CSV

korisničkih interakcija (DataModel). Na temelju modela se instancira objekt klase

UserSimilarity, a sličnost korisnika koja se pohranjuje u instancirani objekt

Page 33: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

29

računa se na temelju izračuna Pearsonovog koeficijenta korelacije koji je opisan

ranije u poglavlju 4.1. Pri pozivu metode s ovakvim parametrima instancira se

objekt klase Apache Mahout UserBasedRecommender koji nudi metodu

recommend (userId, N), koja na temelju izračunatih Pearsonovih koeficijenata

sličnosti iz DataModela korisniku vraća potencijalno interesantne članke čisto na

temelju sličnosti njegovih interesa s ostalim korisnicima.

Pri pozivu metode s parametrima koji su navedeni kao treći način poziva,

instanciranje objekata Apache Mahout kao logike koja kreira preporuke odvija se

na jednak način kao u prvom slučaju, ali se nad objektom klase

GenericBasedRecommender također pozove metoda recommend (userId, N)

koja za željenog korisnika na temelju DataModela i instance klase

ItemSimilarityFromTopDocsMatrix kreira preporuke koje bi mu trebale biti

interesantne. U ovom slučaju radi se o preporukama koje kombiniraju sličnost

korisnika na temelju DataModela i sličnost članaka na temelju objekta

ItemSimilarity, odnosno o preporukama na temelju hibridne sličnosti (engl.

Hybrid similarity).

Važno je napomenuti da ako metoda getTopNRecommnedations iz nekog razloga

ne uspije dohvatiti željeni broj preporuka, a pri pozivu je kao parametar predana i

apsolutna putanja do članka, sustav se spušta logičku razinu niže i zove metodu

getTopNRecommendationsFromMatrix s predanom apsolutnom putanjom te

vraća preporuke čisto na temelju sličnosti članaka.

5.1.7 Klasa DataModelGenerator

Funkcionalnosti koje su implementirane unutar klase DataModelGenerator ne

moraju biti nužno dio razvijenog programskog modula, već se mogu odvijati

negdje odvojeno, u tom je slučaju modulu potrebno osigurati pristup prema

datoteci CSV koja je generirana od treće strane. Za testiranje programskog

modula bilo je potrebno razviti i ovakvu komponentu kako bi se mogla generirati

testna datoteka CSV korisničkih interakcija. Budući da su razvijene i metode

pomoću kojih se mogu dodavati retci u datoteku CSV korisničkih interakcija, ali i

Page 34: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

30

brisati retci za one članke koji su obrisani iz sustava, ova je komponenta sasvim

legitimna za korištenje kao dio programskog modula.

Unutar klase DataModelGenerator implementirane su tri glavne metode,

initialModel(), rateNewsItem (userId, absolutePath, rating) i

removeRatingsForDeletedNewsItem (absolutePath).

Metoda initialModel() implementirana je kako bi se kreirala testna datoteka

CSV korisničkih interakcija (DataModel) kojom je omogućeno kvalitetno testiranje

modula.

Unutar metode rateNewsItem (userId, absolutePath, rating)

implementirana je logika dodavanja novog retka u datoteku CSV korisničkih

interakcija na temelju predanog korisničkog identifikatora (userId), apsolutne

putanje do članka (absolutePath) i ocjene koju je korisnik pridijelio članku

(rating).

Metodom removeRatingsForDeletedNewsItem (aboslutePath) se na temelju

apsolutne putanje članka pri brisanju članka iz sustava mogu obrisati svi zapisi

korisničkih ocjena pridijeljenih za članak čija je apsolutna putanja predana.

Brisanje funkcionira tako da metoda pronalazi identifikator obrisanog članka iz

HashMape koja povezuje apsolutne putanje sa identifikatorima te briše sve retke u

datoteci CSV koji na mjestu identifikatora članka imaju upravo pronađeni

identifikator.

Unutar klase je implementirana još i privatna metoda emptyFile koje se koristi u

prethodnoj metodi jer brisanje redaka iz datoteke CSV funkcionira na način da se

datoteka CSV isprazni te se ponovno puni samo onim retcima iz stare datoteke u

kojima identifikator članka nije jednak pronađenom identifikatoru članka.

emptyFile (dataModel); ...

for (String fileContentLine : fileContentLines) {

if (fileContentLine.contains(","+newsItemId+",")) {

continue;

}

newContent.append(fileContentLine +

System.lineSeparator());

}

Kod 10 Logika brisanja redaka iz datoteke CSV

Page 35: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

31

6 Slučajevi uporabe (engl. use cases) i metode sučelja

Implementacijska logika metoda koje su izložene (engl. expose) web-portalu i koje

će biti spominjane prilikom opisivanja slučajeva uporabe opisana je u prethodnoj

cjelini. U nastavku će biti opisano kako na pravilan način koristiti izložene metode

te dobivati što efikasnije preporuke na web-portalu unutar kojeg je integriran

razvijeni programski modul.

6.1 Inicijalizacija sustava i dodavanje novog članka u sustav

Slika 4 Dijagram za akcije inicijalizacije sustava i dodavanja članka

Page 36: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

32

Inicijalizacija sustava i dodavanje novog članka u sustav vrše se metodom

addNewsItem (String absolutePath). Kao što je i ranije objašnjeno, kada u

sustavu još ne postoji generiran indeks, niti matrica sličnosti, metodu

addNewsItem potrebno je pozvati s apsolutnom putanjom prema direktoriju koji

sadrži skup članaka kojima će se sustav inicijalizirati. Jednom kad je sustav

inicijaliziran, metoda addNewsItem prihvaća isključivo apsolutne putanje do

članaka, odnosno datoteka XML članaka, koje indeksira i smješta u novi redak

matrice sličnosti kako bi se mogli pojaviti kao preporuke. Poziv iste metode

prilikom inicijalne konfiguracije sustava i prilikom dodavanja novog članka

olakšava posao administratoru sustava te smanjuje mogućnost inicijalizacije

sustava malim brojem članaka ili čak samo jednim člankom, što se želi izbjeći, jer

ako sustav ima mali broj članaka u matrici sličnosti, kreirane preporuke nemaju

smisla, a često i nije moguće pronaći članak dovoljno sličan da bi se uopće

preporučio.

6.2 Brisanje postojećeg članka iz sustava

Slika 5 Dijagram za akciju brisanja članka iz sustava

Page 37: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

33

Prilikom brisanja članka iz sustava potrebno je pozvati metodu removeNewsItem

(String absolutePath). Metoda briše članak koji je zabilježen pod predanom

apsolutnom putanjom iz indeksa, kao i sve zapise koji su povezani s člankom, a

nalaze se u datotekama koje sustav koristi. To su zapisi u matricama sličnosti,

zapisi u datoteci CSV korisničkih interakcija te zapis iz HashMape indeksa.

6.3 Pridjeljivanje ocjene članku

Slika 6 Dijagram akcije korisničkog ocjenjivanja članka

Kada korisnik web-portala koji unutar kojeg je integriran programski modul za

preporučivanje pridoda ocjenu određenom članku, potrebno je pozvati metodu

rateNewsItem (int userId, String absolutePath, int rating), te joj

predati identifikator korisnika koji je pridijelio ocjenu, apsolutnu putanju do članka

koji je ocijenjen i ocjenu koja je pridijeljena za članak. Navedena metoda će iz

predanih parametara generirati novi redak u datoteci CSV korisničkih interakcija u

obliku <userId, newsItemId, rating>.

6.4 Generiranje preporuka

Slika 7 Dijagram akcije generiranja preporuka

Page 38: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

34

Posljednji slučaj korištenja razvijenog programskog modula jest onaj prema kojem

je sam modul dobio i ime, a to je generiranje preporuka. Preporuke se, kao što je i

ranije opisano, generiraju na poziv metode getTopNRecommendations gdje

navedena metoda ima tri implementacije s obzirom na broj i vrstu predanih

parametara pri pozivu. Tako je metodu getTopNRecommendations moguće

pozvati s apsolutnom putanjom članka i željenim brojem preporuka (String

absolutePath, int N), gdje metoda vraća preporuke koje ovise o sličnosti

članaka koristeći logiku knjižnice Apache Mahout, s apsolutnom putanjom članka,

identifikatorom korisnika i željenim brojem preporuka (String absolutePath,

int userId, int N). U ovom slučaju metoda vraća preporuke na temelju

kombinacije sličnosti članaka i korisnika te s identifikatorom korisnika i željenim

brojem preporuka (int userId, int N), gdje metoda vraća preporuke

isključivo na temelju sličnosti korisnika. Pri prva dva načina poziva metode

getTopNRecommendations omogućeno je spuštanje sustava na jednu logičku

razinu niže, ako zbog nekog razloga nije moguće kreirati preporuke na temelju

logike knjižnice Apache Mahout. U tom slučaju sustav na temelju apsolutne

putanje članka traži slične članke direktno u matrici sličnosti te vraća preporuke

prema najsličnijim člancima direktno iz matrice sličnosti, ne koristeći logiku

knjižnice Apache Mahout.

Programski modul preporuke vraća isključivo kao skup stringova koji predstavljaju

apsolutne putanje do članaka koji su preporučeni te tako olakšava manipuliranje

generiranim preporukama, odnosno njihovu prezentaciju.

Također je važno primijetiti da sve metode koje su izložene iz programskog

modula prema web-portalu kao referencu za članke koriste apsolutnu putanju

članka te se tako osigurava potpuna konzistencija suradnje između programskog

modula i web-portala.

Page 39: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

35

7 Zaključak

Vrlo velika količina podataka dostupna korisnicima na web-portalima i Internetu

općenito često kod korisnika ne izaziva znatiželju čija bi posljedica bilo

pretraživanje svih dostupnih informacija, već upravo suprotno. Kada korisnik

primijeti veliku količinu međusobno nepovezanog sadržaja, često izgubi motivaciju

i odustaje od daljnjeg korištenja portala na kojem je doživio navedeno iskustvo.

Kako zbog prethodno navedenog ne bi došlo do gubitka korisnika, a samim time i

smanjenja zarade od klikova na različite reklame i slično, vrlo je važno u sklopu

web-portala imati integriran sustav koji će korisniku posluživati onaj sadržaj koji će

korisnika zadržati na portalu što više vremena, zbog kojeg će korisnik biti

zadovoljniji i vraćati se na isti web-portal ponovno.

Programski modul za preporučivanje sadržaja na web-portalima je upravo takav

inteligentan sustav, koji na temelju sličnosti sadržaja te na temelju korisničkih

interakcija pruža mogućnost posluživanja prijedloga korisniku upravo onog

sadržaja koji je sličan sadržaju koji korisnik u trenutku čita, ali i sadržaju koji su

čitali drugi korisnici koji imaju slične korisničke preferencije kao trenutni korisnik.

Ovakav način kreiranja prijedloga zanimljivog sadržaja unutar programskog

modula omogućen je integracijom dviju vrlo moćnih programskih knjižnica

otvorenog koda Apache. Pomoću programske knjižnice Apache Lucene

omogućeno je indeksiranje članaka koji se unesu u web-portal te kreiranje matrica

sličnosti isključivo po sadržaju članaka. Pomoću programske knjižnice Apache

Mahout omogućena je logika traženja sličnosti među korisnicima te kreiranje

preporuka za članke na temelju sadržajne sličnosti, koja je izračunata ranije

Lucenom, i na temelju sličnosti korisnika.

Vrlo je važno napomenuti kako sve metode koje su izložene web-portalu koji bi

integrirao programski modul koriste konzistentne parametre, te da administrator

web-portala za pravilan rad s integriranim modulom mora znati samo apsolutnu

putanju svakog članka koji se nalazi u indeksu te identifikator svakog korisnika koji

je registriran na web-portalu. Nakon integracije i inicijalizacije modula s web-

portalom administrator koji posjeduje gore navedene podatke na najjednostavniji

način može dohvaćati prijedloge preporučljivog sadržaja.

Page 40: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

36

8 Literatura

[1] Ted Dunning, Ellen Friedman, Practical Machine Learning. O’Reilly Media,

Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472, 2014.

[2] Sean Owen, Robin Anill, Ted Dunning, Ellen Friedman, Mahout in action.

Manning Publications Co., 20 Baldwin Road, PO Box 261, Shelter Island,

NY 11964, 2012.

[3] Michael McCandless, Erik Hatcher, Otis Gospodnetić, Lucene in action –

second edition. Manning Publications Co., 180 Broad St., Suite 1323,

Stamford, CT 06901, 2010.

[4] https://lucene.apache.org/core/5_3_1/core/overview-summary.html,

13.6.2016.

Page 41: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

37

9 Sažetak

Programski modul za preporučivanje sadržaja na web-portalima

Na početku ovog diplomskog rada opisane su osnovne tehnike kreiranja

preporuka koje su implementirane u razvijenom programskom modulu, a to su

tehnike preporučivanja prema sličnost sadržaja i prema suradnji korisnika. U

sljedećem poglavlju slijedi opis programskih knjižnica Apache Lucene i Mahout

čija je integracija implementirana unutar programskog modula, koje je omogućila

osnovnu funkcionalnost modula. Zatim slijedi poglavlje u kojem su opisane tehnike

određivanja sličnosti koje su implementirane unutar razvijenog programskog

modula, a na kraju se nalaze poglavlja u kojima su opisane arhitektura, klase i

metode razvijenog programskog modula i slučajevi korištenja programskog

modula iz web-portala unutar kojeg bi modul bio integriran.

Ključne riječi: Preporuka, Lucene, Mahout, integracija.

Software module for content recommendations at web-portals

Summary

At the beginning of this master's thesis there is a description of basic

recommendation creating techniques that are integrated into the developed

software, and these are Content-based and Collaborative filtering recommendation

techniques. In the following chapter Apache Lucene and Mahout software libraries

are described, whose integration is incorporated into the software module,

enabling basic functioning of the module. Following this, similarity defining

technics that are integrated into the developed software are discussed. In the final

chapters architecture, classes and methods of the developed software are

depicted, along with the software module usage cases from a web-portal into

which the software module is designed to be integrated.

Keywords: Recommendation, Lucene, Mahout, integration.

Page 42: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

38

10 Dodatak: programski kod

package recs.parse;

/**

*

* @author joe

*/

public class NewsItem {

private String _title="";

private Text _txt;

public String getTitle() {

return _title;

}

public void setTitle(String title) {

_title = title;

}

public Text getText() {

return _txt;

}

public void setText(Text txt) {

_txt = txt;

}

}

package recs.parse;

/**

*

* @author joe

*/

public class Text {

private String _p="";

public String getP() {

return _p;

}

public void setP (String p) {

_p = _p + p;

}

}

Page 43: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

39

package recs.parse;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.util.Date;

import java.util.HashMap;

import org.apache.commons.digester3.Digester;

import org.apache.lucene.document.Document;

import org.apache.lucene.document.Field;

import org.apache.lucene.document.FieldType;

import org.apache.lucene.index.IndexOptions;

import org.apache.lucene.index.IndexWriter;

import org.xml.sax.SAXException;

import org.apache.lucene.index.IndexWriterConfig;

import org.apache.lucene.store.Directory;

import org.apache.lucene.store.FSDirectory;

import org.apache.lucene.analysis.standard.StandardAnalyzer;

import org.apache.lucene.index.DirectoryReader;

import org.apache.lucene.index.IndexReader;

import org.apache.lucene.queryparser.classic.ParseException;

import org.apache.lucene.queryparser.classic.QueryParser;

import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.search.Query;

import org.apache.lucene.search.ScoreDoc;

import org.apache.lucene.search.TopDocs;

import static

recs.basics.DataModelGenerator.removeRatingsForDeletedNewsItem;

import static recs.parse.MatrixGeneratorWithTopDocs.addingNewsItem;

import static

recs.parse.MatrixGeneratorWithTopDocs.getSimilarityIndexesOutput;

import static

recs.parse.MatrixGeneratorWithTopDocs.initialGenerator;

import static

recs.parse.MatrixGeneratorWithTopDocs.removingNewsItem;

public class Indexer {

private static final StandardAnalyzer analyzer = new

StandardAnalyzer();

private static final IndexWriterConfig config = new

IndexWriterConfig(analyzer);

private static HashMap <String,Integer> tempMap = new HashMap<>

();

public static void main (String[] args) throws Exception {

//addNewsItem ("/home/joe/recs/dataset");

//addNewsItem ("/home/joe/recs/2286newsML.xml");

//removeNewsItem ("/home/joe/recs/2286newsML.xml");

}

Page 44: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

40

public static void addNewsItem (String dataPath) throws IOException,

SAXException, Exception {

File dataDir = new File (dataPath);

if (!dataDir.exists()) {

throw new IOException (dataDir + " does not

exist");

}

Directory indexDir = getIndexDir();

IndexWriter writer = new IndexWriter (indexDir, config);

//DELETION OF OLD DATA IN INDEX

//writer.deleteAll();

int [][] matrix = null;

try {

matrix = getSimilarityIndexesOutput();

} catch (FileNotFoundException e) {

System.out.println (e);

}

if (dataDir.getName().endsWith(".xml") && matrix != null)

{

index (writer, dataDir);

addingNewsItem();

HashMap <String,Integer> map = getIndexMap();

map.put(dataDir.getAbsolutePath(),

writer.numDocs()-1);

setIndexMap (map);

writer.close();

} else if(dataDir.isDirectory() && matrix == null) {

index (writer, dataDir);

initialGenerator (100);

setIndexMap (tempMap);

writer.close();

} else {

writer.close();

System.out.println ("You must set folder as path

for fisrt time. Otherwise XML file is needed.");

}

}

private static void index (IndexWriter writer, File dataDir) throws

SAXException, Exception {

long start = new Date().getTime();

indexDirectory (writer, dataDir);

long end = new Date().getTime();

writer.commit();

int numIndexed = writer.maxDoc();

System.out.println("Indexing file(s) took " + (end - start) + "

miliseconds");

System.out.println("Index contains " + numIndexed + "

file(s)");

}

Page 45: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

41

//recursive method that calls itself when it finds a directory

private static void indexDirectory (IndexWriter writer, File dir)

throws IOException, SAXException, Exception {

if (dir.getName().endsWith(".xml")) {

indexFile (writer, dir);

} else {

File[] files = dir.listFiles();

for (File f : files) {

if (f.isDirectory()) {

indexDirectory (writer, f);

} else if (f.getName().endsWith(".xml")) {

indexFile (writer, f);

}

}

}

}

//method to index a file using Lucene

private static void indexFile (IndexWriter writer, File f) throws

IOException, SAXException, FileNotFoundException,

ClassNotFoundException {

if (f.isHidden() || !f.exists() || !f.canRead()) {

return;

}

System.out.println("Indexing " + f.getCanonicalPath());

Digester digester = new Digester();

digester.setValidating(false);

digester.addObjectCreate ("newsitem", NewsItem.class);

digester.addObjectCreate ("newsitem/text", Text.class);

digester.addBeanPropertySetter("newsitem/text/p", "p");

digester.addSetNext("newsitem/text", "setText");

digester.addBeanPropertySetter("newsitem/title", "title");

NewsItem newsItem = (NewsItem) digester.parse(f);

Document doc = new Document();

final FieldType ft = new FieldType();

final FieldType ft2 = new FieldType();

ft.setStored(true);

ft.setStoreTermVectors(true);

ft.setTokenized(true);

ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AN

D_OFFSETS);

ft2.setStored(true);

ft2.setStoreTermVectors(true);

ft2.setTokenized(true);

ft2.setIndexOptions(IndexOptions.DOCS);

Field titleField = new Field ("title", newsItem.getTitle(),

ft);

doc.add(titleField);

Field contentField = new Field ("text",

newsItem.getText().getP(), ft);

doc.add(contentField);

Field nameField = new Field ("name", f.getName(), ft2);

doc.add(nameField);

writer.addDocument(doc);

int docId = writer.numDocs()-1;

tempMap.put(f.getAbsolutePath(),docId);

System.out.println(docId);

//pretty much slower with committing after every file

//writer.commit();

}

Page 46: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

42

public static void removeNewsItem (String absolutePath) throws

IOException, ParseException, Exception {

Directory indexDir = getIndexDir();

IndexReader reader = DirectoryReader.open(indexDir);

IndexSearcher is = new IndexSearcher (reader);

Path path = Paths.get (absolutePath);

String name = path.getFileName().toString();

System.out.println (name);

Query query = new QueryParser("name", new

StandardAnalyzer()).parse(name);

TopDocs docs = is.search(query, 1);

ScoreDoc[] hits = docs.scoreDocs;

System.out.println (hits.length);

reader.close();

IndexWriter writer = new IndexWriter (indexDir, config);

if (hits.length == 1) {

int docId = hits[0].doc;

System.out.println("Deleted document id " + docId);

writer.deleteDocuments (query);

writer.commit();

System.out.println(writer.maxDoc());

writer.close();

//Method of MatrixGeneratorWithTopDocs class

removingNewsItem (docId);

removeRatingsForDeletedNewsItem (absolutePath);

//Removing from HashMap

HashMap <String,Integer> map = getIndexMap();

map.remove(absolutePath);

setIndexMap (map);

} else {

System.out.println ("There's no hits");

}

}

public static Directory getIndexDir () throws IOException {

String indexPath = "/home/joe/recs/index";

Directory indexDir = FSDirectory.open(Paths.get(indexPath));

return indexDir;

}

Page 47: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

43

public static HashMap<String,Integer> getIndexMap() throws

FileNotFoundException, IOException, ClassNotFoundException {

ObjectInputStream in = new ObjectInputStream(new

FileInputStream("indexMapOutput"));

HashMap <String,Integer> map = (HashMap<String, Integer>)

in.readObject();

return map;

}

public static void setIndexMap (HashMap <String, Integer> outputMap)

throws IOException {

ObjectOutputStream out = new ObjectOutputStream ( new

FileOutputStream ("indexMapOutput"));

out.writeObject(outputMap);

out.close();

}

}

Page 48: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

44

package recs.parse;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import org.apache.lucene.analysis.core.StopAnalyzer;

import org.apache.lucene.index.DirectoryReader;

import org.apache.lucene.index.IndexReader;

import org.apache.lucene.queryparser.classic.ParseException;

import org.apache.lucene.queryparser.classic.QueryParser;

import org.apache.lucene.search.BooleanQuery;

import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.search.Query;

import org.apache.lucene.search.TopDocs;

import org.apache.lucene.store.Directory;

import static recs.parse.Indexer.getIndexDir;

/**

*

* @author joe

*/

public class MatrixGeneratorWithTopDocs {

public static void main (String[] args) throws Exception {

//initialGenerator (100);

//have to call this method after indexind new newsitem

//addingNewsItem ();

//have to call this method after removing newsitem from index

//removingNewsItem (20999);

}

//getting indexPath and number TopDocs for every item (number of

columns in matrix)

public static void initialGenerator (int num) throws Exception {

int i,j;

Directory fsDir = getIndexDir();

IndexReader reader = DirectoryReader.open(fsDir);

IndexSearcher is = new IndexSearcher (reader);

float [][] similarityValuesMatrix = new

float[reader.numDocs()][num];

int [][] similarityIndexesMatrix = new

int[reader.numDocs()][num];

BooleanQuery.setMaxClauseCount(10000);

for (i=0; i<reader.numDocs(); i++) {

TopDocs docs = getTopDocs (reader, is, i, num);

for (j=1; j<docs.scoreDocs.length; j++) {

System.out.println (docs.scoreDocs[j].doc+"

"+docs.scoreDocs[j].score);

similarityIndexesMatrix[i][j-

1]=docs.scoreDocs[j].doc;

similarityValuesMatrix[i][j-

1]=docs.scoreDocs[j].score;

}

}

outputtingMatrix (similarityIndexesMatrix,

similarityValuesMatrix);

}

Page 49: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

45

// need to INDEX Newsitem first so numDocs IS ALREADY BIGGER FOR ONE

public static void addingNewsItem () throws Exception {

int i,j,num;

Directory fsDir = getIndexDir();

IndexReader reader = DirectoryReader.open(fsDir);

IndexSearcher is = new IndexSearcher (reader);

int [][] inIndexes = getSimilarityIndexesOutput();

float [][] inValues = getSimilarityValuesOutput();

//number od TopDocs in a row (number of columns)

num = inIndexes[0].length;

int [][] similarityIndexesMatrix = new

int[reader.numDocs()][num];

float [][] similarityValuesMatrix = new

float[reader.numDocs()][num];

for (i=0; i<reader.numDocs()-1; i++) {

for (j=0; j<num; j++) {

similarityIndexesMatrix [i][j] = inIndexes[i][j];

similarityValuesMatrix[i][j]= inValues[i][j];

}

}

//got numDocs() documents in index, from 0 to numDocs()-1

TopDocs docs = getTopDocs (reader, is, reader.numDocs()-1,num);

for (j=1; j<docs.scoreDocs.length; j++) {

System.out.println (docs.scoreDocs[j].doc+"

"+docs.scoreDocs[j].score);

similarityIndexesMatrix [reader.numDocs()-1][j-1] =

docs.scoreDocs[j].doc;

similarityValuesMatrix [reader.numDocs()-1][j-1] =

docs.scoreDocs[j].score;

}

outputtingMatrix (similarityIndexesMatrix,

similarityValuesMatrix);

}

Page 50: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

46

//need to remove Newsitem from index first so numDocs IS ALREADY LESS

FOR ONE

public static void removingNewsItem (int docId) throws Exception {

int i,j,num;

Directory fsDir = getIndexDir();

IndexReader reader = DirectoryReader.open(fsDir);

int [][] inIndexes = getSimilarityIndexesOutput();

float [][] inValues = getSimilarityValuesOutput();

//number od TopDocs in a row (number of columns)

num = inIndexes[0].length;

int [][] similarityIndexesMatrix = new

int[reader.numDocs()][num];

float [][] similarityValuesMatrix = new

float[reader.numDocs()][num];

//removing element from matrix with checking if element is in

last row or somewhere earlier

System.out.println (reader.numDocs());

if (docId == reader.numDocs()) {

for (i=0; i<reader.numDocs(); i++) {

for (j=0; j<num; j++) {

similarityIndexesMatrix [i][j] = inIndexes

[i][j];

similarityValuesMatrix [i][j] = inValues

[i][j];

}

}

} else {

for (i=docId; i<reader.numDocs(); i++) {

for (j=0; j<num; j++) {

similarityIndexesMatrix [i][j] =

inIndexes[i+1][j];

similarityValuesMatrix[i][j]=

inValues[i+1][j];

}

}

}

outputtingMatrix (similarityIndexesMatrix,

similarityValuesMatrix);

}

Page 51: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

47

private static TopDocs getTopDocs (IndexReader reader, IndexSearcher

is, int i, int num) throws IOException, ParseException {

String q = reader.document(i).getField("text").stringValue();

TopDocs docs;

int solution;

if (q.length()!=0) {

Query query = new QueryParser("text", new

StopAnalyzer()).parse(QueryParser.escape(q));

docs = is.search(query, num+1);

System.out.println (i+" "+docs.scoreDocs.length);

solution = 1;

} else {

q =

reader.document(i).getField("title").stringValue();

Query query = new QueryParser("title", new

StopAnalyzer()).parse(QueryParser.escape(q));

docs = is.search(query, num+1);

System.out.println (i+" "+docs.scoreDocs.length);

solution = 2;

}

if (docs.scoreDocs.length<(num+1) && solution == 1) {

q =

reader.document(i).getField("title").stringValue();

Query query = new QueryParser("title", new

StopAnalyzer()).parse(QueryParser.escape(q));

docs = is.search(query, num+1);

System.out.println (i+" "+docs.scoreDocs.length);

}

return docs;

}

private static void outputtingMatrix (int[][]

similarityIndexesMatrix, float[][] similarityValuesMatrix) throws

IOException {

ObjectOutputStream out = new ObjectOutputStream ( new

FileOutputStream ("similarityIndexesOutput"));

out.writeObject(similarityIndexesMatrix);

out.close();

ObjectOutputStream out1 = new ObjectOutputStream ( new

FileOutputStream ("similarityValuesOutput"));

out1.writeObject(similarityValuesMatrix);

out1.close();

}

Page 52: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

48

public static int [][] getSimilarityIndexesOutput() throws

FileNotFoundException, IOException, ClassNotFoundException {

ObjectInputStream in = new ObjectInputStream(new

FileInputStream("similarityIndexesOutput"));

int [][] inIndexes = (int [][]) in.readObject();

in.close();

return inIndexes;

}

public static float [][] getSimilarityValuesOutput() throws

IOException, ClassNotFoundException {

ObjectInputStream in = new ObjectInputStream(new

FileInputStream("similarityValuesOutput"));

float [][] inValues = (float [][]) in.readObject();

in.close();

return inValues;

}

}

Page 53: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

49

package recs.mahout.itemsimilarity;

import com.google.common.base.Preconditions;

import java.util.Collection;

import org.apache.mahout.cf.taste.common.Refreshable;

import org.apache.mahout.cf.taste.common.TasteException;

import org.apache.mahout.cf.taste.impl.common.RefreshHelper;

import org.apache.mahout.cf.taste.similarity.ItemSimilarity;

/**

*

* @author joe

*/

public final class ItemSimilarityFromTopDocsMatrix implements

ItemSimilarity{

private final int[][] matrixIndexes;

private final float[][] matrixValues;

private final RefreshHelper refreshHelper;

public ItemSimilarityFromTopDocsMatrix (int [][] matrixIndexes,

float[][] matrixValues) {

Preconditions.checkArgument(matrixIndexes != null,

"matrixIndexes is null");

Preconditions.checkArgument(matrixValues != null,

"matrixValues is null");

this.matrixIndexes = matrixIndexes;

this.matrixValues = matrixValues;

this.refreshHelper = new RefreshHelper(null);

}

public int[][] getMatrixIndexes(){

return matrixIndexes;

}

public float[][] getMatrixValues(){

return matrixValues;

}

@Override

public double itemSimilarity(long itemID1, long itemID2) throws

TasteException {

int [][] matrixIndexesLocal = getMatrixIndexes();

float [][] matrixValuesLocal = getMatrixValues();

int [] matrixIndexesRow = matrixIndexesLocal[(int)itemID1-1];

boolean contains = false;

int ind = 0;

for (int i=0; i<matrixIndexesRow.length; i++) {

if (matrixIndexesRow[i]==(((int)itemID2)-1)) {

ind = i;

contains = true;

}

}

if (contains) {

//int index =

Arrays.asList(matrixIndexesRow).indexOf((int)itemID2-1);

return matrixValuesLocal[((int)itemID1)-1][ind];

} else {

return 0;

}

}

Page 54: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

50

@Override

public double[] itemSimilarities(long itemID1, long[] itemID2s)

throws TasteException {

int [][] matrixIndexesLocal = getMatrixIndexes();

float [][] matrixValuesLocal = getMatrixValues();

int length = itemID2s.length;

double[] result = new double[length];

int [] matrixIndexesRow = matrixIndexesLocal[(int)itemID1-1];

int ind = 0;

boolean contains;

for (int i=0; i<length; i++) {

contains = false;

for (int j=0; i<matrixIndexesRow.length; i++) {

if (matrixIndexesRow[i]==(((int)itemID2s[j])-1)) {

ind = i;

contains = true;

}

}

if (contains) {

//int index =

Arrays.asList(matrixIndexesRow).indexOf((int)itemID2-1);

result[i] = matrixValuesLocal[((int)itemID1)-

1][ind];

} else {

result[i] = 0;

}

}

return result;

}

@Override

public long[] allSimilarItemIDs(long itemID) throws TasteException {

//throw new UnsupportedOperationException("Not supported

yet."); //To change body of generated methods, choose Tools |

Templates.

long[] result = null;

result = null;

int [][] matrixIndexesLocal = getMatrixIndexes();

int [] middleResult = matrixIndexesLocal[(int)itemID-1];

for (int i=0; i<middleResult.length; i++) {

long help = new Long (middleResult[i]);

result[i] = help;

}

return result;

}

@Override

public void refresh(Collection<Refreshable> alreadyRefreshed) {

refreshHelper.refresh(alreadyRefreshed);//throw new

UnsupportedOperationException("Not supported yet."); //To change body

of generated methods, choose Tools | Templates.

}

}

Page 55: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

51

package recs.parse;

import java.io.IOException;

import java.util.HashMap;

import java.util.HashSet;

import java.util.Set;

import org.apache.lucene.queryparser.classic.ParseException;

import static recs.parse.Indexer.getIndexMap;

import static

recs.parse.MatrixGeneratorWithTopDocs.getSimilarityIndexesOutput;

/**

*

* @author joe

*/

public class ItemRecommenderFromTopDocsMatrix {

public static void main (String[] args) throws Exception {

//getTopNRecommendationsFromMatrix

("/home/joe/recs/2286newsML.xml", 6);

}

public static Set<String> getTopNRecommendationsFromMatrix

(String absolutePath, int N) throws IOException,

ClassNotFoundException, ParseException {

int numOfRecommends = N;

int [][] inMatrix = getSimilarityIndexesOutput();

HashMap <String,Integer> indexMap = getIndexMap();

int itemId = indexMap.get(absolutePath);

Set<String> shouldRecommend = new HashSet<>();

for (int j=0; j< numOfRecommends; j++) {

for (String absPath : indexMap.keySet()) {

int recId = inMatrix[itemId][j];

if (indexMap.get(absPath).equals(recId)) {

shouldRecommend.add(absPath);

}

}

}

System.out.println (shouldRecommend.toString());

return (shouldRecommend);

}

}

Page 56: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

52

package recs.parse;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.util.HashMap;

import java.util.HashSet;

import java.util.List;

import java.util.Set;

import org.apache.lucene.queryparser.classic.ParseException;

import org.apache.mahout.cf.taste.common.TasteException;

import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;

import

org.apache.mahout.cf.taste.impl.neighborhood.ThresholdUserNeighborhoo

d;

import

org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommend

er;

import

org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommend

er;

import

org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilari

ty;

import org.apache.mahout.cf.taste.model.DataModel;

import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;

import org.apache.mahout.cf.taste.recommender.RecommendedItem;

import org.apache.mahout.cf.taste.recommender.UserBasedRecommender;

import org.apache.mahout.cf.taste.similarity.ItemSimilarity;

import org.apache.mahout.cf.taste.similarity.UserSimilarity;

import static recs.basics.DataModelGenerator.getDataModelFileName;

import static recs.basics.DataModelGenerator.getDataModelFullPath;

import recs.mahout.itemsimilarity.ItemSimilarityFromTopDocsMatrix;

import static recs.parse.Indexer.getIndexMap;

import static

recs.parse.ItemRecommenderFromTopDocsMatrix.getTopNRecommendationsFro

mMatrix;

import static

recs.parse.MatrixGeneratorWithTopDocs.getSimilarityIndexesOutput;

import static

recs.parse.MatrixGeneratorWithTopDocs.getSimilarityValuesOutput;

/**

*

* @author joe

*/

public class ItemRecommenderFromDataModelTopDocs {

public static void main (String[] args) throws Exception {

//getTopNRecommendations ("/home/joe/recs/2286newsML.xml",

6);

//getTopNRecommendations (50,6);

//getTopNRecommendations ("/home/joe/recs/2286newsML.xml",

50, 6);

}

Page 57: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

53

public static Set<String> getTopNRecommendations (String

absolutePath, int N) throws IOException, ClassNotFoundException,

ParseException {

HashMap <String,Integer> indexMap = getIndexMap();

int itemId = indexMap.get(absolutePath);

Set<String> shouldRecommend = new HashSet<>();

DataModel dm = new FileDataModel (new

File(getDataModelFileName()));

int [][] inIndexes = getSimilarityIndexesOutput();

float [][] inValues = getSimilarityValuesOutput();

ItemSimilarity sim2 = new

ItemSimilarityFromTopDocsMatrix(inIndexes, inValues);

GenericItemBasedRecommender recommender = new

GenericItemBasedRecommender (dm, sim2);

List<RecommendedItem> recommendations;

try {

recommendations = recommender.mostSimilarItems(itemId+1,

N);

for (RecommendedItem recommendation : recommendations) {

for (String absPath : indexMap.keySet()) {

int recId = (int)

(recommendation.getItemID());

recId = recId-1;

if (indexMap.get(absPath).equals(recId)) {

System.out.println (recId);

System.out.println (absPath);

shouldRecommend.add(absPath);

}

}

}

if (!shouldRecommend.isEmpty()) {

System.out.println (shouldRecommend.toString());

return (shouldRecommend);

} else {

shouldRecommend = getTopNRecommendationsFromMatrix

(absolutePath, N);

return (shouldRecommend);

}

} catch (TasteException ex) {

System.out.println (ex.toString());

shouldRecommend = getTopNRecommendationsFromMatrix

(absolutePath, N);

return (shouldRecommend);

}

}

Page 58: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

54

public static Set<String> getTopNRecommendations (String

absolutePath, int userId, int N) throws IOException,

ClassNotFoundException, ParseException {

HashMap <String,Integer> indexMap = getIndexMap();

int itemId = indexMap.get(absolutePath);

Set<String> shouldRecommend = new HashSet<>();

DataModel dm = new FileDataModel (new

File(getDataModelFileName()));

int [][] inIndexes = getSimilarityIndexesOutput();

float [][] inValues = getSimilarityValuesOutput();

ItemSimilarity sim2 = new

ItemSimilarityFromTopDocsMatrix(inIndexes, inValues);

GenericItemBasedRecommender recommender = new

GenericItemBasedRecommender (dm, sim2);

List<RecommendedItem> recommendations;

try {

recommendations = recommender.recommend(userId, N);

for (RecommendedItem recommendation : recommendations) {

for (String absPath : indexMap.keySet()) {

int recId = (int)

(recommendation.getItemID());

recId = recId-1;

if (indexMap.get(absPath).equals(recId)) {

System.out.println (recId);

System.out.println (absPath);

shouldRecommend.add(absPath);

}

}

}

if (!shouldRecommend.isEmpty()) {

System.out.println (shouldRecommend.toString());

return (shouldRecommend);

} else {

shouldRecommend = getTopNRecommendationsFromMatrix

(absolutePath, N);

return (shouldRecommend);

}

} catch (TasteException ex) {

System.out.println (ex.toString());

shouldRecommend = getTopNRecommendationsFromMatrix

(absolutePath, N);

return (shouldRecommend);

}

}

Page 59: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

55

public static Set<String> getTopNRecommendations (int userId, int N)

throws IOException, FileNotFoundException, ClassNotFoundException,

TasteException, ParseException{

HashMap <String,Integer> indexMap = getIndexMap();

Set<String> shouldRecommend = new HashSet<>();

DataModel model = new FileDataModel(new

File(getDataModelFullPath()));

UserSimilarity similarity = new

PearsonCorrelationSimilarity(model);

UserNeighborhood neighborhood = new

ThresholdUserNeighborhood(0.2, similarity, model);

UserBasedRecommender recommender = new

GenericUserBasedRecommender(model, neighborhood, similarity);

List<RecommendedItem> recommendations;

try {

recommendations = recommender.recommend(userId, N);

for (RecommendedItem recommendation : recommendations) {

for (String absPath : indexMap.keySet()) {

int recId = (int)

(recommendation.getItemID());

recId = recId-1;

if (indexMap.get(absPath).equals(recId)) {

System.out.println (recId);

System.out.println (absPath);

shouldRecommend.add(absPath);

}

}

}

System.out.println (shouldRecommend.toString());

return shouldRecommend;

} catch (TasteException ex) {

System.out.println (ex.toString());

System.out.println (shouldRecommend.toString());

return shouldRecommend;

}

}

}

Page 60: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

56

package recs.basics;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileWriter;

import java.io.IOException;

import java.io.PrintWriter;

import java.io.RandomAccessFile;

import java.io.UnsupportedEncodingException;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.LinkedHashSet;

import java.util.Set;

import java.util.concurrent.ThreadLocalRandom;

import org.apache.commons.io.FileUtils;

import static recs.parse.Indexer.getIndexMap;

/*

* To change this license header, choose License Headers in Project

Properties.

* To change this template file, choose Tools | Templates

* and open the template in the editor.

*/

/**

*

* @author joe

*/

public class DataModelGenerator {

public static void main (String[] args) throws

FileNotFoundException, UnsupportedEncodingException, IOException,

ClassNotFoundException {

initialModel ();

//rateNewsItem (1111, "/home/joe/recs/2286newsML.xml", 1111);

//rateNewsItem (1111, "/home/joe/recs/2286newsML.xml", 1112);

//rateNewsItem (1111, "/home/joe/recs/2286newsML.xml", 1112);

//removeRatingsForDeletedNewsItem

("/home/joe/recs/2286newsML.xml");

}

Page 61: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

57

//creatnig initial random dataModel.csv file

public static void initialModel () throws FileNotFoundException,

UnsupportedEncodingException {

try (PrintWriter writer = new

PrintWriter(getDataModelFileName(), "UTF-8")) {

int n = 21000;

for (int u=1; u<51; u++) {

ArrayList<Integer> arrayRandom = new

ArrayList<>(100);

for (int i=0; i<1030; i++)

{

arrayRandom.add(ThreadLocalRandom.current().nextInt(1, n

+ 1));

}

Set <Integer> set = new LinkedHashSet<>

(arrayRandom);

Object[] objRandoms = set.toArray();

for (Object objRandom : objRandoms) {

if (u==50 &&

objRandom==objRandoms[objRandoms.length-1]) {

writer.print(u+"," + objRandom + "," +

ThreadLocalRandom.current().nextInt(1,6));

} else {

writer.println(u+"," + objRandom + ","

+ ThreadLocalRandom.current().nextInt(1,6));

}

}

}

} catch (FileNotFoundException | UnsupportedEncodingException

e) {

System.out.println (e.toString());

}

}

//adding new line into dataModel.csv file

public static void rateNewsItem (int userId, String absolutePath, int

rating) throws IOException, FileNotFoundException,

ClassNotFoundException {

String csvFile = getDataModelFullPath();

BufferedWriter bw = null;

Path path = Paths.get (absolutePath);

String name = path.getFileName().toString();

HashMap <String,Integer> indexMap = getIndexMap();

int newsItemId = indexMap.get(name);

//file writer with append parameter setted to true

try {

bw = new BufferedWriter(new FileWriter(csvFile, true));

bw.append("\n" + userId + "," + newsItemId + "," +

rating);

bw.close();

} catch (IOException e) {

System.out.println (e.toString());

System.out.println ("No such file :" + csvFile);

}

}

Page 62: WEB-PORTALIMA · 2016. 9. 1. · 2 Osnovne tehnike preporučivanja sadržaja 2.1 Preporuke prema sličnosti sadržaja (engl. Content-based) Najosnovniji pristup pri stvaranju preporuka

58

//removing lines of deleted newsitem in dataModel

public static void removeRatingsForDeletedNewsItem (String

absolutePath) throws IOException, FileNotFoundException,

ClassNotFoundException {

File dataModel = new File (getDataModelFullPath());

String fileContents = FileUtils.readFileToString(dataModel);

String [] fileContentLines =

fileContents.split(System.lineSeparator());

emptyFile (dataModel);

Path path = Paths.get (absolutePath);

HashMap <String,Integer> indexMap = getIndexMap();

int newsItemId = indexMap.get(absolutePath);

StringBuilder newContent = new StringBuilder ();

for (String fileContentLine : fileContentLines) {

if (fileContentLine.contains(","+newsItemId+",")) {

continue;

}

newContent.append(fileContentLine +

System.lineSeparator());

}

FileUtils.writeStringToFile (dataModel,

newContent.toString().trim());

}

//help method for removing files

private static void emptyFile (File file) throws IOException {

try (RandomAccessFile randomAccessFile = new RandomAccessFile

(file, "rw")) {

randomAccessFile.setLength(0);

randomAccessFile.close();

} catch(IOException e) {

System.out.println(e.toString());

System.out.println ("No such file: " + file);

}

}

public static String getDataModelFullPath () {

String fullPath = "/home/joe/recs/dataModel.csv";

return fullPath;

}

public static String getDataModelFileName () {

String fileName = "dataModel.csv";

return fileName;

}

}