본문 바로가기

R/R로 만드는 추천 시스템

추천 시스템 - 05

반응형

사용자 기반 협업 필터링

이전 절에서 알고리즘은 아이템을 기반으로 했으며 추천 항목을 선별하는 단계는 다음과 같다.

  • 같은 사람들이 구매한 것과 유사한 아이템 선별
  • 새 사용자에게는 구매했던 것과 비슷한 아이템을 추천

이 절에서는 반대의 방법을 사용한다. 먼저 새로운 사용자가 생기면 유사한 사용자를 선별한다. 그런 다음 유사한 사용자가 구매해 좋은 평점을 준 아이템을 추천한다. 이 방법을 사용자 기반 협업 필터링이라고 한다. 새로운 사용자에 대해서는 다음 단계가 있다.

  1. 각 사용자가 새로운 사용자와 얼마나 유사한지 측정한다. IBCF와 마찬가지로 주로 사용되는 유사도 측정 방법은 상관관계 및 코사인이다.
  2. 가장 유사한 가용자를 선별한다. 옵션은 다음과 같다.
    -상위 k명의 사용자(k-nearest_neighbors)를 고려한다.
    -정의된 임계 값을 초과하는 유사도의 사용자를 고려한다.
  3. 가장 유사한 사용자가 구매한 아이템들에 평점을 매긴다. 평점은 유사한 사용자 간의 평균 평점이며 접근 방식은 다음과 같다.
    -평균 평점
    유사도를 가중치로 사용하는 가중 평균 평점
  4. 최고 평점 아이템을 선별한다.

이전 장에서 했던 것처럼 트레이닝 및 테스트 세트를 만든다. 그러면 이제 모델을 직접 생성할 수 있다.

 

추천 모델 생성

모델을 생성하는 R 명령은 이전 장과 동일하다. 이제 이 기법을 UBCF라고 부르자.

recommender_models <- recommenderRegistry$get_entries(dataType = "realRatingMatrix")
recommender_models$UBCF_realRatingMatrix$parameters
$method
[1] "cosine"

$nn
[1] 25

$sample
[1] FALSE

$normalize
[1] "center"

 

관련 매개변수는 다음과 같다.

  • method : 사용자 간의 유사도를 계산하는 방법
  • nn : 유사한 사용자의 수

매개변수를 기본값으로 하는 추천 모델을 생성해본다.

recc_model <- Recommender(data = recc_data_train, method = "UBCF")
recc_model
Recommender of type ‘UBCF’ for ‘realRatingMatrix’ 
learned using 116 users.

getModel을 사용해 모델에 대한 세부 정보를 추출해본다.

model_details <- getModel(recc_model)

모델의 구성 요소를 살펴본다.

names(model_details)
[1] "description" "data"        "method"      "nn"          "sample"      "normalize"   "verbose"    

model_details에는 model의 설명과 매개변수 외에 다음과 같은 데이터 정보가 포함돼 있다.

model_details$data
116 x 332 rating matrix of class ‘realRatingMatrix’ with 12495 ratings.
Normalized using center on rows.

model_details$data 객체는 평점 매트릭스를 포함한다. UBCF는 사후 학습 기법이므로 예측을 수행하기 위해 모든 데이터에 액세스해야 하기 때문이다.

 

테스트 세트에 추천 모델 적용

IBCF와 같은 방식으로 각 신규 사용자에 대한 상위 여섯 개의 추천 항목을 결정할 수 있다.

recc_predicted <- predict(object = recc_model,
+                           newdata = recc_data_test,
+                           n = n_recommended)
recc_predicted
Recommendations as ‘topNList’ with n = 6 for 444 users.

테스트 세트 사용자에 대해 추천 항목이 있는 매트릭스를 정의할 수 있따.

recc_matrix <- sapply(recc_predicted@items, function(x){colnames(ratings_movies)[x]})
dim(recc_matrix)
[1]   6 444

처음 네 명의 사용자를 살펴보자.

recc_matrix[, 1:4]
     2                                  3                                  5                          7                         
