Kemudraj

preporaki_zad1

Aug 22nd, 2017
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.06 KB | None | 0 0
  1. Задача 1 Problem 1 (1 / 3)
  2. По изработка на задачите од претходната вежба веќе ќе имате две тренинг множества претставени во Python како речник од речници. Искористете ги за изработка на систем за препораки така што да може на секој од тест корисниците да им предложи по 3 филмови, еднаш користејќи item-based, а еднаш user-based препораки. При item-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:", 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:", 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.  
  195. if __name__ == "__main__":
  196.     korisnik = input()
  197.     # korisnik = 'Gary Coleman'
  198.  
  199.     do_user_recomendation(korisnik)
  200.     do_item_recomendation(korisnik)
  201.  
  202. Sample input
  203. 'Gary Coleman'
  204.  
  205. Sample output
  206. user-based: ['Snakes on a Plane', 'Snitch', 'The Night Listener']
  207. item-based: ['Just My Luck', 'Snakes on a Plane', 'Snitch']
Advertisement
Add Comment
Please, Sign In to add comment