juooo1117

Recommender System 본문

Artificial Intelligence

Recommender System

Hyo__ni 2023. 12. 18. 13:50

Recommender System

고객의 기호를 바탕으로 아이템(상품)을 추천하는 시스템. 추천 시스템은 개인 또는 그룹의 기호를 기반으로 작동한다.

 

Collaborative Filtering(CF)

  -  추천 대상인 사용자와 비슷한 취향을 가진 다른 사람들이 선택한 아이템을 추천하는 시스템

  -  과거의 구매 이력을 봤을 때, A와 B의 이력이 비슷하다면 A에게 B가 구매한 다른 상품을 추천

  -  기본적으로 사용자가 아이템들에 대해 평가한 데이터가 필요하다. 지금까지 나와 비슷한 행동을 한(아이템 구매 or 평가) 사람은 앞으로도 그럴 것이라는 가정 하에 진행된다.

 

Nearest Neighbor Recommendation

평가 패턴으로 판단해서 가장 비슷한 사용자를 선택하여 그 사람이 Item5에 대해 평가한 점수를 반영한다. 만약, 여러명의 사용자가 선택이 된다면 그 점수들의 평균을 사용한다.

 

similarity metric 을 어떻게 측정할 것인가?

Correlation Analysis

두 명의 사용자의 유사도를 분석하기 위해서 상관 관계를 사용한다. 양쪽 모두 평가한 아이템만 계산에 사용된다.

Aggregation

유사한 사용자의 점수를 종합하여 현재 예측 대상 사용자(u)의 새로운 아이템(i)에 대한 점수를 예측한다.

 

Weights

유사도 계산시에 각 아이템의 중요도가 다를 수 있다. 대부분의 사람들이 선호하는 아이템의 경우에는 취향을 판단할 때 변별력이 없기 때문에, 이를 반영해 주기 위해서 이러한 아이템은 weight를 낮춰서 줄 수 있다.

현재 예측 대상 사용자와 평가 아이템 종류가 별로 겹치지 않는 사용자는 중요하지 않을 가능성이 높다. 따라서 significance weight를 추가해서 이러한 사용자에 대한 점수를 낮춘다. 예를 들어 공동으로 평가한 아이템이 일정 개수 이하일 때 패널티를 부여한다.

 

Collaborative filtering의 문제점

  -  Cold start: 데이터에 충분한 사용자와 아이템 정보가 존재해야 한다. 신규 사용자나 아이템이 점수를 가지고 있지 않다면, 그 사용자에 대해 미리 점수를 예측하고 이후에 다른 사용자에 대한 추천을 수행하면 된다.

  -  Sparsity: 많은 사용자가 존재한다고 하더라도, 추천 대상인 아이템이 너무 많다면 user/rating matrix는 매우 sparse함 (같은 상품을 평가한 사용자들을 찾기가 어려울 수 있음)

  -  First rater: 평가가 없는 아이템에 대해서는 추천할 수 없음 (신규아이템이나 소수만이 좋아하는 아이템)

  -  Popularity Bias: 독특한 기호를 갖고 있는 사용자에게 제대로 추천하기가 어려움 (일반적으로 인기가 많은 아이템을 추천하게 된다)

 

 

Contents-Based(CB) Recommender System

  -  개인의 기호를 반영하여 추천해 주는 시스템

  -  A라는 사람이 어떤 장르의 영화를 좋아하는 지 판단해서 추천

  -  아이템은 다양한 속성으로 표현되며, 이러한 정보들을 사용한다. (e.g. 영화라면 감독, 배우, 장르, 줄거리, 음악 ... )

  -  각 사용자별로 예측 모델을 학습하여 신규 아이템들에 대한 선호도를 예측한다.

 

CB의 특징 (장점/단점)

장점: 다른 사용자에 대한 데이터가 필요하지 않고, cold start 문제가 크지 않다. 또한 대규모 matrix 데이터를 구축하고 이에 대한 연산을 수행할 필요가 없고, 내용 기반이라서 유명한 아이템만이 추천되는 문제점이 발생하지 않는다.  

단점: 주어진 데이터에 맞게 feature engineering이 필요하다. 만약 사용자가 특정 분야에 대해서만 평가를 했다면, 그 분야에서만 추천이 이루어진다. (Filter bubble 문제!) 신규 사용자에 대해서는 해당 사용자의 데이터가 쌓일 때까지의 추천은 어렵다.

 

 

Hybrid Recommender System

Content-Based → Collaborative filtering

다양한 아이템에 대해 많은 평가 점수를 가지고 있는 사용자에 대해서 우선 content-based 추천을 수행하고, 이 결과를 이용해서 다른 user를 위한 collaborative filtering을 수행한다.

 

Collaborative filtering → Content-Based

collaborative filtering을 사용하여 다른 사용자들의 점수로부터 contents의 features 값들을 획득할 수 있다.

 

Recommenders with TensorFlow

movielens/100k datasets를 이용해서 간단한 matrix factorization model을 구축해 보자

이 모델을 사용자에게 영화를 추천해 주는 일에 사용할 수 있다.

CF recommendation with NMF: NMF 수행 후에, 점수를 매기지 않은 영화에 대해서 WH를 계산해서 역으로 예측하는 방법이다.

# build vocabularies

user ids & movie titles 을 embedding layer에 넣기 위해서 정수 인덱스로 변환한다.

ratings = tfds.load('movielens/100k-ratings', split="train")
movies = tfds.load('movielens/100k-movies', split="train")

ratings = ratings.map(lambda x: {"movie_title": x["movie_title"],   # 평점
    							 "user_id": x["user_id"]})
movies = movies.map(lambda x: x["movie_title"])                     # 영화이름

# build vocabularies
user_ids_vocabulary = tf.keras.layers.StringLookup(mask_token=None)
user_ids_vocabulary.adapt(ratings.map(lambda x: x["user_id"]))

movie_titles_vocabulary = tf.keras.layers.StringLookup(mask_token=None)
movie_titles_vocabulary.adapt(movies)

# define a model

inheriting from tfrs.Model  →  Define the two models and the retrieval task.

class MovieLensModel(tfrs.Model):
  def __init__(self,
      		   user_model: tf.keras.Model,
      		   movie_model: tf.keras.Model,
      		   task: tfrs.tasks.Retrieval):
    super().__init__()

    self.user_model = user_model
    self.movie_model = movie_model
    self.task = task                # Set up a retrieval task.

  def compute_loss(self, features: Dict[Text, tf.Tensor], training=False) -> tf.Tensor:
    user_embeddings = self.user_model(features["user_id"])
    movie_embeddings = self.movie_model(features["movie_title"])

    return self.task(user_embeddings, movie_embeddings)
    
# Define user and movie models.
user_model = tf.keras.Sequential([user_ids_vocabulary,
    			tf.keras.layers.Embedding(user_ids_vocabulary.vocab_size(), 64)])
movie_model = tf.keras.Sequential([movie_titles_vocabulary,
    			tf.keras.layers.Embedding(movie_titles_vocabulary.vocab_size(), 64)])
# Define your objectives.
task = tfrs.tasks.Retrieval(metrics=tfrs.metrics.FactorizedTopK(
    			movies.batch(128).map(movie_model)))

# model fit and evaluation

Use brute-force search to set up retrieval using the trained representations.

즉, 가능한 모든 경우의 수를 체크하여 답을 찾는 방법을 의미 (완전탐색)

# Create a retrieval model.
model = MovieLensModel(user_model, movie_model, task)
model.compile(optimizer=tf.keras.optimizers.Adagrad(0.5))
model.fit(ratings.batch(4096), epochs=3)

# Use brute-force search to set up retrieval using the trained representations.
index = tfrs.layers.factorized_top_k.BruteForce(model.user_model)
index.index_from_dataset(
    movies.batch(100).map(lambda title: (title, model.movie_model(title))))

# Get some recommendations.
_, titles = index(np.array(["42"]))
print(f"Top 3 recommendations for user 42: {titles[0, :3]}")

# recommendations

선택된 사용자를 위한 top 3 영화제목을 추천해 준다. 

e.g. Top 3 recommendations for user 42:

[b'Rent-a-Kid (1995)' b'Land Before Time III: The Time of the Great Giving (1995) (V)' b'Just Cause (1995)']