text: '''
  Author: Uday Boni
  Source:  https://surprise.readthedocs.io/en/stable/knn_inspired.html#surprise.prediction_algorithms.knns.KNNBasic
  Date: 24-NOV-2019
  License: Open Source; feel free to modify the code 
  '''
  #Load the MovieLens module
  from MovieLens import MovieLens
  from surprise import KNNBasic
  import heapq
  from collections import defaultdict
  from operator import itemgetter
  
  #Test the user number 85 to generate the top-10 recommendations based on used based filterring
  
  testSubject = '85'
  k = 10
  
  # Load our data set and compute the user similarity matrix
  ml = MovieLens()
  data = ml.loadMovieLensLatestSmall()
  
  trainSet = data.build_full_trainset()
  
  sim_options = {'name': 'cosine',
                 'user_based': True
                 }
  
  model = KNNBasic(sim_options=sim_options)
  model.fit(trainSet)
  simsMatrix = model.compute_similarities()
  
  # Get top N similar users to our test subject
  
  testUserInnerID = trainSet.to_inner_uid(testSubject)
  similarityRow = simsMatrix[testUserInnerID]
  
  similarUsers = []
  for innerID, score in enumerate(similarityRow):
      if (innerID != testUserInnerID):
          similarUsers.append( (innerID, score) )
  
  kNeighbors = heapq.nlargest(k, similarUsers, key=lambda t: t[1])
  
  # Get the stuff they rated, and add up ratings for each item, weighted by user similarity
  candidates = defaultdict(float)
  for similarUser in kNeighbors:
      innerID = similarUser[0]
      userSimilarityScore = similarUser[1]
      theirRatings = trainSet.ur[innerID]
      for rating in theirRatings:
          candidates[rating[0]] += (rating[1] / 5.0) * userSimilarityScore
      
  # Build a dictionary of stuff the user has already seen
  watched = {}
  for itemID, rating in trainSet.ur[testUserInnerID]:
      watched[itemID] = 1
      
  # Get top-10 rated items from similar users:
  pos = 0
  for itemID, ratingSum in sorted(candidates.items(), key=itemgetter(1), reverse=True):
      if not itemID in watched:
          movieID = trainSet.to_raw_iid(itemID)
          print(ml.getMovieName(int(movieID)), ratingSum)
          pos += 1
          if (pos > 10):
              break
  
  
  
  