[추천시스템] 02. 협업 필터링 (Collaborative Filtering) - 1) 사용자 기반 CF, 아이템 기반 CF

‍강민석·2022년 7월 14일
2

추천시스템

목록 보기
3/5

협업 필터링의 원리

  • 사용자 집단별 추천에서의 인구통계학적 변수 (나이, 성별 등) 가 아닌 사용자의 취향을 고려한 추천시스템 개발
  • 특정 아이템에 대해 비슷한 취향을 가진 사람들은 다른 아이템 또한 비슷한 취향을 가질 것이라고 가정
  • 특정 사용자와 취향이 비슷한 집단 (유사 집단) 의 취향을 기반으로 아이템 추천

유사도 지표

CF는 유사 집단을 파악하는 것이 핵심이므로 사용자 또는 아이템간 유사도를 구하기 위해 유사도 지표를 활용한다.

1. 상관계수

r=(xix)(yiy)(xix)2(yiy)2r = \frac{\sum{(x_i - \overline{x})(y_i - \overline{y})}}{\sqrt{\sum{(x_i - \overline{x})^2}\sum{(y_i - \overline{y})^2}}}
  • 두 변수 x,y 사이의 상관관계의 정도를 나타내는 수치
  • 연속형 데이터셋에 적용
  • -1과 1 사이의 값

2. 코사인 유사도

similarity=cosθ=ABAB=AiBiAi2Bi2similarity = \cos{\theta} = \frac{A \cdot B}{\Vert A \Vert \Vert B \Vert} = \frac{\sum{A_i B_i}}{\sqrt{\sum{A_i^2}}\sqrt{\sum{B_i^2}}}
  • CF에서 가장 널리 쓰이는 유사도
  • 각 아이템이 하나의 차원이 되고, 사용자의 평가값이 좌표값이 된다.
  • 두 사용자의 평가값이 유사한 경우, θ\theta가 작아져 cosθ\cos{\theta}가 커진다.
  • -1과 1 사이의 값

사용자 기반 CF vs 아이템 기반 CF

🔑 유사도를 계산하는 기준에 따라 분류

  • 사용자 기반 CF : 취향이 비슷한 집단을 알아내고, 집단에 속한 사용자들이 공통적으로 좋게 평가한 아이템을 추천

  • 아이템 기반 CF : 사용자들의 평가 패턴을 바탕으로 아이템 간의 유사도를 계산해서 사용자의 특정 아이템에 대한 예측 평점을 계산

즉, 간단히 말해서 사용자 기반 CF는 사용자간 유사도를 계산하는 것이고, 아이템 기반 CF는 아이템간 유사도를 계산하는 것이 차이점이라고 이해할 수 있다.

사용자 기반 CF 알고리즘

사용자 기반 CF 알고리즘을 통한 추천 프로세스는 다음과 같다.

  1. 모든 사용자간 유사도 계산
  2. 추천 대상과 다른 사용자간 유사도 추출
  3. 추천 대상이 평가하지 않은 아이템에 대한 예상 평가값 계산 (평가값 = 다른 사용자의 평가 ×\times 다른 사용자와의 유사도)
  4. 아이템 중 예상 평가값이 가장 높은 N개 추천

💡 사용자 기반 CF - MovieLens 실습에서는 사용자간 유사도를 계산하고, 사용자 기반 CF 알고리즘을 통해 추천 대상이 평가한 영화에 대해 예상 평가값을 계산해 실제값과 비교하여 정확도를 계산한다.

  • 데이터 읽고, 필요한 함수 정의
# u.user 파일 DataFrame 형태로 읽기
u_user_src = os.path.join(base_src,'u.user')
u_cols = ['user_id', 'age','sex','occupation','zip_code']
users = pd.read_csv(u_user_src,sep = '|', names = u_cols, encoding = 'latin-1')
users = users.set_index('user_id')

# u.item 파일 DataFrame 형태로 읽기
u_item_src = os.path.join(base_src,'u.item')
i_cols = ['movie_id', 'title', 'release data', 'video release data',
          '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_src, sep = '|', names = i_cols, encoding = 'latin-1')
movies = movies.set_index('movie_id')

# u.data 파일 DataFrame형태로 읽기
u_data_src = os.path.join(base_src,'u.data')
r_cols = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_csv(u_data_src, sep = '\t', names = r_cols, encoding = 'latin-1')

### 성능 평가

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

# score(RMSE) 계산
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)
    
### 데이터셋 만들기
x = ratings.copy()
y = ratings['user_id']

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.25, stratify = y)

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

위 내용은 movielens 데이터를 읽고 필요한 함수를 정의하는 과정으로, 앞선 과정과 중복되는 내용이다.

  • 모든 사용자간 유사도 계산
### 코사인 유사도 계산
from sklearn.metrics.pairwise import cosine_similarity

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

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

  • 예측치 계산 함수
### 영화의 가중평균 rating을 계산하는 함수
def CF_simple(user_id, movie_id):
    if movie_id in ratings_matrix.columns:
        sim_scores = user_similarity[user_id].copy()
        movie_ratings = ratings_matrix[movie_id].copy()
        none_rating_idx = movie_ratings[movie_ratings.isnull()].index
        movie_ratings = movie_ratings.dropna()
        sim_scores = sim_scores.drop(none_rating_idx)
        mean_rating = np.dot(sim_scores, movie_ratings) / sim_scores.sum()

    else:
        mean_rating = 3.0

    return mean_rating

# 정확도 계산
score(CF_simple)

RMSE는 약 1.025로, 성별에 따른 추천 방식보다 개선되었음을 알 수 있다.


아이템 기반 CF 알고리즘

아이템 기반 CF 알고리즘을 통한 추천 프로세스는 다음과 같다.

  1. 모든 아이템간 유사도 계산
  2. 추천 대상이 선택한 아이템과 다른 아이템간 유사도 추출
  3. 유사도가 가장 높은 N개 추천

아이템 기반 CF 알고리즘의 예시

  • 특정 기사를 본 사람들이 본 뉴스
  • 해당 음원을 재생한 사람들이 재생한 다른 음원
  • 이 책을 구매한 사람들이 함께 구매한 책

💡 아이템 기반 CF - MovieLens 실습에서는 영화간 유사도를 계산하고 특정 영화와 유사도가 높은 영화를 추천한다.

  • 모든 영화간 유사도 계산
# 아이템 기준이므로 전치시켜야 함.
rating_matrix_t = np.transpose(rating_matrix)

# 결측치는 0으로
matrix_dummy = rating_matrix_t.copy().fillna(0)

# 각 상품간의 코사인 유사도 
item_similarity = cosine_similarity(matrix_dummy, matrix_dummy)

# 데이터프레임으로 변환
item_similarity = pd.DataFrame(item_similarity, index=rating_matrix_t.index,
                               columns=rating_matrix_t.index)
                               
# 각 상품 (영화) 간의 유사도 출력
item_similarity                           

위 사진에서는 영화의 id가 아닌 title을 기준으로 영화간의 유사도를 계산한 결과이다. (위 코드는 id를 기준으로 계산)

  • 사용자가 본 영화와 유사도가 높은 영화 추천 함수
# 유사도가 높은 영화 10개 추천 함수
def get_recom(title):
    return item_similarity[title].sort_values(ascending=False)[:11]
    
get_recom('Godfather, The (1972)')

profile
데이터분석가

0개의 댓글