[1,] "Usual Suspects, The (1995)"       "Fargo (1996)"                     "Good Will Hunting (1997)" "Titanic (1997)"          
[2,] "Godfather: Part II, The (1974)"   "Star Wars (1977)"                 "Contact (1997)"           "L.A. Confidential (1997)"
[3,] "Boot, Das (1981)"                 "Casablanca (1942)"                "Titanic (1997)"           "Lone Star (1996)"        
[4,] "Graduate, The (1967)"             "Silence of the Lambs, The (1991)" "Godfather, The (1972)"    "Good Will Hunting (1997)"
[5,] "Princess Bride, The (1987)"       "Godfather, The (1972)"            "Game, The (1997)"         "Big Night (1996)"        
[6,] "Silence of the Lambs, The (1991)" "African Queen, The (1951)"        "Trainspotting (1996)"     "Close Shave, A (1995)"   

또한 각 영화가 추천된 횟수를 계산하고 관련 빈도 막대 그래프를 작성할 수 있다.

number_of_items <- factor(table(recc_matrix))
chart_title <- "Distribution of the number of items for UBCF"

분포도를 작성해본다.

qplot(number_of_items) + ggtitle(chart_title)

다음 그림은 UBCF를 위한 아이템 수의 분포를 표시한다.

IBCF와 비교할 떄 분포도의 꼬리가 길다. 즉, 다른 영화들보다 훨씬 더 자주 추천되는 영화가 있음을 의미한다. 최댓값은 26며 IBCF는 11로서 대비된다.

 

상위권 제목을 살펴본다.

number_of_items_sorted <- sort(number_of_items, decreasing = TRUE)
number_of_items_top <- head(number_of_items_sorted, n = 4)
table_top <- data.frame(names(number_of_items_top), number_of_items_top)
table_top
                           names.number_of_items_top. number_of_items_top
Godfather, The (1972)           Godfather, The (1972)                 152
Boot, Das (1981)                     Boot, Das (1981)                 143
Good Will Hunting (1997)     Good Will Hunting (1997)                 142
Usual Suspects, The (1995) Usual Suspects, The (1995)                 117

 

UBCF와 IBCF의 결과를 비교하면 알고리즘을 이해하는 데 도움이 된다. UBCF는 초기 데이터에 액세스해야 하므로 사후 학습 모델이다. 전체 데이터베이스를 메모리에 저장해야 하므로 큰 평점 매트릭스가 있는 경우 제대로 작동하지 않는다. 또한 유사도 매트릭스를 생성하기 위해서는 많은 게산 능력과 시간이 필요하다.

그러나 UBCF는 IBCF보다 좀 더 정확하다는 것이 입증됐으므로 데이터 세트가 너무 크지 않은 경우 좋은 추천 모델이다.

 

이진 데이터에 대한 협업 필터링

이전 두 절에서는 데이터가 각 구매에 대한 평점을 나타내므로 사용자 선호를 기반으로 추천 모델을 생성했다. 그러나 이 정보를 항상 사용할 수 있는 것은 아니다. 다음과 같은 두 가지 시나리오가 발생할 수 있다.

  • 어떤 아이템을 구매했는지 알지만 평점을 알지는 못한다.
  • 각 사용자에 대해 구매한 아이템을 알 수는 없지만 좋아하는 아이템은 알고있다.

이러한 맥락에서 사용자가 아이템을 구매하면(또는 좋아하면) 값이 1이고 그렇지 않으면 0이 되는 사용자-아이템 매트릭스를 작성할 수 있다. 이 경우 기법은 마찬가지로 아이템 기반 및 사용자 기반이지만 이제까지와는 다른 방식으로 처리해야 한다.

 

여기서는 ratings_movies부터 시작해 사용자가 영화를 본 경우 값 1, 그렇지 아니면 0이 되는 ratings_movies_watched 매트릭스를 만들 수 있다. 우리는 그것을 앞 절(데이터 이진화)에서 다뤘다.

 

데이터 준비

binarize 함수를 사용해 ratings_movies_watched를 만들 수 있다.

ratings_movies_watched <- binarize(ratings_movies, minRating = 1)

 

데이터를 간단히 살펴본다. 각 사용자가 얼마나 많은 영화를 봤는지 나타내는 분포도를 작성해본다.

qplot(rowSums(ratings_movies_watched)) +
  stat_bin(binwidth = 10) +
  geom_vline(xintercept = mean(rowSums(ratings_movies_watched)), col = "red", linetype = "dashed") +
  ggtitle("Distribution of movies by user")

 

다음 그림은 사용자별 영화 분포를 보여준다.

평균적으로 각 사용자는 약 100편의 영화를 봤고 단지 소수만 200편의 영화를 봤다.

추천 모델을 만들기 위해 트레이닝 및 테스트 세트를 정의해본다.

which_train <- sample(x = c(TRUE, FALSE), size = nrow(ratings_movies),
                      replace = TRUE, prob = c(0.8, 0.2)) 

recc_data_train <- ratings_movies[which_train, ]
recc_data_test <- ratings_movies[!which_train, ]

이제 IBCF 및 UBCF 모델을 만들 준비가 됐다.

 

이진 데이터에 대한 아이템 기반 협업 필터링 

IBCF의 첫 번째 단계는 아이템 간의 유사도를 정의하는 것이다. 이진 데이터의 경우 상관관계와 코사인 같은 거리가 제대로 동작하지 않는다. 다른 좋은 대안으로 Jaccard 인덱스가 있따. 두 아이템이 있을 때 인덱스는 두 아이템을 모두 구매한 사용자 수를 그중 최소 하나 이상 구매한 사용자 수로 나눈 값으로 계산한다. 

이전과 같은 명령어를 사용해 IBCF 모델을 만들 수 있따. 유일한 차이점은 method에 매개변수로 Jaccard를 입력하는 것이다.

recc_model <- Recommender(data = recc_data_train,
                          method = "IBCF", parameter = list(method = "Jaccard"))
model_details

$description
[1] "UBCF-Real data: contains full or sample of data set"

$data
116 x 332 rating matrix of class ‘realRatingMatrix’ with 12495 ratings.
Normalized using center on rows.

$method
[1] "cosine"

$nn
[1] 25

$sample
[1] FALSE

$normalize
[1] "center"

$verbose
[1] FALSE

 

이전 절과 마찬가지로 테스트 세트에서 각 사용자에게 여섯 개의 아이템을 추천할 수 있다.

n_recommended <- 6
recc_predicted <- predict(object = recc_model, newdata = recc_data_test,
                          n = n_recommended)
recc_matrix <- sapply(recc_predicted@items, function(x){colnames(ratings_movies)[x]})

처음 네 명의 사용자에 대한 추천 사항을 살펴본다.

head(recc_matrix, 4)
$`11`
[1] "Down Periscope (1996)"    "Craft, The (1996)"        "Leaving Las Vegas (1995)" "Scream (1996)"           
[5] "Titanic (1997)"           "Toy Story (1995)"        

$`22`
[1] "Twelve Monkeys (1995)"     "Toy Story (1995)"          "Mr. Holland's Opus (1995)" "Birdcage, The (1996)"     
[5] "Fargo (1996)"              "Jerry Maguire (1996)"     

$`28`
[1] "GoldenEye (1995)"        "Get Shorty (1995)"       "Babe (1995)"             "Dead Man Walking (1995)" "Mighty Aphrodite (1995)"
[6] "Postino, Il (1994)"     

$`42`
[1] "Babe (1995)"             "Dead Man Walking (1995)" "Seven (Se7en) (1995)"    "Postino, Il (1994)"      "Braveheart (1995)"      
[6] "Taxi Driver (1976)"  

 

이 방식은 평점 매트릭스를 사용하는 IBCF와 유사하지만 평점을 고려하지 않기 평점을 고려하지 않기 떄문에 결과는 덜 정확하다.

 

이진 데이터에 대한 사용자 기반 협업 필터링

IBCF와 마찬가지로 UBCF에도 Jaccard 인덱스를 사용해야 한다. 두 사용자가 주어진 경우, 인덱스는 두 사용자 모두 구매한 아이템의 수를 적어도 그들 중 한 명 이상 구매한 아이템의 수로 나눈 값으로 계산된다.

 

추천 모델을 만들어 본다.

recc_model <- Recommender(data = recc_data_train,
                          method = "UBCF", parameter = list(method = "Jaccard"))

 

IBCF에서도 같은 명령어를 사용해 각 사용자에게 여섯 편의 영화를 추천하고, 처음 네 명의 사용자를 살펴본다.

n_recommended <- 6
recc_predicted <- predict(object = recc_model, newdata = recc_data_test,
                          n = n_recommended)

recc_matrix <- sapply(recc_predicted@items,
                      function(x){colnames(ratings_movies)[x]})
dim(recc_matrix)
[1]   6 126

recc_matrix[ ,1:4]
     11                               22                                 28                          42                         
[1,] "Star Wars (1977)"               "Fargo (1996)"                     "Raising Arizona (1987)"    "Fargo (1996)"             
[2,] "Raiders of the Lost Ark (1981)" "Pulp Fiction (1994)"              "Dead Man Walking (1995)"   "Pulp Fiction (1994)"      
[3,] "Return of the Jedi (1983)"      "Usual Suspects, The (1995)"       "Return of the Jedi (1983)" "Raising Arizona (1987)"   
[4,] "This Is Spinal Tap (1984)"      "Dead Man Walking (1995)"          "Close Shave, A (1995)"     "Dead Man Walking (1995)"  
[5,] "Close Shave, A (1995)"          "Close Shave, A (1995)"            "Brazil (1985)"             "This Is Spinal Tap (1984)"
[6,] "L.A. Confidential (1997)"       "Silence of the Lambs, The (1991)" "L.A. Confidential (1997)"  "Close Shave, A (1995)"  

 

결과가 IBCF와는 다르다.

 

이 기법들은 0이 누락된 값으로 가정한다. 그러나 이진 매트릭스만 다루는 기법에서는 나쁜 평점으로 취급하는 옵션도 있다.

사용자 대부분이 아이템에 평점을 부여하지 않을 경우와 같이, 0-1 매트릭스의 여러가지 실생활 사례가 있다. 그러나 이러한 맥락에서 추천 시스템을 만드는 방법을 아는 것이 중요하다.

 

협업 필터링에 대한 결론

이 책은 추천 시스템에서 가장 대중적인 기법의 하나인 협업 필터링을 중심적으로 다루고 있따. 또한 recommenderlab에서는 협업 필터링만 지원된다.

그러나 협업 필터링이 항상 가장 적합한 기법은 아니다. 이 장에서는 협업 필터링의 한계와 몇 가지 대안의 개요를 살펴본다.

 

협업 필터링의 한계

협업 필터링에는 몇 가지 제한 사항이 있다. 새로운 사용자 또는 새 아이템을 처리할 때 알고리즘에 다음과 같은 문제가 발생한다.

  • 새로운 사용자가 아직 영화를 보지 못했다면 IBCF와 UBCF 모두 어느 아이템에도 추천할 수 없다. IBCF는 기존 사용자가 새로운 사용자와 유사한 선호도를 가졌는지 알아야 하지만 영화 평점에 대해 알지 못한다.
  • 새 아이템을 다른 사람이 구매하지 않은 경우에는 절대로 추천되지 않는다. IBCF의 경우, 같은 사용자가 구매했던 아이템들과 맞춰보더라도 다른 것들과 새 아이템이 일치하지 않을 것이다. UBCF는 유사한 사용자가 구매한 아이템들을 각 사용자에게 추천한다. 하지만 아무도 새 아이템을 구매하지 않았다면 알고리즘은 누구에게도 추천하지 않을 것이다.

따라서 새로운 아이템이 추천 대상에 포함되지 않을 수 있으며, 이런 제약을 콜드 스타트 문제라고 부른다. 새로운 사용자 또는 아이템을 포함시키려면 사용자 프로필 및 아이템 설명과 같은 다른 정보도 고려해야 한다.

협업 필터링의 또 다른 한계는 평점 매트릭스만 고려한다는 것이다. 많은 경우 추천 성능을 향상할 수 있는 몇 가지 추가 정보가 있다. 덧붙이면, 사용자 선호도는 항상 사용할 수 있는 것은 아니며 불완전할 수도 있다.

다음 절에서는 몇 가지 다른 접근법을 살펴본다.

 

콘텐츠 기반 필터링

