Advertisement
nanorocks

recommenden_systems_lab1_ex

May 16th, 2018
302
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.64 KB | None | 0 0
  1. """
  2. По изработка на задачите од претходната вежба веќе ќе имате две тренинг множества претставени во Python како речник од речници. Искористете ги за изработка на систем за препораки така што да може на секој од тест корисниците да им предложи по 3 филмови, еднаш користејќи item-based, а еднаш user-based препораки. При item-based пристапот се предлагаат фимови кои ги нема гледано корисникот кои се со позитивна сличност со некои од филмовите кои ги има гледано. На излез треба да се печатат две листи кои ги содржат само имињата на предложените филмови во растечки (азбучен) редослед. Првата листа е според user-based, а втората според item-based пристап.
  3.  
  4. """
  5.  
  6. critics={
  7.     '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},
  8.     '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},
  9.     '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},
  10.     '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},
  11.     '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},
  12.     '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},
  13.     'Toby': {'Snakes on a Plane':4.5, 'Snitch': 5.0},
  14.     '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},
  15.     '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},
  16.     'Larry': {'Lady in the Water': 3.0, 'Just My Luck': 3.5, 'Snitch': 1.5, 'The Night Listener': 3.5}
  17.     }
  18.  
  19.  
  20. from math import sqrt
  21.  
  22. def sim_distance(oceni, person1, person2):
  23.     filmovi1=set(oceni[person1].keys())
  24.     filmovi2=set(oceni[person2].keys())
  25.     zaednicki = filmovi1.intersection(filmovi2)
  26.     #print(filmovi1)
  27.     #print(filmovi2)
  28.     #print(zaednicki)
  29.  
  30.     for item in oceni[person1].keys():
  31.          if item in oceni[person2]:
  32.              zaednicki.add(item)
  33.  
  34.     if len(zaednicki) == 0: return 0
  35.  
  36.     suma = 0.0
  37.     for item in zaednicki:
  38.         ocena1 = oceni[person1][item]
  39.         ocena2 = oceni[person2][item]
  40.         suma += (ocena1 - ocena2) ** 2
  41. #         print(item, person1, ocena1, person2, ocena2)
  42.  
  43.     return 1 / (1 + sqrt(suma))
  44.  
  45. def sim_pearson(oceni, p1, p2):
  46.     zaednicki = set()
  47.     for item in oceni[p1]:
  48.         if item in oceni[p2]:
  49.             zaednicki.add(item)
  50.  
  51.     # Se presmetuva brojot na predmeti oceneti od dvajcata
  52.     n = len(zaednicki)
  53.  
  54.     # Ako nemaat zaednicki predmeti vrati korelacija 0
  55.     if n == 0: return 0
  56.  
  57.     # Soberi gi zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  58.     sum1 = 0
  59.     sum2 = 0
  60.  
  61.     # Soberi gi kvadratite od zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  62.     sum1Sq = 0
  63.     sum2Sq = 0
  64.  
  65.     # Soberi gi proizvodite od ocenite na dvete licnosti
  66.     pSum = 0
  67.     for item in zaednicki:
  68.         ocena1 = oceni[p1][item]
  69.         ocena2 = oceni[p2][item]
  70.         sum1 += ocena1
  71.         sum1Sq += ocena1 ** 2
  72.         sum2 += ocena2
  73.         sum2Sq += ocena2 ** 2
  74.         pSum += ocena1 * ocena2
  75.  
  76.     # Presmetaj go koeficientot na korelacija
  77.     num = pSum - (sum1 * sum2 / n)
  78.     den = sqrt((sum1Sq - pow(sum1, 2) / n) * (sum2Sq - pow(sum2, 2) / n))
  79.     if den == 0: return 0
  80.     r = num / den
  81.     return r
  82.  
  83. def transformPrefs(oceni):
  84.     result = {}
  85.     for person in oceni.keys():
  86.         for item in oceni[person]:
  87.             result.setdefault(item, {})
  88.             # Zameni gi mestata na licnosta i predmetot
  89.             result[item][person] = oceni[person][item]
  90.     return result
  91.  
  92. def topMatches(oceni, person, n=5, similarity=sim_pearson):
  93.     scores = []
  94.     for person2 in oceni.keys():
  95.         if person != person2:
  96.             s = similarity(oceni, person, person2)
  97.             scores.append((s, person2))
  98.     # Se sortira listata vo rastecki redosled
  99.     scores.sort()
  100.     # Se prevrtuva za najslicnite (so najgolema vrednost) da bidat prvi
  101.     scores.reverse()
  102.     if n is None:
  103.         return scores
  104.     else:
  105.         return scores[0:n]
  106.  
  107. def getRecommendations(oceni, person, similarity=sim_pearson, min_zaednicki=None):
  108.     totals = {}
  109.     simSums = {}
  110.     for person2 in oceni.keys():
  111.  
  112.         filmovi1 = set(oceni[person].keys())
  113.         filmovi2 = set(oceni[person2].keys())
  114.         zaednicki = filmovi1.intersection(filmovi2)
  115.         # ova e ako se bara minimum zaednicki filmovi
  116.         # za da se zemat vo predvid ocenite na drugiot korisnik
  117.         if min_zaednicki and len(zaednicki) < min_zaednicki:
  118.             print('So korisnikot', person2, 'imame samo', len(zaednicki), 'filmovi, pa go preskoknuvame')
  119.             continue
  120.  
  121.         if person2 == person:
  122.             continue
  123.  
  124.         sim = similarity(oceni, person, person2)
  125.  
  126.         if sim <= 0:
  127.             continue
  128.  
  129.         for item in oceni[person2]:
  130.             if item not in oceni[person] or oceni[person][item] == 0:
  131.                 # similarity * Score   (Slicnost * Ocena)
  132.                 #print(item, sim, oceni[person2][item], sim* oceni[person2][item])
  133.                 totals.setdefault(item, 0)
  134.                 totals[item] += oceni[person2][item] * sim
  135.  
  136.                 # Sumuma na slicnosti
  137.                 simSums.setdefault(item, 0)
  138.                 simSums[item] += sim
  139.  
  140.     rankings = [(total / simSums[item], item) for item, total in totals.items()]
  141.     #rankings = [item for item,v in totals.items()]
  142.     rankings.sort(reverse=True)
  143.     a = []
  144.     for i in rankings:
  145.         a.append(i[1])
  146.     a = a[:3]
  147.     a.sort()
  148.     return a#sorted(rankings[0:3])
  149.  
  150. def getItemBasedRecomendations(oceni,korisnik,similarity=sim_pearson):
  151.     rankings = []
  152.     filmovi = oceni.keys()
  153.     gledani = [item for item in filmovi if critics[korisnik].has_key(item)]
  154.     negledani = [item for item in filmovi if not critics[korisnik].has_key(item)]
  155.     #print gledani
  156.     #print negledani
  157.     slicnosti = {}
  158.     for film in negledani:
  159.         for drug in gledani:
  160.             sim = similarity(oceni, film, drug)
  161.             slicnosti.setdefault(film, 0);
  162.             if slicnosti[film] < sim:
  163.                 slicnosti[film] = sim
  164.     stvari = slicnosti.items()
  165.     #print stvari
  166.     stvari.sort(key=lambda tup: tup[1], reverse=True)
  167.     novi = [item[0] for item in stvari if item[1] > 0][0:3]
  168.     novi.sort()
  169.     return novi
  170.  
  171. def item_based(critics, person1, n=3):
  172.     oceni_po_film = transformPrefs(critics)
  173.     similarity_per_item = {}
  174.     for item in critics[person1].keys():
  175.         similar_items = topMatches(oceni_po_film, item, n=None)
  176.         my_rating = critics[person1][item]
  177.  
  178.         for similarity, item2 in similar_items:
  179.             if item2 in critics[person1] or similarity <= 0:
  180. #                 print('Slicnost', similarity, 'na', item,'so', item2)
  181.                 continue
  182.             weight= similarity * my_rating
  183. #             print('Slicnost', similarity, 'na', item,'so', item2, weight)
  184.             similarity_per_item.setdefault(item2, [])
  185.             similarity_per_item[item2].append(weight)
  186. #         print(item, my_rating, list(similarity_per_item.items()))
  187.     similarity_per_item_avg = []
  188.     import numpy as np
  189.     for item in similarity_per_item:
  190.         #print(item, similarity_per_item[item])
  191.         avg_sim = np.mean(similarity_per_item[item])
  192.         similarity_per_item_avg.append((avg_sim, item))
  193.     similarity_per_item_avg.sort(reverse=True)
  194.     a = []
  195.     for i in similarity_per_item_avg:
  196.         a.append(i[1])
  197.     a = a[:n]
  198.     a.sort()
  199.     return a #similarity_per_item_avg[:n]
  200.  
  201. if __name__ == "__main__":
  202.     korisnik = input()
  203.  
  204.     print "user-based: " + str(getRecommendations(critics, korisnik))
  205.     print "item-based: " + str(item_based(critics=critics, person1=korisnik))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement