| 알고리즘명 | 설명 | 예측정확도 | 계산속도(대규모데이터에서계산) | 콜드스타드 문제 대응 |
|---|---|---|---|---|
| 무작위 추천 | 무작위로 아이템을 추천한다. 베이스라인으로 사용하기도 함 | X | ◎ | O |
| 통계 정보나 특정 규칙 을 기반으로 추천 (인기도 추천등) | 베이스라인으로 자주 사용한다 | X | ◎ | O |
| 연관 규칙 | 간단한 계산 방법이고 SQL로도 구현할 수 있어 예전부터 널리 활용되고 있다. | O | O | X |
| 사용자-사용자 메모리 기반 방법 협조 필터링 | 위와 같음 | O | O | X |
| 회귀 모델 | 회구 문제로서 추천 태스크를 정식화하여 다양한 머신러닝 방법을 적용한다. | O | O | O |
| SVD(특잇값 분해) | 간단한 행렬분해 방법 | △ | △ | X |
| NFM(비음수 행렬 분해) | 비음수 제약을 추가한 행렬 분석 방법 | △ | △ | X |
| MF(Matrix Factorization) | 넷플릭스 프라이즈(Netfilix Prize)에서 좋 은 성적을 거둔 행렬 분해 방법 | O | O | X |
| IMF(Implicit Matrix Factorization) | 암묵적 평가값에 대응하는 행렬 분해 방법 | O | O | X |
| BRP(Bayesian Personalized Ranking | 암묵적 평갓값에 대응하며 순위를 고려한 행렬 분해 방법 | O | O | X |
| FM(Factorization Machines) | 평갓값 외에도 아이템과 사용자의 정보를 가미할 수 있는 방법 | O | O | O |
| LDA(콘텐츠 기반) | 아이템의 콘텐츠 정보에 토픽 모델을 적용해 추천하는 방법 | △ | △ | O |
| LDA(협조 필터링) | 사용자의 행동 이력에 토픽 모델을 적용해 추천하는 방법 | O | △ | X |
| word2vec(콘텐츠 기반) | 아이템의 콘텐츠 정보에 word2vec을 적 용해 추천하는 방법 | △ | O | X |
| item3vec(협조 필터링) | 사용자의 행동 이력에 word2vec을 적용 해 추천하는 방법 | O | O | X |
| 머신러닝 | 머신러닝 추천 방법 | O | △ | O |
| 파일명 | 설명 |
|---|---|
| movies.dat | 영화의 제목, 공개 연도, 장르 등의 정보, 이번 장에서는 id, title, genre만 사용한다 |
| tags.dat | 사용자가 각 영화에 부여한 태그 정보(사용자 ID, 영화 ID, 태그, 타임스탬프) 형식 |
| ratings.dat | 사용자가 각 영화에 부여한 평갓값 데이터(사용자 ID, 영화 ID, 평갓값, 타임스탬프) 형식 |
from util.models import RecommendResult, Dataset
from src.base_recommender import BaseRecommender
from collections import defaultdict
import numpy as np
np.random.seed(0)
class RandomRecommender(BaseRecommender):
def recommend(self, dataset: Dataset, **kwargs) -> RecommendResult:
# 사용자 ID와 아이템 ID에 대해 0부터 시작하는 인덱스를 할당한다
unique_user_ids = sorted(dataset.train.user_id.unique())
unique_movie_ids = sorted(dataset.train.movie_id.unique())
user_id2index = dict(zip(unique_user_ids, range(len(unique_user_ids))))
movie_id2index = dict(zip(unique_movie_ids, range(len(unique_movie_ids))))
# 사용자 x 아이템의 행렬에서 각 셀의 예측 평갓값은 0.5~5.0의 균등 난수로 한다
pred_matrix = np.random.uniform(0.5, 5.0, (len(unique_user_ids), len(unique_movie_ids)))
# rmse 평가용으로 테스트 데이터에 나오는 사용자와 아이템의 예측 평갓값을 저장한다
movie_rating_predict = dataset.test.copy()
pred_results = []
for i, row in dataset.test.iterrows():
user_id = row["user_id"]
# 테스트 데이터의 아이템 ID가 학습용으로 등장하지 않는 경우도 난수를 저장한다
if row["movie_id"] not in movie_id2index:
pred_results.append(np.random.uniform(0.5, 5.0))
continue
# 테스트 데이터에 나타나는 사용자 ID와 아이템 ID의 인덱스를 얻어, 평갓값 행렬값을 얻는다
user_index = user_id2index[row["user_id"]]
movie_index = movie_id2index[row["movie_id"]]
pred_score = pred_matrix[user_index, movie_index]
pred_results.append(pred_score)
movie_rating_predict["rating_pred"] = pred_results
# 순위 평가용 데이터 작성
# 각 사용자에 대한 추천 영화는, 해당 사용자가 아직 평가하지 않은 영화 중에서 무작위로 10개 작품으로 한다
# 키는 사용자 ID, 값은 추천 아이템의 ID 리스트
pred_user2items = defaultdict(list)
# 사용자가 이미 평가한 영화를 저장한다
user_evaluated_movies = dataset.train.groupby("user_id").agg({"movie_id": list})["movie_id"].to_dict()
for user_id in unique_user_ids:
user_index = user_id2index[user_id]
movie_indexes = np.argsort(-pred_matrix[user_index, :])
for movie_index in movie_indexes:
movie_id = unique_movie_ids[movie_index]
if movie_id not in user_evaluated_movies[user_id]:
pred_user2items[user_id].append(movie_id)
if len(pred_user2items[user_id]) == 10:
break
return RecommendResult(movie_rating_predict.rating_pred, pred_user2items)
if __name__ == "__main__":
RandomRecommender().run_sample()
다음과 같은 통계 정보나 규칙에 기반해 추천하는 것을 생각한다
서비스의 데이터 통계 정보나 아이템 속성 정보에 기반해 나열하는 추천은 특정 사용자에게 의존하지 않는 정보에 기반해 아이템을 나열하여 추천하므로 기본적으로 개인화를 수행하지 않는 알고리즘
기본적인 통계 데이터나 아이템 속성 정보는 추천 시스템의 콘텍스트에 관계없이 시스템이 갖고 있는 것이 많으며 다루기 쉬운 데이터이므로 구현하기가 비교적 쉽다고 할 수 있다.
비교적 단순한 알고리즘을 사용한 추천은 해당 아이템이 어떤 구조로 추천되는지 사용자가 알기 쉽다는 특징이 있다
예) '지난달 판매 순위' 라고 했을 때 가장 위에 추천된 아이템은 지난달 가장 많이 판매된 아이템일 것
사용자가 추천 이유를 쉽게 알 수 있도록 했을 때 사용자의 구매 행동과 연결되는 경우가 많기에 고려해야함
사용자의 속성 정보를 기반으로 다른 아이템을 추천하는 경우, 사용자의 속성 정보를 기반으로 상요자를 몇 가지 세그먼트로 나눔으로써 각각의 사용자 세그먼트에 적합하게 추천을 진행
예) 전자상거래 사이트에서 프로필을 남성으로 선택한 사용자에게는 서비스 안에서도 마찬가지로 남성을 선택한 다른 사용자들이 자주 열람하는 순서대로 아이템을 추천한다.
-> 성별에 관계없이 모든 사용자가 잘 열람하는 순서로 아이템을 추천하는 것 보다 흥미가 있는 아이템을 추천할 수 있음
사용자의 나이, 성별, 거주지 등의 인구 통계학적 데이터에 기반해 아이템을 추천하는 것을 데모그래픽 필터링(demographic filtering)이라고 한다.
데모그래픽 필터링에서는 사용자의 속성 정보별로 아이템을 추천하는 것만으로도 어느 정도 흥미가 있는 것을 추천할 가능성이 존재
주의점
서비스나 사용자의 성질에 따라 데모그래픽 정보를 일부러 입력하지 않거나 경우에 따라 잘못된 정보가 입력될 수도 있다
예) 아마존 등의 전자상거래 사이트에서 굳이 사용자가 자신의 성별이나 나이를 입력하는 일은 많지 않을 수 있다
매칭 서비스와 같이 비교적 능동적으로 프로필을 입력하는 경향이 있는 서비스라 하더라도 프로필을 잘 입력하지 않거나 자신을 보다 돋보이게 하기 위해 허위 정보를 입력하기도 함
공평성관점에서 데모그래픽 데이터를 사용할 때 주의해야함
예) 사용자에게 성별 등을 묻는 것 자체가 문제될 수 있다
그리고 남성이니까 또는 여성이니까 같은 사고 방식은 설령 그것이 통계적인 경향을 갖고 있다하더라도 그 경향을 서비스 지표 개선 등의 목적으로 사용할 수는 없다
그리고 의도치 않게 그런 정보를 사용했다가 문제가 되기도 한다.
예) 아마존은 채용 과정에서 지원자의 프로필 정보가 회사와 얼마나 매치되는지 머신러닝으로 산출 후 스크리닝에 사용했다
하지만 후보자의 성별에 따라 채용 시험 합격률에 큰 차이가 있었다는 사실이 발각되어 문제가 되었다
사용자의 데모그래픽 정보라는 것은 개발자가 특정 정보를 사용하지 않았어도 공평성 관점에서 문제가 될 수 있어 사용 시 세심한 주의가 필요하다.
항상 좋은 글 감사합니다.