Advertisement
nanorocks

recommenden_systems_lab2_ex

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