Advertisement
TDimovska

[СНЗ] Препорака на филмови

Jan 23rd, 2022
648
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #Препорака на филмови
  2. from math import sqrt
  3. from copy import deepcopy
  4.  
  5. def sim_distance(prefs, person1, person2):
  6.     """
  7.    Враќа мерка за сличност базирана на растојание помеѓу person1 и person2
  8.    :param prefs: речник со оцени од корисници
  9.    :param person1: име на корисник1
  10.    :param person2: име на корисник2
  11.    :return: сличност помеѓу корисник1 и корисник2
  12.    """
  13.     # Се прави листа на заеднички предмети
  14.     si = {}
  15.     for item in prefs[person1]:
  16.         if item in prefs[person2]:
  17.             si[item] = 1
  18.     # Ако немаат заеднички рејтинзи, врати 0
  19.     if len(si) == 0:
  20.         return 0
  21.     # Собери ги квадратите на сите разлики
  22.     sum_of_squares = sum([pow(prefs[person1][item] - prefs[person2][item], 2)
  23.                           for item in prefs[person1] if item in prefs[person2]])
  24.     return 1 / (1 + sqrt(sum_of_squares))
  25.  
  26.  
  27. def sim_pearson(prefs, p1, p2):
  28.     """
  29.    Го враќа коефициентот на Пирсонова корелација помеѓу p1 и p2 (личност1 и личност 2).
  30.    Вредностите се помеѓу -1 и 1
  31.    :param prefs: речник со оцени од корисници
  32.    :param p1: име на корисник1
  33.    :param p2: име на корисник2
  34.    :return: сличност помеѓу корисник1 и корисник2
  35.    """
  36.     # Се креира речник во кој ќе се чуваат предметите кои се оценети од двајцата
  37.     # Во речникот ни се важни само клучевите за да ги чуваме имињата на филмовите
  38.     # кои се заеднички, а вредностите не ни се важни
  39.     si = {}
  40.     for item in prefs[p1]:
  41.         if item in prefs[p2]:
  42.             si[item] = 1
  43.  
  44.     # Се пресметува бројот на предмети оценети од двајцата
  45.     n = len(si)
  46.  
  47.     # Ако немаат заеднички предмети, врати корелација 0
  48.     if n == 0:
  49.         return 0
  50.  
  51.     # Собери ги сите оцени за секоја личност посебно
  52.     sum1 = sum([prefs[p1][it] for it in si])
  53.     sum2 = sum([prefs[p2][it] for it in si])
  54.     # Собери ги квадратите од сите оцени за секоја личност посебно
  55.     sum1Sq = sum([pow(prefs[p1][it], 2) for it in si])
  56.     sum2Sq = sum([pow(prefs[p2][it], 2) for it in si])
  57.     # Собери ги производите од оцените на двете личности
  58.     pSum = sum([prefs[p1][it] * prefs[p2][it] for it in si])
  59.  
  60.     # Пресметај го коефициентот на корелација
  61.     num = pSum - (sum1 * sum2 / n)
  62.     den = sqrt((sum1Sq - pow(sum1, 2) / n) * (sum2Sq - pow(sum2, 2) / n))
  63.     if den == 0:
  64.         return 0
  65.     r = num / den
  66.     return r
  67.  
  68.  
  69. def top_matches(prefs, person, n=5, similarity=sim_pearson):
  70.     """
  71.    Ги враќа најсличните n корисници за даден корисник.
  72.    :param prefs: речник со оцени од корисници
  73.    :param person: име на корисник
  74.    :param n: број на слични корисници
  75.    :param similarity: метрика за сличност
  76.    :return: листа со најслични n корисници
  77.    """
  78.     scores = [(similarity(prefs, person, other), other)
  79.               for other in prefs if other != person]
  80.     # Се сортира листата во растечки редослед
  81.     scores.sort()
  82.     # Се превртува за најсличните (со најголема вредност) да бидат први
  83.     scores.reverse()
  84.     return scores[0:n]
  85.  
  86.  
  87. def get_recommendations(prefs, person, similarity=sim_pearson):
  88.     """
  89.    Ги враќа препораките за даден корисник со користење на тежински просек
  90.    со оцените од другите корисници
  91.    :param prefs: речник со оцени од корисници
  92.    :param person: име на корисник
  93.    :param similarity: метрика за сличност
  94.    :return: препораки за даден корисник
  95.    """
  96.     totals = {}
  97.     simSums = {}
  98.     for other in prefs:
  99.         # За да не се споредува со самиот себе
  100.         if other == person:
  101.             continue
  102.         sim = similarity(prefs, person, other)
  103.         # не се земаат предвид резултати <= 0
  104.         if sim <= 0:
  105.             continue
  106.         for item in prefs[other]:
  107.             # за тековниот корисник ги земаме само филмовите што ги нема гледано
  108.             if item not in prefs[person] or prefs[person][item] == 0:
  109.                 # Similarity * Score
  110.                 totals.setdefault(item, 0)
  111.                 totals[item] += prefs[other][item] * sim
  112.  
  113.                 # Сума на сличности
  114.                 simSums.setdefault(item, 0)
  115.                 simSums[item] += sim
  116.  
  117.     # Креирање на нормализирана листа со рејтинзи
  118.     rankings = [(total / simSums[item], item) for item, total in totals.items()]
  119.  
  120.     # Сортирање на листата во растечки редослед. Превртување на листата за најголемите вредности да бидат први
  121.     rankings.sort(reverse=True)
  122.  
  123.     return rankings
  124.  
  125.  
  126. def get_recommendations_item_based(inverted_prefs, person):
  127.     """
  128.    Ги враќа препораките за даден корисник со користење на тежински просек
  129.    со оцените од предметите
  130.    :param inverted_prefs: инвертиран речник со оцени од корисници, item-based
  131.    :param person: име на корисник
  132.    :return: препораки за даден корисник
  133.    """
  134.     similarity_per_item = {}
  135.     person_items = [item for item, values in inverted_prefs.items() if person in values.keys()]
  136.     for item in person_items:
  137.         similar_items = top_matches(inverted_prefs, item, n=None)
  138.         my_rating = inverted_prefs[item][person]
  139.         for similarity, item in similar_items:
  140.             if person in inverted_prefs[item] or similarity <= 0:
  141.                 continue
  142.             similarity_per_item.setdefault(item, [])
  143.             similarity_per_item[item].append(similarity * my_rating)
  144.  
  145.     # Креирање на нормализирана листа со рејтинзи
  146.     similarity_per_item_avg = [(sum(similarity_per_item[item]) / len(similarity_per_item[item]), item) for item in
  147.                                similarity_per_item]
  148.     similarity_per_item_avg.sort(reverse=True)
  149.  
  150.     return similarity_per_item_avg
  151.  
  152.  
  153. def transform_prefs(prefs):
  154.     """
  155.    Ги трансформира рејтинзите така што клучеви ќе бидат филмовите,
  156.    а вредност ќе биде листа со рејтинзи од секој корисник
  157.    :param prefs: речник со оцени од корисници
  158.    :return: инвертиран речник со оцени од корисници
  159.    """
  160.     result = {}
  161.     for person in prefs:
  162.         for item in prefs[person]:
  163.             result.setdefault(item, {})
  164.             # Замени ги местата на корисникот и предметот
  165.             result[item][person] = prefs[person][item]
  166.     return result
  167.  
  168. ratings = {
  169.     'Lisa Rose': {'Catch Me If You Can': 3.0, 'Snakes on a Plane': 3.5, 'Superman Returns': 3.5,
  170.                   'You, Me and Dupree': 2.5, 'The Night Listener': 3.0, 'Snitch': 3.0},
  171.     'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 'Just My Luck': 1.5, 'The Night Listener': 3.0,
  172.                      'You, Me and Dupree': 3.5},
  173.     'Michael Phillips': {'Catch Me If You Can': 2.5, 'Lady in the Water': 2.5, 'Superman Returns': 3.5,
  174.                          'The Night Listener': 4.0, 'Snitch': 2.0},
  175.     'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 'The Night Listener': 4.5, 'Superman Returns': 4.0,
  176.                      'You, Me and Dupree': 2.5},
  177.     'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 'Just My Luck': 2.0, 'Superman Returns': 3.0,
  178.                      'You, Me and Dupree': 2.0},
  179.     'Jack Matthews': {'Catch Me If You Can': 4.5, 'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,
  180.                       'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5, 'Snitch': 4.5},
  181.     'Toby': {'Snakes on a Plane': 4.5, 'Snitch': 5.0},
  182.     'Michelle Nichols': {'Just My Luck': 1.0, 'The Night Listener': 4.5, 'You, Me and Dupree': 3.5,
  183.                          'Catch Me If You Can': 2.5, 'Snakes on a Plane': 3.0},
  184.     'Gary Coleman': {'Lady in the Water': 1.0, 'Catch Me If You Can': 1.5, 'Superman Returns': 1.5,
  185.                      'You, Me and Dupree': 2.0},
  186.     'Larry': {'Lady in the Water': 3.0, 'Just My Luck': 3.5, 'Snitch': 1.5, 'The Night Listener': 3.5}
  187. }
  188.  
  189. if __name__ == '__main__':
  190.     test_users = list(input().split(", "))
  191.     test={}
  192.     train = {}
  193.     for u in ratings:
  194.         if u in test_users:
  195.             test[u] =ratings[u]
  196.         else:
  197.             train[u] = ratings[u]
  198.     for t in test:
  199.         res=[]
  200.         train[t] = test[t]
  201.         result = get_recommendations(train,t)
  202.         train.pop(t)
  203.         for r in result:
  204.             res.append(r[1])
  205.         print(t + ": " + "; ".join(res))
  206.  
  207.  
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement