Priporočilni sistem: podatki in osnovno napovedovanje
Podatki
V navodilih nalog bomo uporabljali izvedene movielens podatke. Za razliko od originalne podatkovne množice, ta vsebuje še precej več kot pa samo ocene. Opis podatkov je v README datoteki. Za svojo seminarsko lahko uporabite poljubne dovolj velike podatke.
Branje ocen (6)
Napišite razred (npr. z imenom UserItemData
), v katerem boste hranili prebrane podatke. Predlagam, da imate v konstruktorju razreda argument path
(pot do datoteke) in tri opcijske argumente: from_date
(od katerega datuma naprej naj bere podatke), to_date
(do katerega datuma naj prebere podatke) in min_ratings
(minimalno število ocen, ki jih mora imeti film). V razred dodajte še metodo, ki vam izpiše, koliko ocen je prebral. Predlagam, da dodate še metodi, ki prebrane podatke shrani oz. prebere s pomočjo knjižnice pickle
.
Npr., naslednji program:
uim = UserItemData('data/user_ratedmovies.dat') print(uim.nratings()) uim = UserItemData('data/user_ratedmovies.dat', start_date = '12.1.2007', end_date='16.2.2008', min_ratings=100) print(uim.nratings())izpiše:
855598 73584
Branje filmov (6)
Napišite razred, ki prebere datoteko s filmi in ima metodo get_title(movieID)
, ki za dani ID filma vrne njegov naslov. Primer:
md = MovieData('data/movies.dat') print(md.get_title(1))Rezultat:
Toy story
Prediktor
Z besedo "prediktor" bomo označevali razrede, ki za določenega uporabnika na nek način ocenijo, s kakšno vrednostjo bi ta uporabnik ocenil filme oz. produkte, ki jih ima na voljo. Ti razredi bodo imeli metodo fit(self, X)
, kjer je X
tipa UserItemData
, in metodo predict(self, user_id)
, kjer je user_id
ID uporabnika. Metodo fit
bomo uporabljali za učenje modela, predict
pa za izračun priporočenih vrednosti za podanega uporabnika. Priporočene vrednosti so lahko npr. vrnjene kot slovar.
Naključni prediktor (6)
Napišite razred RandomPredictor
, ki v konstruktorju sprejme minimalno in maksimalno oceno, metoda predict
pa vrne naključno vrednost (med min in max) za vsak produkt.
md = MovieData('data/movies.dat')
uim = UserItemData('data/user_ratedmovies.dat')
rp = RandomPredictor(1, 5)
rp.fit(uim)
pred = rp.predict(78)
print(type(pred))
items = [1, 3, 20, 50, 100]
for item in items:
print("Film: {}, ocena: {}".format(md.get_title(item), pred[item]))
Rezultat:
<class 'dict'> Film: Toy story, ocena: 5 Film: Grumpy Old Men, ocena: 4 Film: Money Train, ocena: 5 Film: The Usual Suspects, ocena: 5 Film: City Hall, ocena: 3
Priporočanje (6)
Napišite razred Recommender
. Razred naj v konstruktorju sprejme prediktor in ima dve metodi: fit(self, X)
in recommend(self, userID, n=10, rec_seen=True)
. Prva ima enako funkcijo, kot pri prediktorju, druga pa vrne urejen seznam priporočenih produktov za uporabnika userID
. Parameter n
določa število priporočenih filmov, z rec_seen
pa določimo ali hočemo med priporočenimi tudi že gledane (tiste, ki jim je uporabnik že dal oceno) ali ne.
md = MovieData('data/movies.dat')
uim = UserItemData('data/user_ratedmovies.dat')
rp = RandomPredictor(1, 5)
rec = Recommender(rp)
rec.fit(uim)
rec_items = rec.recommend(78, n=5, rec_seen=False)
for idmovie, val in rec_items:
print("Film: {}, ocena: {}".format(md.get_title(idmovie), val))
Rezultat:
Film: Toy story, ocena: 5
Film: Sudden Death, ocena: 5
Film: Dracula: Dead and Loving It, ocena: 5
Film: Money Train, ocena: 5
Film: It Takes Two, ocena: 5
Napovedovanje s povprečjem (6)
Napišite razred AveragePredictor
, ki v konstruktorju sprejme parameter b
, kjer b >= 0
. V metodi fit
izračunajte povprečje za vsak film po formuli avg = (vs + b * g_avg) / (n + b)
, kjer so:
-
vs
je vsota vseh ocen za ta film, -
n
je število ocen, ki jih je ta film dobil, -
g_avg
je povprečje čez vse filme, -
b
je parameter formule za povprečje. Če jeb=0
, gre za navadno povprečje.
Če v recommenderju uporabimo AveragePredictor(b=0) in ostalo enako kot v prejšnjem razdelku
, dobimo:
Film: Sonnenallee, ocena: 5.0
Film: Vals Im Bashir, ocena: 5.0
Film: Britannia Hospital, ocena: 5.0
Film: Il mio viaggio in Italia, ocena: 5.0
Film: Shu dan long wei, ocena: 5.0
Če pa uporabimo AveragePredictor(b=100)
, se vrednosti spremenijo:
Film: The Usual Suspects, ocena: 4.225944245560473
Film: The Godfather: Part II, ocena: 4.146907937910189
Film: Cidade de Deus, ocena: 4.116538340205236
Film: The Dark Knight, ocena: 4.10413904093503
Film: 12 Angry Men, ocena: 4.103639627096175
Priporočanje najbolj gledanih filmov (6)
Napišite prediktor ViewsPredictor
, ki za vsak film vrne število ogledov posameznega filma. To je priporočanje najbolj gledano . Za naš primer boste dobili naslednje:
Film: The Lord of the Rings: The Fellowship of the Ring, ocena: 1576
Film: The Lord of the Rings: The Two Towers, ocena: 1528
Film: The Lord of the Rings: The Return of the King, ocena: 1457
Film: The Silence of the Lambs, ocena: 1431
Film: Shrek, ocena: 1404
Priporočanje kontroverznih filmov
Kako bi ocenili kontroverznost (produkti, ki imajo veliko dobrih in veliko slabih ocen) ? Ali je "nepersonaliziran" način priporočanja primeren za take produkte? Napišite prediktor za najbolj kontroverzne produkte, kjer je film lahko kontroverzen, če ima vsaj n
ocen. Za mero uporabite standardno deviacijo ocen. Če mora film imeti vsaj 100 ocen, dobimo:
md = MovieData('data/movies.dat')
uim = UserItemData('data/user_ratedmovies.dat')
rp = STDPredictor(100)
rec = Recommender(rp)
rec.fit(uim)
rec_items = rec.recommend(78, n=5, rec_seen=False)
for idmovie, val in rec_items:
print("Film: {}, ocena: {}".format(md.get_title(idmovie), val))
Film: Plan 9 from Outer Space, ocena: 1.3449520951495717
Film: The Passion of the Christ, ocena: 1.281493459525735
Film: The Texas Chainsaw Massacre, ocena: 1.235349321908819
Film: Jackass Number Two, ocena: 1.2189769976366684
Film: White Chicks, ocena: 1.1899581424297319