또 다른 대중적인 기법은 콘텐츠 기반 필터링이다. 알고리즘은 아이템에 대한 세부 정보로 시작되고 동시에 다른 사용자들을 고려할 필요가 없다. 각 사용자에 대해 알고리즘은 과거 구매와 유사한 아이템을 추천한다.

다음은 추천을 수행하는 단계다.

  1. 아이템의 세부 정보를 정의한다.
  2. 구매를 기반으로 사용자 프로필을 정의한다.
  3. 각 사용자에게 프로필과 일치하는 아이템을 추천한다.

사용자 프로필은 구매를 기반으로 하므로 알고리즘은 과거에 구매했던 것과 비슷한 아이템을 추천한다.

 

하이브리드 추천 시스템

많은 상황에서 서로 다른 협업 기반 필터링과 콘텐츠 기반 필터링으로 모델을 만들 수 있다. 동시에 두 개 모두를 고려한다면 어떨까? 머신 러닝에서는 서로 다른 모델을 결합하는 방식이 더 좋은 결과를 보이기도 한다.

간단한 예는 사용자 및 아이템에 대한 정보가 결합한 협업 필터링이다. IBCF의 경우 아이템 간 유사도는 사용자 선호도와 아이템 정보가 동시에 고려될 수 있따. UBCF에서도 사용자 간 유사도는 선호도와 개인정보를 고려할 수 있다.

 

추천 시스템에서는 이러한 모델을 하이브리드라고 부르며 협업 필터링 모델을 결합하는 다양한 방법들이 있다.

병렬 하이브리드 시스템은 추천 모듈을 병렬로 각각 실행하고 그 결과를 결합한다. 다음과 같은 몇 가지 옵션이 있다.

  • 각 사용자에 대한 추천 결과들 중 하나를 선택하는 규칙을 정의한다. 규칙은 사용자 프로필 또는 추천 내용을 기반으로 할 수 있다.
  • 여러 추천 결과들 순위의 평균을 계산하고 그 평균에 가중치를 적용할 수 있다.

파이프라인 하이브리드 시스템은 서로 다른 추천 시스템들을 차례대로 수행한다. 각 추천 시스템의 결과는 다른 추천 시스템의 입력 값으로 반영된다.

 

모놀리식 하이브리드 시스템은 동일한 추천 알고리즘 내에서 다양한 방식으로 수행한 결과를 통합한다. 몇 가지 옵션은 다음과 같다.

  • 특징 조합 : 다양한 유형의 입력 정보를 조합한다. 예를 들면, 알고리즘은 평점, 사용자 프로필, 아이템 세부 정보를 고려할 수 있따.
  • 특징 확대 : 다른 데이터 정보를 결합해 추천 모듈의 입력 정보를 만든다.

지식 기반 추천 시스템

협업 기반 필터링 및 콘텐츠 기반 필터링이 작동되지 않는 상황들이 있다.

 

이러한 맥락에서 우리는 사용자와 제품에 대한 명확한 지식과 추천 기준을 사용할 수 있다. 이 기법들의 한 분야를 지식 기반이라고 부른다. 여기에는 다양한 기법들이 있으며, 데이터 및 비즈니스 상황에 따라 다르다. 이러한 이유로 몇 가지 기법들로 서로 다른 상황에서 적용할 수 있도록 정의하기는 어렵다.

 

요약

추천을 위한 다양한 기법 중에서 협업 필터링이 가장 구현하기 쉽다. 또한 상황에 따라 다른 콘텐츠 기반 필터링 알고리즘은 여전히 R로도 구현해볼 수 있다.

 

이 장에서는 협업 필터링에 중점을 두면서 추천 시스템에 대한 다양한 접근 방식을 보여줬다. 다음 장에서는 추천 기법들을 테스트하고 평가하는 방법을 설명한다.

반응형

'R > R로 만드는 추천 시스템' 카테고리의 다른 글

추천 시스템의 평가 - 02  (0) 2020.03.24
추천 시스템의 평가 - 01  (0) 2020.03.24
추천 시스템 - 04  (0) 2020.03.19
추천 시스템 - 03  (0) 2020.03.19
추천 시스템 - 02  (0) 2020.03.17