Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Задача 2 Problem 2 (1 / 2)
- Да се напише функција која во зависност од бројот на рангирани филмови на корисникот ќе одбира начинот на препорачување - дали item-based или user-based. Функцијата треба да прима аргумент име на корисникот и бројот n од стандарден влез. Ако бројот на рангирани филмови на корисникот е помал од n да препорачува на со item-based начин, а ако е поголем или еднаков на n да препорачува на user-based начин. На излез да се печати одбраниот начин (user-based или item-based), и во вториот ред да се испечати листа од препорачани филмови која ги содржи само имињата сортирани во растечки (азбучен) редослед.
- oceniPoKorisnici = {
- 'Lisa Rose': {'Catch Me If You Can': 3.0, 'Snakes on a Plane': 3.5, 'Superman Returns': 3.5,
- 'You, Me and Dupree': 2.5, 'The Night Listener': 3.0, 'Snitch': 3.0},
- 'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 'Just My Luck': 1.5, 'The Night Listener': 3.0,
- 'You, Me and Dupree': 3.5},
- 'Michael Phillips': {'Catch Me If You Can': 2.5, 'Lady in the Water': 2.5, 'Superman Returns': 3.5,
- 'The Night Listener': 4.0, 'Snitch': 2.0},
- 'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 'The Night Listener': 4.5, 'Superman Returns': 4.0,
- 'You, Me and Dupree': 2.5},
- 'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 'Just My Luck': 2.0, 'Superman Returns': 3.0,
- 'You, Me and Dupree': 2.0},
- 'Jack Matthews': {'Catch Me If You Can': 4.5, 'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,
- 'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5, 'Snitch': 4.5},
- 'Toby': {'Snakes on a Plane': 4.5, 'Snitch': 5.0},
- 'Michelle Nichols': {'Just My Luck': 1.0, 'The Night Listener': 4.5, 'You, Me and Dupree': 3.5,
- 'Catch Me If You Can': 2.5, 'Snakes on a Plane': 3.0},
- 'Gary Coleman': {'Lady in the Water': 1.0, 'Catch Me If You Can': 1.5, 'Superman Returns': 1.5,
- 'You, Me and Dupree': 2.0},
- 'Larry': {'Lady in the Water': 3.0, 'Just My Luck': 3.5, 'Snitch': 1.5, 'The Night Listener': 3.5}
- }
- from math import sqrt
- import json
- # Vrakja merka za slicnost bazirana na rastojanieto za person1 i person2
- def sim_distance(oceni, person1, person2):
- # Se pravi lista na zaednicki predmeti (filmovi)
- zaednicki = {}
- for item in oceni[person1].keys():
- if item in oceni[person2]:
- zaednicki[item] = 1
- # ako nemaat zaednicki rejtinzi, vrati 0
- if len(zaednicki) == 0: return 0
- # Soberi gi kvadratite na zaednickite razliki
- sum_of_squares = sum([pow(oceni[person1][item] - oceni[person2][item], 2)
- for item in oceni[person1] if item in oceni[person2]])
- return 1 / (1 + sqrt(sum_of_squares))
- # return 1/(1+(sum_of_squares))
- # Go vrakja koeficientot na Pearsonova korelacija pomegu p1 i p2 (licnost 1 i licnost 2)
- # Vrednostite se pomegu -1 i 1
- def sim_pearson(oceni,p1,p2):
- # Se kreira recnik vo koj ke se cuvaat predmetite (filmovi) koi se oceneti od dvajcata
- # Vo recnikot ni se vazni samo klucevite za da gi cuvame iminjata na filmovite koi se zaednicki, a vrednostite ne ni se vazni
- zaednicki={}
- for item in oceni[p1]:
- if item in oceni[p2]: zaednicki[item]=1
- # Se presmetuva brojot na predmeti oceneti od dvajcata
- n=len(zaednicki)
- # Ako nemaat zaednicki predmeti vrati korelacija 0
- if n==0: return 0
- # Soberi gi zaednickite oceni (rejtinzi) za sekoja licnost posebno
- sum1=sum([oceni[p1][it] for it in zaednicki])
- sum2=sum([oceni[p2][it] for it in zaednicki])
- # Soberi gi kvadratite od zaednickite oceni (rejtinzi) za sekoja licnost posebno
- sum1Sq=sum([pow(oceni[p1][it],2) for it in zaednicki])
- sum2Sq=sum([pow(oceni[p2][it],2) for it in zaednicki])
- # Soberi gi proizvodite od ocenite na dvete licnosti
- pSum=sum([oceni[p1][it]*oceni[p2][it] for it in zaednicki])
- # Presmetaj go koeficientot na korelacija
- num=pSum-(sum1*sum2/n)
- den=sqrt((sum1Sq-pow(sum1,2)/n)*(sum2Sq-pow(sum2,2)/n))
- if den==0: return 0
- r=num/den
- return r
- # Gi transformira rejtinzite taka sto klucevi ke bidat filmovite a vrednost lista od rejtinzi od sekoj korisnik
- def transformPrefs(oceni):
- result={}
- for person in oceni:
- for item in oceni[person]:
- result.setdefault(item,{})
- # Zameni gi mestata na licnosta i predmetot
- result[item][person]=oceni[person][item]
- return result
- # Gi vrakja najslicnite n korisnici na daden korisnik
- # Brojot na rezultati (n) i funkcijata za slicnost se opcionalni parametri
- def topMatches(oceni,person,n=5, similarity=sim_pearson):
- scores=[(similarity(oceni,person,other),other)
- for other in oceni if other!=person]
- # Se sortira listata vo rastecki redosled
- scores.sort( )
- # Se prevrtuva za najslicnite (so najgolema vrednost) da bidat prvi
- scores.reverse( )
- return scores[0:n]
- # Gi vrakja preporakite za daden korisnik person so
- # koristenje na tezinski prosek na ocenite od drugite korisnici
- def getUserBasedRecomendations(oceni, person, similarity=sim_pearson):
- totals = {}
- simSums = {}
- for other in oceni:
- # Za da ne se sporeduva so samiot sebe
- if other == person: continue
- sim = similarity(oceni, person, other)
- # ne se zemaat vo predvid rezultati <= 0
- if sim <= 0: continue
- for item in oceni[other]:
- # za tekovniot korisnik gi zemame samo filmovite sto gi nemame veke gledano
- if item not in oceni[person] or oceni[person][item] == 0:
- # similarity * Score (Slicnost * Ocena)
- totals.setdefault(item, 0)
- totals[item] += oceni[other][item] * sim
- # Sumuma na slicnosti
- simSums.setdefault(item, 0)
- simSums[item] += sim
- # Kreiranje na normalizirana lista so rejtinzi
- rankings = [(total / simSums[item], item) for item, total in totals.items()]
- # Sortiranje na listata vo rastecki redosled
- rankings.sort()
- # Prevrtuvanje na lista za najgolemite vrednosti da bidat napred
- rankings.reverse()
- return rankings
- def getItemBasedRecomendations(critics, person1, n=None):
- oceni_po_film = transformPrefs(critics)
- similarity_per_item = {}
- for item in critics[person1].keys():
- similar_items = topMatches(oceni_po_film, item, n=None)
- my_rating = critics[person1][item]
- for similarity, item in similar_items:
- if item in critics[person1] or similarity <= 0:
- continue
- similarity_per_item.setdefault(item, [])
- # similarity_per_item[item].append(similarity)
- similarity_per_item[item].append(similarity*my_rating)
- similarity_per_item_avg = []
- for item in similarity_per_item:
- avg_sim = mean(similarity_per_item[item])
- similarity_per_item_avg.append((avg_sim, item))
- similarity_per_item_avg.sort(reverse=True)
- return similarity_per_item_avg
- def do_user_recomendation(korisnik):
- recomended_user_based = getUserBasedRecomendations(oceniPoKorisnici, korisnik)
- recomended_three = []
- minimum = len(recomended_user_based);
- if minimum > 3:
- minimum = 3
- for x in range(0, minimum):
- recomended_three.append(recomended_user_based[x][1])
- recomended_three.sort()
- print "user-based\n", recomended_three
- def do_item_recomendation(korisnik):
- # print json.dumps(oceni_po_filmovi, indent=2)
- recomended_item_based = getItemBasedRecomendations(oceniPoKorisnici, korisnik)
- recomended_three = []
- minimum = len(recomended_item_based);
- if minimum > 3:
- minimum = 3
- for x in range(0, minimum):
- recomended_three.append(recomended_item_based[x][1])
- recomended_three.sort()
- print "item-based\n", recomended_three
- def mean(x):
- if len(x)==0: return 0.0
- return sum(x)/len(x)
- if __name__ == "__main__":
- korisnik = input()
- # korisnik = 'Gene Seymour'
- n=input()
- # n = 7
- user_rankings = len(oceniPoKorisnici[korisnik])
- # print "user rankings", user_rankings
- if user_rankings < n:
- do_item_recomendation(korisnik)
- else:
- do_user_recomendation(korisnik)
- Sample input
- 'Gene Seymour'
- 7
- Sample output
- item-based
- ['Catch Me If You Can', 'Snitch', 'Superman Returns']
Advertisement
Add Comment
Please, Sign In to add comment