협업 필터링 (Collaborative Filtering)은 사용자 행동이나 아이템 정보로부터 사용자가 선호할 만한 아이템을 추측하여 제시하는 추천 시스템 (Recommendation System)의 한 유형이다. 추천 시스템에는 협업 필터링 외에도 콘텐츠 기반 필터링 (Content-Based Filtering) 기법이 있다. 콘텐츠 기반 필터링은 사용자가 선호하는 특정 아이템을 분석하여 그 아이템과 유사한 콘텐츠를 가진 아이템을 추천하는 방식이다. 우리가 앞서 다루었던 연관규칙 분석 역시 추천 대상의 아이템을 분석하여 추천 항목을 도출하는 것이므로 일종의 콘텐츠 기반 필터링 기법 중 하나라고 할 수 있다.
[그림 1] 추천 시스템 모형의 분류
협업 필터링은 많은 사용자로부터 얻은 기호정보를 분석하여 해당 사용자와 비슷한 성향의 사용자들이 선호하는 아이템을 추천하는 일련의 방법들을 의미한다. 기술적인 관점에서 보았을 때, 협업 필터링은 아래 그림처럼 사용자-아이템 평점 행렬과 같이 축적된 사용자 행동 데이터를 기반으로 사용자가 아직 평가하지 않은 아이템을 예측 평가하는 것이라고 할 수 있다.
협업 필터링에서 사용하는 사용자-아이템 평점 행렬은 많은 아이템을 열로 가지는 다차원 행렬인데, 사용자가 평점을 매긴 아이템의 수가 많지 않기 때문에 희소 행렬 (Sparse Matrix)의 특성을 보이게 된다.
[그림 2] 사용자-아이템 평점 행렬
협업 필터링은 일반적으로 사용자나 상품을 기준으로 평점의 유사성을 살피는 메모리 기반 협업 필터링 (Memory based Collaborative Filtering)과 머신러닝 모형을 이용해 평점을 예측하는 모델 기반 협업 필터링 (Model-based Collaborative Filtering)으로 나뉜다.
[그림 3] 협업 필터링의 유형
메모리 기반 협업 필터링은 다시 사용자 기반 협업 필터링 (User-Based Collaborative Filtering)과 아이템 기반 협업 필터링 (Item-Based Collaborative Filtering)으로 나뉠 수 있다. 사용자 기반 협업 필터링은 사용자 간의 유사성을 바탕으로 아이템을 추천하는 방법이고, 아이템 기반 협업 필터링은 아이템 간의 유사성을 바탕으로 아이템을 추천하는 방법인데, 이는 분석의 대상이 사용자냐 아이템이냐에 대한 차이가 있을 뿐 아이템을 추천하는 알고리즘은 동일하다. 이들은 시스템이 이미 갖고 있는 데이터에 기초하여 사용자/아이템을 추천하기 때문에 메모리 기반 협업 필터링 (Memory-Based CF)이라고도 불린다.
모델 기반 협업 필터링은 베이지안 네트워크 (Bayesian Network)나 군집분석, SVM, 딥러닝 등 다양한 머신러닝 모형을 이용해 사용자의 평점을 예측하는 모형을 만드는 방식이다. 다양한 모형 기반 협업 필터링 기법 중 현재 많은 주목을 받고 있는 것은 잠재요인 모델 기반 협업 필터링 (Latent Factor Model-Based Collaborative Filtering)이다. 이는 특이값 분해 (Singular Value Decomposition, SVD) 모형과 같은 차원 감소 기법을 기반으로 다차원 행렬을 분해하고, 잠재요인을 추출하여 사용자가 특정 항목을 선호하는 이유를 알아내는 기법으로서 넷플릭스 (Netflix)의 알고리즘 대회에서 우승하여 현재 많은 추천 시스템에서 활용되고 있다.
협업 필터링은 결과가 직관적이며, 상품에 대한 구체적인 정보를 분석할 필요가 없다는 장점이 있다. 가령, 영화 상품의 경우 장르가 무엇인지, 사용자가 구매한 기존 상품과 추천 상품이 서로 연계되어 있는 관계인지 등 상품 내용을 이해하지 않아도 된다는 것이다. 그러나 협업 필터링은 기존에 없던 새로운 항목이 추가되는 경우 이를 추천할 수 있는 정보가 쌓일 때까지 추천이 어렵다는 콜드 스타트 (Cold Start) 문제를 가지고 있다. 또한, 판매하는 상품이 매우 많지만, 소수의 인기상품들 중심으로 평가 정보가 존재하는 롱테일 (Long Tail) 현상에 대해서는 추천 성능이 급격히 저하되는 문제점을 가지고 있다.
[표 1] 협업 필터링의 장단점
장점 | 결과가 직관적이다. |
상품 자체에 대한 정보 없이 추천이 가능하다. | |
단점 | 새로운 항목 추천에 한계가 있는 콜드 스타트 문제가 있다. |
관심이 저조한 상품은 정보가 부족하여 추천이 어렵다. | |
계산량이 많아 사용자가 많아질수록 추천의 효율성이 떨어진다. |
[1] 사용자 기반 협업 필터링
사용자 기반 협업 필터링 (User-based Collaborative Filtering)은 특정 사용자와 구매 패턴 및 품목 평가 패턴이 유사한 사용자들을 찾고, 이를 기반으로 사용자에게 제품을 추천하는 방법이다. 사용자 기반 협업 필터링의 가장 일반적인 예는 온라인 쇼핑 사이트에서 흔히 볼 수 있는 ‘이 상품을 구매한 사용자가 구매한 상품들’ 기능이다.
사용자 기반 협업 필터링은 사용자-아이템 평점 행렬에서 특정 사용자와 타 사용자 간의 유사도를 측정하고, 가장 유사도가 높은 사용자들을 추출하여 특정 사용자가 평점을 부여하지 않은 아이템의 평점을 예측하게 된다.
사용자 기반 협업 필터링에서 두 명의 사용자 u, v간의 유사도를 측정하는 방법은 다음과 같다.
평균제곱차이 유사도 (Mean Squared Difference Similarity)
사용자 사이의 유클리드 거리에 기반한 유사도 측정 방법이다. 우선 평균제곱차이 (MSD)를 구한 뒤, 이 MSD 값이 0이 되는 경우에 대응하기 위해 1을 더하고, 사용자 간 유사도가 높을수록 값이 작아지도록 역수를 취해 평균제곱차이 유사도(MSD_sim)를 계산한다.
코사인 유사도 (Cosine Similarity)
코사인 각도를 이용하여 측정된 두 사용자 간의 유사한 정도를 측정한다. 측정값은 0과 1사이의 값을 가지며 1에 가까울수록 유사도가 높다.
피어슨 유사도 (Pearson Similarity)
두 사용자 간의 상관계수 (Pearson Correlation Coefficient)를 이용하여 유사도를 측정한다. 따라서, 1에 가까울수록 두 사용자 간의 유사도가 높으며, 유사도가 전혀 없을 경우 0이 된다.
간단한 예시를 통해 사용자 기반 협업 필터링의 동작 과정을 살펴보자.
사용자 간 유사도 계산
아래와 같이 사용자-아이템 평점 행렬이 주어졌을 때, 위에서 설명한 유사도 측정 방식 중 하나를 이용해 사용자 간 유사도를 구한다. 본 예시에서는 코사인 유사도를 사용하였다. 사용자 간 유사도 계산 결과는 사용자 수사용자 수 크기의 유사도 행렬이 만들어진다. 이때, 유사도는 두 사용자가 공통으로 평가한 상품에 대해서만 계산하기 때문에 공통으로 평가한 상품의 개수가 적을 경우 유사성이 과대평가될 수 있다. 한편, 만약 사용자 간 공통 평가 상품이 없을 경우 유사성은 0이 된다.
[그림 4] 유사도 계산 예시
유사도 높은 K명의 평점들을 기반으로 예측 평점 계산
사용자 간 유사도가 구해지면 특정 사용자와 유사도가 높은 k명의 사용자를 선택하여 특정 아이템에 대한 평점을 예측한다. 이때 예측 평점은 유사도 높은 k명 사용자들의 평점들을 단순 평균하여 사용하거나, k명 사용자 간의 유사도에 대해 가중 평균하여 계산할 수 도 있다. 본 예시에서는 사용자 간 유사도를 기반으로 한 가중 평균 방식을 이용하여 아이템에 대한 평점을 예측해보았다.
사용자 1이 아직 평가하지 않은 아이템 D에 대한 평점을 예측할 경우는 다음과 같다. 사용자 1의 경우 k를 2로 설정하면 유사도 기준으로 사용자 2와 사용자 3이 선택되는데, 사용자 2와 사용자 3의 아이템 D에 대해 평가 점수는 모두 5이므로 아래와 같이 가중 평균하면 사용자 1의 아이템 D에 대한 예측 평점은 5.0이 된다.
[그림 5] 예측 평점 계산 예시
이와 같은 방식으로 사용자-아이템 평점 행렬 데이터를 갱신한 예시는 아래 그림과 같다. 그림에서 보는 바와 같이 평가되지 않았던 아이템에 대한 점수가 생길 뿐만 아니라, 기존의 평가 점수들도 모두 갱신된다는 것을 알 수 있다. 협업 필터링은 모든 사용자 및 상품에 적용하여 평점이 이미 존재하는 항목에 대해서도 예측 평점을 구하기 때문이다. 따라서, 원래 평점이 있었던 항목에 대하여 원 평점과 예측 평점을 비교한다면 RMSE 등의 지표를 이용하여 협업 필터링 모형의 성능을 평가할 수 있을 것이다.
[그림 6] 원 평점 행렬과 예측 평점 행렬
이러한 방식의 메모리 기반 협업 필터링을 k명의 유사도가 높은 이웃 사용자를 선택한다고 해서 K-NN(K-Nearest Neighbors) 기반 협업 필터링이라고 부르기도 한다.
[2] 아이템 기반 협업 필터링
아이템 기반 협업 필터링 (Item-Based Collaborative Filtering)은 평점이 입력된 상품과 평점을 예측하고자 하는 상품과의 유사도를 계산하여 상품을 추천하는 방법이다. 이러한 방식의 추천 기법이 유효한 이유는 대부분의 사람들이 과거에 자신이 좋아했던 상품과 비슷한 상품이라면 현재도 좋아하는 경향이 있고, 반대로 과거에 선호하지 않는 상품과 비슷한 상품이라면 현재도 선호하지 않는 경향이 존재하기 때문이다. 기술적인 관점에서 보면 아이템 기반 협업 필터링은 사용자-아이템 행렬 대신 행과 열이 바뀐 아이템-사용자 행렬을 기반으로 한다는 점만 다를 뿐 유사성 측정 방식이나 예측 평점 계산 방식은 동일하다.
아이템 간 유사도 계산
아래와 같은 아이템-사용자 평점 행렬이 주어졌을 때 아이템 간의 유사도를 계산한다. 마찬가지로 코사인 유사도를 기반으로 계산하였으며, [그림 7]의 오른쪽 테이블과 같이 아이템아이템 크기의 유사도 행렬이 생성되었다.
[그림 7] 아이템 간의 유사도 계산 결과
유사도 높은 K개의 아이템 평점들을 기반으로 예측 평점 계산
Item B에 대한 User 3의 예측 평점을 구하는 과정을 예로 들어보자. k를 2로 한다면 Item B와 유사도가 높은 상품은 Item C와 Item D이므로, 사용자 기반 협업 필터링에서 설명한 동일한 방식으로 측정된 평점들을 아이템 간 유사도를 바탕으로 가중 평균하면 Item B에 대한 User 3의 평가 점수를 예측할 수 있을 것이다. 이와 같은 방식으로 측정된 모든 아이템에 대한 예측 평점 결과는 다음과 같다.
[그림 8] 원 평점 행렬과 예측 평점 행렬
사용자 기반 협업 필터링에 비해 아이템 기반 협업 필터링 방식이 다소 더 선호되는 경향이 있는데, 이는 비슷한 상품을 구매한 사용자들간의 취향이 비슷할 것이라는 무리한 전제를 하지 않아도 되기 때문이다. 그러나, 이러한 아이템 기반 협업 필터링 역시 연관규칙 분석을 통한 상품 추천과 마찬가지로 소비자의 취향이나 특성을 전혀 고려하지 못한다는 단점을 그대도 가지고 있다. 따라서, 아이템 기반 협업 필터링을 활용하는 개인화 추천 모델 구축 시에는 이러한 단점을 해결하기 위한 다양한 부가적인 방법을 모색하는 것이 바람직하다.
[3] 잠재요인 모델 기반 협업 필터링
잠재요인 모델 기반 협업 필터링 (Latent Factor Model-Based Collaborative Filtering)은 사용자-아이템 평점 행렬에 내재되어 있는 잠재요인 (Factor)을 추출하여, 이 잠재요인과 사용자 및 아이템 간의 관계를 바탕으로 평점 예측을 수행하는 알고리즘이다. 잠재요인 모델 기반 협업 필터링의 개념을 살펴보기 위해 다음과 같은 사용자-아이템 평점 행렬이 존재한다고 가정하자.
[그림 9] 사용자-아이템 평점 행렬 예시
이러한 사용자-아이템 간의 관계는 잠재요인을 추출할 수 있는 주성분분석 (Principle Component Analysis, PCA)이나 특이값 분해 (Singular Value Decomposition, SVD)와 같은 요인추출 기법을 사용하여 아래 그림과 같은 2개의 저차원 밀집 행렬을 얻을 수 있다. 이렇게 분해된 두 행렬의 내적을 통해 새로운 사용자-아이템 평점 행렬을 얻을 수 있다.
[그림 10] 예측 평점 행렬 도출 예시
만약, 위 예시가 영화에 대한 사용자 평점 데이터였다면 각 아이템은 개별 영화의 제목이고, 추출된 2개의 잠재요인은 영화의 장르라는 볼 수 있을 것이다. 가령, 요인 1은 코미디, 요인 2는 액션이라고 할 때, 사용자-잠재요인 행렬을 통해 User 1은 코미디에는 0.84, 액션에는 0.82 수준으로 선호하고 있다는 정보를 얻을 수 있으며, 잠재요인-아이템 행렬을 통해 Item A는 코미디 요인에 1.9, 액션 요인에 2.8 수준의 연관성을 가지고 있다고 해석할 수 있다. 따라서, User 1의 Item A에 대한 예측 평점은 요인 1(코미디)에 대한 선호도요인 1(코미디)과 Item A의 연관성+요인 2(액션)에 대한 선호도요인 2(액션)와 Item A의 연관성으로 계산할 수 있다.
잠재요인을 추출하여 행렬 분해를 하는 방법에는 PCA나 SVD 등 여러 방식이 사용될 수 있으나, SVD 방식이 가장 널리 사용된다.
연습
Surprise
Surprise는 파이썬 기반의 추천 시스템 구축을 위한 전용 라이브러리 중 하나로, 다양한 추천 알고리즘이 구현되어 있어 쉽게 추천 시스템을 구축할 수 있다. Surprsie 라이브러리는 추천 데이터 학습과 예측을 위한 fit( )과 predict( ) 함수, 그리고, 학습용 데이터 세트와 평가용 데이터 세트 분리를 위한 train_test_split( ) 함수 등 Scikit-Learn 라이브러리에서 제공하는 함수들과 유사한 함수들을 제공한다.
Surprise를 설치하기 위해서 Anaconda Prompt OS 창을 관리자 권한으로 실행하여 열고 다음의 코드를 입력한다.
pip install scikit-surprise
Surprise에 대한 자세한 설명은 http://surpriselib.com/에서 확인할 수 있다.
실습은 사용자 기반 협업필터링을 진행해보겠다.
1) 데이터
실습에서 사용할 데이터는 Surprise 라이브러리 내에서 제공하는 무비렌즈 (MovieLens) 데이터 중 1,000명의 사용자가 1,700편의 영화에 대해 평가한 총 10만 개의 평점 데이터 세트를 사용할 것이다. 무비렌즈는 다양한 기간에 걸쳐 수집된 다양한 크기의 데이터 세트를 제공하는데, 이중에서 Surprise는 ‘ml-100k’(10만 개의 평점 데이터)와 ‘ml-1m’(100만 개의 평점 데이터)을 로딩할 수 있는 함수를 제공한다. 아래 URL에 접속하면 무비렌즈의 다양한 데이터 세트를 다운받을 수 있다.
https://grouplens.org/datasets/movielens/
MovieLens
GroupLens Research has collected and made available rating data sets from the MovieLens web site ( The data sets were collected over various periods of time, depending on the size of the set. …
grouplens.org
#1. 모듈 및 함수 불러오기
from surprise import Dataset
#2. 데이터 로딩
data = Dataset.load_builtin('ml-100k')
import pandas as pd
ratings = pd.DataFrame(data.raw_ratings, columns=['user', 'item', 'rate', 'timestamp'])
ratings.head()
2) 모형 학습 및 예측
#1. 모듈 및 함수 불러오기
from surprise.model_selection import train_test_split
from surprise import KNNBasic
#2. 데이터 분할(학습용/평가용 데이터 세트)
trainset, testset = train_test_split(data, test_size=0.3, random_state=0)
#3. 모형 학습 및 예측
model = KNNBasic(name = 'cosine', user_base=True)
predictions = model.fit(trainset).test(testset)
predictions[:3]
3) 모형 평가
from surprise import accuracy
rmse = accuracy.rmse(predictions)
4) 고객별 추천 영화 리스트 출력
협업 필터링 모델링의 목적은 고객이 평가한 적이 없는 아이템에 대한 평점을 예측하고, 이를 기반으로 고객에게 적절한 아이템을 추천해주는 것이다. 이러한 작업을 자동으로 실행하는 함수가 따로 마련되어 있지는 않기 때문에 분석자가 적절한 코드를 직접 작성하여 고객별 추천 아이템을 도출해내야 한다. 본 실습에서는 recommend 라는 사용자 정의 함수를 만들어 고객별 추천 영화 리스트를 출력하였다.
#1. 함수 정의
def recommend(predictions, n, k):
print("-----고객별 추천 영화 리스트-----")
#2. n명의 고객ID 추출
uids = [pred.uid for pred in predictions][:n]
#3. 고객별 추천 리스트 출력
for uid in uids:
#3-1. 고객이 관람하지 않은 영화 추출
seen_movies = ratings[ratings.user== uid]['item'].tolist()
total_movies=movies['movie_id'].tolist()
unseen_movies=[movie for movie in total_movies if movie not in seen_movies]
#3-2. k개의 미관람 영화에 대한 평점 예측
pred=[model.predict(str(uid), str(item)) for item in unseen_movies]
pred.sort(key=lambda pred: pred[3], reverse=True)
top_pred=pred[:k]
#3-3. 예측 결과로부터 영화ID, 제목, 예측 평점 추출
top_ids = [int(pred.iid) for pred in top_pred]
top_titles = movies[movies.movie_id.isin(top_ids)]['title']
top_rating = [pred.est for pred in top_pred]
top_preds=[(id, title, rating) for id, title, rating in zip(top_ids, top_titles, top_rating)]
#3-4. 추천 리스트 출력
print("#고객ID:", uid)
for top_movie in top_preds:
print(top_movie[1], ":", top_movie[2])
#4. 함수 호출
recommend(predictions, 10, 3)
This post was written based on what I read and studied the book below.
http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9791195511747
댓글