Collaboration Filtering

2022. 3. 21. 22:23AI/Big data

    목차
반응형

CF

취향이 비슷한 사람들은 다른 아이템에 대해서도 비슷한 취향을 가지고 있을 것을 가정하고 추천하는 방법
유사도 지표로 "코사인 유사도"를 사용
두 벡터의 내적을 각 벡터의 크기(norm)의 곱으로 나눠준 값

data load

 

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split


u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
users = pd.read_csv('u.user', sep='|', names=u_cols, encoding='latin-1')
i_cols = ['movie_id', 'title', 'release date', 'video release date', 'IMDB URL', 'unknown', 
          'Action', 'Adventure', 'Animation', 'Children\'s', 'Comedy', 'Crime', 'Documentary', 
          'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 
          'Thriller', 'War', 'Western']
movies = pd.read_csv('u.item', sep='|', names=i_cols, encoding='latin-1')
r_cols = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_csv('u.data', sep='\t', names=r_cols, encoding='latin-1')
ratings = ratings.drop('timestamp', axis=1)

 

movies = movies[['movie_id', 'title']]
x = ratings
y = ratings['user_id']
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25, stratify=y)

 

def RMSE(y_true, y_pred):
    return np.sqrt(np.mean((np.array(y_true) - np.array(y_pred))**2))

def score(model):
    id_pairs = zip(x_test['user_id'], x_test['movie_id'])
    y_pred = np.array([model(user, movie) for (user, movie) in id_pairs])
    y_true = np.array(x_test['rating'])
    return RMSE(y_true, y_pred)

rating matrix 생성

 

rating_matrix = x_train.pivot(index='user_id', columns='movie_id', values='rating')

 

from sklearn.metrics.pairwise import cosine_similarity


matrix_dummy = rating_matrix.copy().fillna(0)
user_similarity = cosine_similarity(matrix_dummy, matrix_dummy)

user_similarity = pd.DataFrame(user_similarity, index=rating_matrix.index, columns=rating_matrix.index)

 

 

matrix_dummy = rating_matrix.copy().fillna(0)
user_similarity = cosine_similarity(matrix_dummy, matrix_dummy)
user_similarity = pd.DataFrame(user_similarity, index=rating_matrix.index, columns=rating_matrix.index)

 

def CF_simple(user_id, movie_id):
    if movie_id not in rating_matrix:
        return 3.0

    sim_scores = user_similarity[user_id].copy()   # user_id's similarities to the others
    movie_ratings = rating_matrix[movie_id].copy() # cur movies' all users' ratings

    none_rating_idx = movie_ratings[movie_ratings.isnull()].index

    movie_ratings = movie_ratings.dropna()  # NaN인 평가하지 않은 user들 항목을 제거

    sim_scores = sim_scores.drop(none_rating_idx)  # 해당 영화를 평가하지 않은 user들의 유사도를 제거

    mean_rating = np.dot(sim_scores, movie_ratings) / sim_scores.sum()
    return mean_rating

 

  • 주어진 user에 대해 다른 user들과의 유사도 점수를 지닌 벡터가 sim_scores
  • 어떤 영화를 user들이 내린 평점 벡터가 movie_ratings
    • 여기서 평점을 내리지 않은 user들은 제거
    • 마찬가지로, 제거된 user들은 sim_scores에서도 제거
  • 이제 sim_scores 내 각 user의 유사도에 각 user가 rating한 점수를 곱하여 가중치를 계산
    • 이 가중치를 전체 유사도 합으로 나눠 값을 rating의 범위 값 1~5 사이로 scaling
    • 하여 이 값을 반환

 

print('score = ', score(CF_simple))
    score =  1.0256719932045943

 

Pearson correlation coefficient

 

user_similarity = cosine_similarity(matrix_dummy, matrix_dummy)

Pearson 유사도로 계산 하는 ex.

user_similarity = np.corrcoef(matrix_dummy)
반응형

'AI > Big data' 카테고리의 다른 글

최적의 이웃 크기 설정  (0) 2022.03.22
CF considering neighbor  (0) 2022.03.22
영화 추천 - 높은 평균 평점 기준  (0) 2022.03.21
hyperparameter tuning  (0) 2022.03.19
Titanic data training  (0) 2022.03.19