Advertisement
nanorocks

recommenden_systems_exam_2018

May 22nd, 2018
591
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.55 KB | None | 0 0
  1. # -*- coding:utf-8 -*-
  2.  
  3. """
  4. Да испрограмира функција за косинусна сличност која е дефинирана со следнава формула, каде A е листа со оцените на едниот корисник или филм, а B е листа со оцените на другиот корисник или филм:
  5. enter image description here
  6. Притоа треба да се избегне делење со нула и во тој случај да се смета дека сличноста е -1.
  7. Речник со оцени на корисници по филмови треба е веќе даден. Од стандардниот влез се вчитува име на еден филм. Да се испечати сличноста на прочитаниот филм со секој друг филм (освен самиот со себе) така што ќе се печати:
  8. Филм 2
  9. Косинусна сличност, Пеарсонова сличност, Евклидова сличност
  10. Празна линија
  11. При печатењето филмовите треба да бидат подредени по азбучен редослед. Сите сличности треба да бидат заокружени на 2 децимали.
  12. """
  13.  
  14.  
  15. from math import sqrt
  16.  
  17.  
  18.  
  19. oceniPoKorisnici={
  20.     '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},
  21.     '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},
  22.     '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},
  23.     '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},
  24.     '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},
  25.     '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},
  26.     'Toby': {'Snakes on a Plane':4.5, 'Snitch': 5.0},
  27.     '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},
  28.     '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},
  29.     'Larry': {'Lady in the Water': 3.0, 'Just My Luck': 3.5, 'Snitch': 1.5, 'The Night Listener': 3.5}
  30.     }
  31.  
  32.  
  33.  
  34. def sim_cos(oceni, p1, p2):
  35.  
  36.     zaednicki = set()
  37.     for item in oceni[p1]:
  38.         if item in oceni[p2]:
  39.             zaednicki.add(item)
  40.  
  41.     #print(zaednicki)
  42.     #return
  43.  
  44.     # Se presmetuva brojot na predmeti oceneti od dvajcata
  45.     n = len(zaednicki)
  46.  
  47.     # Ako nemaat zaednicki predmeti vrati korelacija 0
  48.     if n == 0: return 0
  49.  
  50.     # Soberi gi zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  51.     sum1 = 0
  52.     sum2 = 0
  53.  
  54.     # Soberi gi kvadratite od zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  55.     sum1Sq = 0
  56.     sum2Sq = 0
  57.  
  58.     # Soberi gi proizvodite od ocenite na dvete licnosti
  59.     pSum = 0
  60.     for item in zaednicki:
  61.         ocena1 = oceni[p1][item]
  62.         ocena2 = oceni[p2][item]
  63.  
  64.         sum1 += ocena1
  65.         sum1Sq += ocena1 ** 2
  66.         sum2 += ocena2
  67.         sum2Sq += ocena2 ** 2
  68.         pSum += ocena1 * ocena2
  69.  
  70.     # Presmetaj go koeficientot na korelacija
  71.     num = pSum
  72.     den = sqrt(sum1Sq) * sqrt(sum2Sq)
  73.     if den == 0: return -1
  74.     r = num / den
  75.     return round(r,2)
  76.  
  77. def sim_distance(oceni, person1, person2):
  78.     # Se pravi lista na zaednicki predmeti (filmovi)
  79.  
  80.     filmovi1=set(oceni[person1].keys())
  81.     filmovi2=set(oceni[person2].keys())
  82.     zaednicki = filmovi1.intersection(filmovi2)
  83. #     print(filmovi1)
  84. #     print(filmovi2)
  85. #     print(zaednicki)
  86. #     for item in oceni[person1].keys():
  87. #         if item in oceni[person2]:
  88. #             zaednicki.add(item)
  89. #     # ako nemaat zaednicki rejtinzi, vrati 0
  90.     if len(zaednicki) == 0: return 0
  91. #     # Soberi gi kvadratite na zaednickite razliki
  92.     suma = 0.0
  93.     for item in zaednicki:
  94.         ocena1 = oceni[person1][item]
  95.         ocena2 = oceni[person2][item]
  96.         suma += (ocena1 - ocena2) ** 2
  97. #         print(item, person1, ocena1, person2, ocena2)
  98.  
  99.     return round(1 / (1 + sqrt(suma)),2)
  100.  
  101. def sim_pearson(oceni, p1, p2):
  102.     # Se kreira recnik vo koj ke se cuvaat predmetite (filmovi) koi se oceneti od dvajcata
  103.     # Vo recnikot ni se vazni samo klucevite za da gi cuvame iminjata na filmovite koi se zaednicki, a vrednostite ne ni se vazni
  104.     zaednicki = set()
  105.     for item in oceni[p1]:
  106.         if item in oceni[p2]:
  107.             zaednicki.add(item)
  108.  
  109.     # Se presmetuva brojot na predmeti oceneti od dvajcata
  110.     n = len(zaednicki)
  111.  
  112.     # Ako nemaat zaednicki predmeti vrati korelacija 0
  113.     if n == 0: return 0
  114.  
  115.     # Soberi gi zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  116.     sum1 = 0
  117.     sum2 = 0
  118.  
  119.     # Soberi gi kvadratite od zaednickite oceni (rejtinzi) za  sekoja licnost posebno
  120.     sum1Sq = 0
  121.     sum2Sq = 0
  122.  
  123.     # Soberi gi proizvodite od ocenite na dvete licnosti
  124.     pSum = 0
  125.     for item in zaednicki:
  126.         ocena1 = oceni[p1][item]
  127.         ocena2 = oceni[p2][item]
  128.         sum1 += ocena1
  129.         sum1Sq += ocena1 ** 2
  130.         sum2 += ocena2
  131.         sum2Sq += ocena2 ** 2
  132.         pSum += ocena1 * ocena2
  133.  
  134.     # Presmetaj go koeficientot na korelacija
  135.     num = pSum - (sum1 * sum2 / n)
  136.     den = sqrt((sum1Sq - pow(sum1, 2) / n) * (sum2Sq - pow(sum2, 2) / n))
  137.     if den == 0: return 0
  138.     r = num / den
  139.     return round(r,2)
  140.  
  141. def topMatches(oceni, person, n=5, similarity=sim_pearson):
  142.     scores = []
  143.     for person2 in oceni.keys():
  144.         if person != person2:
  145.             s = similarity(oceni, person, person2)
  146.             scores.append((s, person2))
  147.     # Se sortira listata vo rastecki redosled
  148.     scores.sort()
  149.     # Se prevrtuva za najslicnite (so najgolema vrednost) da bidat prvi
  150.     scores.reverse()
  151.     if n is None:
  152.         return scores
  153.     else:
  154.         return scores[0:n]
  155.  
  156. def transformoceni(oceni):
  157.     result = {}
  158.     for person in oceni.keys():
  159.         for item in oceni[person]:
  160.             result.setdefault(item, {})
  161.             # Zameni gi mestata na licnosta i predmetot
  162.             result[item][person] = oceni[person][item]
  163.     return result
  164.  
  165. def getRecommendations(oceni, person, similarity=sim_pearson, min_zaednicki=None):
  166.     totals = {}
  167.     simSums = {}
  168.     for person2 in oceni.keys():
  169.         # Za da ne se sporeduva so samiot sebe
  170.         if person2 == person: continue
  171.         filmovi1=set(oceni[person].keys())
  172.         filmovi2=set(oceni[person2].keys())
  173.         zaednicki = filmovi1.intersection(filmovi2)
  174.         # ova e ako se bara minimum zaednicki filmovi
  175.         # za da se zemat vo predvid ocenite na drugiot korisnik
  176.         if min_zaednicki and len(zaednicki)<min_zaednicki:
  177.             print('So korisnikot', person2, 'imame samo',len(zaednicki),'filmovi, pa go preskoknuvame')
  178.             continue
  179.         sim = similarity(oceni, person, person2)
  180. #         print(person,person2,sim)
  181.         # ne se zemaat vo predvid rezultati <= 0
  182.         if sim <= 0: continue
  183.         print(person,person2,sim)
  184.         for item in oceni[person2].keys():
  185. #             print(item, oceni[person].get(item, None), oceni[person2].get(item, None))
  186.             # za tekovniot korisnik gi zemame samo filmovite sto gi nemame veke gledano
  187.             if item not in oceni[person]: # or oceni[person][item] == 0:
  188.                 # similarity * Score   (Slicnost * Ocena)
  189.                 print(item, sim, oceni[person2][item], sim* oceni[person2][item])
  190.                 totals.setdefault(item, 0)
  191.                 totals[item] += oceni[person2][item] * sim
  192.  
  193.                 # Sumuma na slicnosti
  194.                 simSums.setdefault(item, 0)
  195.                 simSums[item] += sim
  196.         print()
  197. #     return
  198.     print()
  199.     # Kreiranje na normalizirana lista so rejtinzi
  200.     # rankings = [(total / simSums[item], item) for item, total in totals.items()]
  201.     rankings = []
  202.     for item, weighted_score in totals.items():
  203.         sim_total = simSums[item]
  204.         my_score = round(weighted_score / sim_total, 1)
  205.         print(item, weighted_score, sim_total, my_score)
  206.         rankings.append((my_score, item))
  207.  
  208.     # Sortiranje na listata vo rastecki redosled
  209.     rankings.sort(reverse=True)
  210.     # Prevrtuvanje na lista za najgolemite vrednosti da bidat napred
  211. #     rankings.reverse()
  212.     return rankings
  213.  
  214. def item_based(critics, person1, n=3):
  215.     oceni_po_film = transformoceni(critics)
  216.     similarity_per_item = {}
  217.     for item in critics[person1].keys():
  218.         similar_items = topMatches(oceni_po_film, item, n=None)
  219.         my_rating = critics[person1][item]
  220.  
  221.         for similarity, item2 in similar_items:
  222.             if item2 in critics[person1] or similarity <= 0:
  223. #                 print('Slicnost', similarity, 'na', item,'so', item2)
  224.                 continue
  225.             weight= similarity * my_rating
  226. #             print('Slicnost', similarity, 'na', item,'so', item2, weight)
  227.             similarity_per_item.setdefault(item2, [])
  228.             similarity_per_item[item2].append(weight)
  229. #         print(item, my_rating, list(similarity_per_item.items()))
  230.     similarity_per_item_avg = []
  231.     import numpy as np
  232.     for item in similarity_per_item:
  233.         print(item, similarity_per_item[item])
  234.         avg_sim = np.mean(similarity_per_item[item])
  235.         similarity_per_item_avg.append((avg_sim, item))
  236.     similarity_per_item_avg.sort(reverse=True)
  237.     return similarity_per_item_avg[:n]
  238.  
  239. def transformoceni(oceni):
  240.     result = {}
  241.     for person in oceni.keys():
  242.         for item in oceni[person]:
  243.             result.setdefault(item, {})
  244.             # Zameni gi mestata na licnosta i predmetot
  245.             result[item][person] = oceni[person][item]
  246.     return result
  247.  
  248.  
  249. if __name__ == '__main__':
  250.  
  251.     film = 'Catch Me If You Can'
  252.  
  253.     # film = input()
  254.  
  255.     movie_base=transformoceni(oceniPoKorisnici)
  256.  
  257.     for k in sorted(movie_base.keys()):
  258.         if film == k:
  259.             continue
  260.         else:
  261.             print(k)
  262.             print sim_cos(movie_base,film,k), sim_pearson(movie_base,film,k), sim_distance(movie_base,film,k)
  263.             print
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement