본문 바로가기

프로그래머스 데브 코스/TIL

[6기] 프로그래머스 인공지능 데브코스 112일차 TIL

1221

[17주차 - Day3] Recommendation system

무비렌즈 데이터를 활용한 아이템 협업 필터링

# surprise 모듈을 통한 로딩 파트
reader = Reader(line_format='user item rating  timestamp', sep=',', skip_lines=1)
data = Dataset.load_from_file('ratings.csv', reader=reader)

 

from surprise import KNNBasic
import heapq
from collections import defaultdict

trainSet = data.build_full_trainset()

sim_options = {
    'name': 'cosine',
    'user_based': False
}

# 아이템 기반과 코사인 기반으로 동작하는 모델 생성
model = KNNBasic(sim_options=sim_options)
# 데이터로부터 아이템 벡터 생성
model.fit(trainSet)
# 아이템간의 유사도 행령 계산
simMatrix = model.compute_similarities()

 

testUserId = '85'
k = 10

pd.set_option('display.max_colwidth', -1)
display(movie_ratings[movie_ratings['userId'] == int(testUserId)].sort_values('rating', ascending=False))

 

testUserInnerID = trainSet.to_inner_uid(testUserId)

# 이 사용자가 좋아한 영화 k개를 읽어서 kNeighbors에 저장
testUserRatings = trainSet.ur[testUserInnerID]
kNeighbors = heapq.nlargest(k, testUserRatings, key=lambda t: t[1])

# 이 사용자 좋아한 영화들과 비슷한 영화를 찾아서 candidates에 유사도 가중치를 곱해서 저장
candidates = defaultdict(float)
for itemID, rating in kNeighbors:
  similarityRow = simMatrix[itemID]
  for innerID, score in enumerate(similarityRow):
    candidates[innerID] += score * (rating)
    
# 사용자가 이미 본 아이템들을 기록
watched = {}
for itemID, rating in trainSet.ur[testUserInnerID]:
  watched[itemID] = 1
  
pos = 0
for itemID, ratingSum in sorted(candidates.items(), key=lambda k: k[1], reverse=True):
  if not itemID in watched:
    movieID = trainSet.to_raw_iid(itemID)
    print(movieID, getMovieName(movie_ratings, int(movieID)), ratingSum)
    pos += 1
    if (pos > 10):
      break

- 사용자 기반이랑 비슷하지만 다른 점들 찾아보면서 이해하기

 

def recommendForUser(userID):
  testUserInnerID = trainSet.to_inner_uid(userID)
  similarityRow = simMatrix[testUserInnerID]

  kNeighbors = heapq.nlargest(k, testUserRatings, key=lambda t: t[1])

  candidates = defaultdict(float)
  for itemID, rating in kNeighbors:
    similarityRow = simMatrix[itemID]
    for innerID, score in enumerate(similarityRow):
      candidates[innerID] += score * (rating)

  watched = {}
  for itemID, rating in trainSet.ur[testUserInnerID]:
    watched[itemID] = 1

  pos = 0
  for itemID, ratingSum in sorted(candidates.items(), key=lambda k: k[1], reverse=True):
    if not itemID in watched:
      movieID = trainSet.to_raw_iid(itemID)
      print(movieID, getMovieName(movie_ratings, int(movieID)), ratingSum)
      pos += 1
      if (pos > 10):
        break

- 동일한 코드 한 함수로 묶기

 

recommendForUser('85')