Advertisement
kristina7

СНЗ - Лаб 4 - Задача 3 - Табела на слични корисници

Jan 22nd, 2018
398
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.48 KB | None | 0 0
  1. from __future__ import print_function
  2. import json
  3. from math import sqrt
  4.  
  5. oceniPoKorisnici={
  6.     '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},
  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,'You, Me and Dupree': 3.5},
  8.     '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},
  9.     '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},
  10.     '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},
  11.     '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},
  12.     'Toby': {'Snakes on a Plane':4.5, 'Snitch': 5.0},
  13.     '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},
  14.     '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},
  15.     'Larry': {'Lady in the Water': 3.0, 'Just My Luck': 3.5, 'Snitch': 1.5, 'The Night Listener': 3.5}
  16.     }
  17.  
  18. def sim_distance(oceni, person1, person2):
  19.     # Se pravi lista na zaednicki predmeti (filmovi)
  20.  
  21.     filmovi1=set(oceni[person1].keys())
  22.     filmovi2=set(oceni[person2].keys())
  23.     zaednicki = filmovi1.intersection(filmovi2)
  24. #     print(filmovi1)
  25. #     print(filmovi2)
  26. #     print(zaednicki)
  27. #     for item in oceni[person1].keys():
  28. #         if item in oceni[person2]:
  29. #             zaednicki.add(item)
  30. #     # ako nemaat zaednicki rejtinzi, vrati 0
  31.     if len(zaednicki) == 0: return 0
  32. #     # Soberi gi kvadratite na zaednickite razliki
  33.     suma = 0.0
  34.     for item in zaednicki:
  35.         ocena1 = oceni[person1][item]
  36.         ocena2 = oceni[person2][item]
  37.         suma += (ocena1 - ocena2) ** 2
  38. #         print(item, person1, ocena1, person2, ocena2)
  39.  
  40.     return 1 / (1 + sqrt(suma))
  41. def sim_pearson(oceni, p1, p2):
  42.     # Se kreira recnik vo koj ke se cuvaat predmetite (filmovi) koi se oceneti od dvajcata
  43.     # Vo recnikot ni se vazni samo klucevite za da gi cuvame iminjata na filmovite koi se zaednicki, a vrednostite ne ni se vazni
  44.     zaednicki = set()
  45.     for item in oceni[p1]:
  46.         if item in oceni[p2]:
  47.             zaednicki.add(item)
  48.  
  49.     # Se presmetuva brojot na predmeti oceneti od dvajcata
  50.     n = len(zaednicki)
  51.  
  52.     # Ako nemaat zaednicki predmeti vrati korelacija 0
  53.     if n == 0: return 0.0, 0
  54.  
  55.     # Soberi gi zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  56.     sum1 = 0
  57.     sum2 = 0
  58.  
  59.     # Soberi gi kvadratite od zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  60.     sum1Sq = 0
  61.     sum2Sq = 0
  62.  
  63.     # Soberi gi proizvodite od ocenite na dvete licnosti
  64.     pSum = 0
  65.     for item in zaednicki:
  66.         ocena1 = oceni[p1][item]
  67.         ocena2 = oceni[p2][item]
  68.         sum1 += ocena1
  69.         sum1Sq += ocena1 ** 2
  70.         sum2 += ocena2
  71.         sum2Sq += ocena2 ** 2
  72.         pSum += ocena1 * ocena2
  73.  
  74.     # Presmetaj go koeficientot na korelacija
  75.     num = pSum - (sum1 * sum2 / n)
  76.     den = sqrt((sum1Sq - pow(sum1, 2) / n) * (sum2Sq - pow(sum2, 2) / n))
  77.     if den == 0: return 0.0, 0
  78.     r = num / den
  79.     return r, n
  80. def transformoceni(oceni):
  81.     result = {}
  82.     for person in oceni.keys():
  83.         for item in oceni[person]:
  84.             result.setdefault(item, {})
  85.             # Zameni gi mestata na licnosta i predmetot
  86.             result[item][person] = oceni[person][item]
  87.     return result
  88. def item_based(critics, person1, n=3):
  89.     oceni_po_film = transformoceni(critics)
  90.     similarity_per_item = {}
  91.     for item in critics[person1].keys():
  92.         similar_items = topMatches(oceni_po_film, item, n=None)
  93.         my_rating = critics[person1][item]
  94.  
  95.         for similarity, item2 in similar_items:
  96.             if item2 in critics[person1] or similarity <= 0:
  97. #                 print('Slicnost', similarity, 'na', item,'so', item2)
  98.                 continue
  99.             weight= similarity * my_rating
  100. #             print('Slicnost', similarity, 'na', item,'so', item2, weight)
  101.             similarity_per_item.setdefault(item2, [])
  102.             similarity_per_item[item2].append(weight)
  103. #         print(item, my_rating, list(similarity_per_item.items()))
  104.     similarity_per_item_avg = []
  105.     import numpy as np
  106.     for item in similarity_per_item:
  107.         print(item, similarity_per_item[item])
  108.         avg_sim = np.mean(similarity_per_item[item])
  109.         similarity_per_item_avg.append((avg_sim, item))
  110.     similarity_per_item_avg.sort(reverse=True)
  111.     return similarity_per_item_avg[:n]
  112. def topMatches_inline(oceni, person, n=5, similarity=sim_pearson):
  113.     scores = [(similarity(oceni, person, other), other)
  114.               for other in oceni if other != person]
  115.     # Se sortira listata vo rastecki redosled
  116.     scores.sort()
  117.     # Se prevrtuva za najslicnite (so najgolema vrednost) da bidat prvi
  118.     scores.reverse()
  119.     return scores[0:n]
  120. def topMatches(oceni, person, n=5, similarity=sim_pearson):
  121.     scores = []
  122.     for person2 in oceni.keys():
  123.         if person != person2:
  124.             s = similarity(oceni, person, person2)
  125.             scores.append((s, person2))
  126.     # Se sortira listata vo rastecki redosled
  127.     scores.sort()
  128.     # Se prevrtuva za najslicnite (so najgolema vrednost) da bidat prvi
  129.     scores.reverse()
  130.     if n is None:
  131.         return scores
  132.     else:
  133.         return scores[0:n]
  134. def getRecommendations(oceni, person, similarity=sim_pearson, min_zaednicki=None):
  135.     totals = {}
  136.     simSums = {}
  137.     for person2 in oceni.keys():
  138.         # Za da ne se sporeduva so samiot sebe
  139.         if person2 == person: continue
  140.         filmovi1=set(oceni[person].keys())
  141.         filmovi2=set(oceni[person2].keys())
  142.         zaednicki = filmovi1.intersection(filmovi2)
  143.         # ova e ako se bara minimum zaednicki filmovi
  144.         # za da se zemat vo predvid ocenite na drugiot korisnik
  145.         if min_zaednicki and len(zaednicki)<min_zaednicki:
  146.             print('So korisnikot', person2, 'imame samo',len(zaednicki),'filmovi, pa go preskoknuvame')
  147.             continue
  148.         sim = similarity(oceni, person, person2)
  149. #         print(person,person2,sim)
  150.         # ne se zemaat vo predvid rezultati <= 0
  151.         if sim <= 0: continue
  152.         print(person,person2,sim)
  153.         for item in oceni[person2].keys():
  154. #             print(item, oceni[person].get(item, None), oceni[person2].get(item, None))
  155.             # za tekovniot korisnik gi zemame samo filmovite sto gi nemame veke gledano
  156.             if item not in oceni[person]: # or oceni[person][item] == 0:
  157.                 # similarity * Score   (Slicnost * Ocena)
  158.                 print(item, sim, oceni[person2][item], sim* oceni[person2][item])
  159.                 totals.setdefault(item, 0)
  160.                 totals[item] += oceni[person2][item] * sim
  161.  
  162.                 # Sumuma na slicnosti
  163.                 simSums.setdefault(item, 0)
  164.                 simSums[item] += sim
  165.         print()
  166. #     return
  167.     print()
  168.     # Kreiranje na normalizirana lista so rejtinzi
  169.     # rankings = [(total / simSums[item], item) for item, total in totals.items()]
  170.     rankings = []
  171.     for item, weighted_score in totals.items():
  172.         sim_total = simSums[item]
  173.         my_score = round(weighted_score / sim_total, 1)
  174.         print(item, weighted_score, sim_total, my_score)
  175.         rankings.append((my_score, item))
  176.  
  177.     # Sortiranje na listata vo rastecki redosled
  178.     rankings.sort(reverse=True)
  179.     # Prevrtuvanje na lista za najgolemite vrednosti da bidat napred
  180. #     rankings.reverse()
  181.     return rankings
  182.  
  183. def newDict(data):
  184.     SlicniKorisnici = {}
  185.     for i in data.keys():
  186.         for j in data.keys():
  187.             if i != j:
  188.                 if i not in SlicniKorisnici.keys():
  189.                     SlicniKorisnici[i]={}
  190.                 p, n = sim_pearson(oceniPoKorisnici, i, j)
  191.                 d = sim_distance(oceniPoKorisnici, i, j)
  192.                 SlicniKorisnici[i][j] = (round(d,3), round(p,3),n)
  193.     return SlicniKorisnici
  194.  
  195. if __name__ == "__main__":
  196.     user1 = input()
  197.     user2 = input()
  198.     SlicniKorisnici = newDict(oceniPoKorisnici)
  199.     print(SlicniKorisnici[user1][user2])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement