Kemudraj

preporaki_zad2

Aug 22nd, 2017
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.07 KB | None | 0 0
  1. Задача 2 Problem 2 (1 / 2)
  2. Да се напише функција која во зависност од бројот на рангирани филмови на корисникот ќе одбира начинот на препорачување - дали item-based или user-based. Функцијата треба да прима аргумент име на корисникот и бројот n од стандарден влез. Ако бројот на рангирани филмови на корисникот е помал од n да препорачува на со item-based начин, а ако е поголем или еднаков на n да препорачува на user-based начин. На излез да се печати одбраниот начин (user-based или item-based), и во вториот ред да се испечати листа од препорачани филмови која ги содржи само имињата сортирани во растечки (азбучен) редослед.
  3.  
  4. oceniPoKorisnici = {
  5.     'Lisa Rose': {'Catch Me If You Can': 3.0, 'Snakes on a Plane': 3.5, 'Superman Returns': 3.5,
  6.                   'You, Me and Dupree': 2.5, 'The Night Listener': 3.0, 'Snitch': 3.0},
  7.     'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 'Just My Luck': 1.5, 'The Night Listener': 3.0,
  8.                      'You, Me and Dupree': 3.5},
  9.     'Michael Phillips': {'Catch Me If You Can': 2.5, 'Lady in the Water': 2.5, 'Superman Returns': 3.5,
  10.                          'The Night Listener': 4.0, 'Snitch': 2.0},
  11.     'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 'The Night Listener': 4.5, 'Superman Returns': 4.0,
  12.                      'You, Me and Dupree': 2.5},
  13.     'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 'Just My Luck': 2.0, 'Superman Returns': 3.0,
  14.                      'You, Me and Dupree': 2.0},
  15.     'Jack Matthews': {'Catch Me If You Can': 4.5, 'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,
  16.                       'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5, 'Snitch': 4.5},
  17.     'Toby': {'Snakes on a Plane': 4.5, 'Snitch': 5.0},
  18.     'Michelle Nichols': {'Just My Luck': 1.0, 'The Night Listener': 4.5, 'You, Me and Dupree': 3.5,
  19.                          'Catch Me If You Can': 2.5, 'Snakes on a Plane': 3.0},
  20.     'Gary Coleman': {'Lady in the Water': 1.0, 'Catch Me If You Can': 1.5, 'Superman Returns': 1.5,
  21.                      'You, Me and Dupree': 2.0},
  22.     'Larry': {'Lady in the Water': 3.0, 'Just My Luck': 3.5, 'Snitch': 1.5, 'The Night Listener': 3.5}
  23. }
  24.  
  25. from math import sqrt
  26. import json
  27.  
  28. # Vrakja merka za slicnost bazirana na rastojanieto za person1 i person2
  29. def sim_distance(oceni, person1, person2):
  30.     # Se pravi lista na zaednicki predmeti (filmovi)
  31.     zaednicki = {}
  32.     for item in oceni[person1].keys():
  33.         if item in oceni[person2]:
  34.             zaednicki[item] = 1
  35.     # ako nemaat zaednicki rejtinzi, vrati 0
  36.     if len(zaednicki) == 0: return 0
  37.     # Soberi gi kvadratite na zaednickite razliki
  38.     sum_of_squares = sum([pow(oceni[person1][item] - oceni[person2][item], 2)
  39.                           for item in oceni[person1] if item in oceni[person2]])
  40.     return 1 / (1 + sqrt(sum_of_squares))
  41.     #    return 1/(1+(sum_of_squares))
  42.  
  43.  
  44. # Go vrakja koeficientot na Pearsonova korelacija pomegu p1 i p2 (licnost 1 i licnost 2)
  45. # Vrednostite se pomegu -1 i 1
  46. def sim_pearson(oceni,p1,p2):
  47.     # Se kreira recnik vo koj ke se cuvaat predmetite (filmovi) koi se oceneti od dvajcata
  48.     # Vo recnikot ni se vazni samo klucevite za da gi cuvame iminjata na filmovite koi se zaednicki, a vrednostite ne ni se vazni
  49.     zaednicki={}
  50.     for item in oceni[p1]:
  51.         if item in oceni[p2]: zaednicki[item]=1
  52.  
  53.     # Se presmetuva brojot na predmeti oceneti od dvajcata
  54.     n=len(zaednicki)
  55.  
  56.     # Ako nemaat zaednicki predmeti vrati korelacija 0
  57.     if n==0: return 0
  58.  
  59.     # Soberi gi zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  60.     sum1=sum([oceni[p1][it] for it in zaednicki])
  61.     sum2=sum([oceni[p2][it] for it in zaednicki])
  62.  
  63.     # Soberi gi kvadratite od zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  64.     sum1Sq=sum([pow(oceni[p1][it],2) for it in zaednicki])
  65.     sum2Sq=sum([pow(oceni[p2][it],2) for it in zaednicki])
  66.  
  67.     # Soberi gi proizvodite od ocenite na dvete licnosti
  68.     pSum=sum([oceni[p1][it]*oceni[p2][it] for it in zaednicki])
  69.  
  70.     # Presmetaj go koeficientot na korelacija
  71.     num=pSum-(sum1*sum2/n)
  72.     den=sqrt((sum1Sq-pow(sum1,2)/n)*(sum2Sq-pow(sum2,2)/n))
  73.     if den==0: return 0
  74.     r=num/den
  75.     return r
  76.  
  77.  
  78. # Gi transformira rejtinzite taka sto klucevi ke bidat filmovite a vrednost lista od rejtinzi od sekoj korisnik
  79. def transformPrefs(oceni):
  80.     result={}
  81.     for person in oceni:
  82.         for item in oceni[person]:
  83.             result.setdefault(item,{})
  84.             # Zameni gi mestata na licnosta i predmetot
  85.             result[item][person]=oceni[person][item]
  86.     return result
  87.  
  88.  
  89. # Gi vrakja najslicnite n korisnici na daden korisnik
  90. # Brojot na rezultati (n) i funkcijata za slicnost se opcionalni parametri
  91. def topMatches(oceni,person,n=5, similarity=sim_pearson):
  92.     scores=[(similarity(oceni,person,other),other)
  93.                    for other in oceni if other!=person]
  94.     # Se sortira listata vo rastecki redosled
  95.     scores.sort( )
  96.     # Se prevrtuva za najslicnite (so najgolema vrednost) da bidat prvi
  97.     scores.reverse( )
  98.     return scores[0:n]
  99.  
  100.  
  101. # Gi vrakja preporakite za daden korisnik person so
  102. # koristenje na tezinski prosek na ocenite od drugite korisnici
  103. def getUserBasedRecomendations(oceni, person, similarity=sim_pearson):
  104.         totals = {}
  105.         simSums = {}
  106.         for other in oceni:
  107.             # Za da ne se sporeduva so samiot sebe
  108.             if other == person: continue
  109.             sim = similarity(oceni, person, other)
  110.             # ne se zemaat vo predvid rezultati <= 0
  111.             if sim <= 0: continue
  112.             for item in oceni[other]:
  113.                 # za tekovniot korisnik gi zemame samo filmovite sto gi nemame veke gledano
  114.                 if item not in oceni[person] or oceni[person][item] == 0:
  115.                     # similarity * Score   (Slicnost * Ocena)
  116.                     totals.setdefault(item, 0)
  117.                     totals[item] += oceni[other][item] * sim
  118.  
  119.                     # Sumuma na slicnosti
  120.                     simSums.setdefault(item, 0)
  121.                     simSums[item] += sim
  122.  
  123.         # Kreiranje na normalizirana lista so rejtinzi
  124.         rankings = [(total / simSums[item], item) for item, total in totals.items()]
  125.  
  126.         # Sortiranje na listata vo rastecki redosled
  127.         rankings.sort()
  128.         # Prevrtuvanje na lista za najgolemite vrednosti da bidat napred
  129.         rankings.reverse()
  130.         return rankings
  131.  
  132.  
  133. def getItemBasedRecomendations(critics, person1, n=None):
  134.     oceni_po_film = transformPrefs(critics)
  135.  
  136.     similarity_per_item = {}
  137.     for item in critics[person1].keys():
  138.         similar_items = topMatches(oceni_po_film, item, n=None)
  139.         my_rating = critics[person1][item]
  140.         for similarity, item in similar_items:
  141.             if item in critics[person1] or similarity <= 0:
  142.                 continue
  143.             similarity_per_item.setdefault(item, [])
  144.             # similarity_per_item[item].append(similarity)
  145.             similarity_per_item[item].append(similarity*my_rating)
  146.     similarity_per_item_avg = []
  147.  
  148.     for item in similarity_per_item:
  149.         avg_sim = mean(similarity_per_item[item])
  150.         similarity_per_item_avg.append((avg_sim, item))
  151.     similarity_per_item_avg.sort(reverse=True)
  152.     return similarity_per_item_avg
  153.  
  154.  
  155.  
  156. def do_user_recomendation(korisnik):
  157.     recomended_user_based = getUserBasedRecomendations(oceniPoKorisnici, korisnik)
  158.     recomended_three = []
  159.  
  160.     minimum = len(recomended_user_based);
  161.     if minimum > 3:
  162.         minimum = 3
  163.  
  164.     for x in range(0, minimum):
  165.         recomended_three.append(recomended_user_based[x][1])
  166.  
  167.     recomended_three.sort()
  168.     print "user-based\n", recomended_three
  169.  
  170.  
  171. def do_item_recomendation(korisnik):
  172.     # print json.dumps(oceni_po_filmovi, indent=2)
  173.  
  174.     recomended_item_based = getItemBasedRecomendations(oceniPoKorisnici, korisnik)
  175.     recomended_three = []
  176.  
  177.     minimum = len(recomended_item_based);
  178.     if minimum > 3:
  179.         minimum = 3
  180.  
  181.     for x in range(0, minimum):
  182.         recomended_three.append(recomended_item_based[x][1])
  183.  
  184.     recomended_three.sort()
  185.  
  186.     print "item-based\n", recomended_three
  187.  
  188.  
  189. def mean(x):
  190.     if len(x)==0: return 0.0
  191.     return sum(x)/len(x)
  192.  
  193.  
  194. if __name__ == "__main__":
  195.     korisnik = input()
  196.     # korisnik = 'Gene Seymour'
  197.  
  198.     n=input()
  199.     # n = 7
  200.  
  201.     user_rankings = len(oceniPoKorisnici[korisnik])
  202.     # print "user rankings", user_rankings
  203.  
  204.  
  205.     if user_rankings < n:
  206.         do_item_recomendation(korisnik)
  207.     else:
  208.         do_user_recomendation(korisnik)
  209.  
  210. Sample input
  211. 'Gene Seymour'
  212. 7
  213.  
  214. Sample output
  215. item-based
  216. ['Catch Me If You Can', 'Snitch', 'Superman Returns']
Advertisement
Add Comment
Please, Sign In to add comment