Advertisement
glavinova

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

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