본문 바로가기

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

추천 시스템의 평가 - 02

반응형

데이터 부트스트랩

이전 절에서는 데이터를 두 부분으로 나눴고 트레이닝 세트에는 행의 80%가 포함됐다. 대신에 복우너 추출을 한다면 어떻게 될까? 같은 사용자가 여러번 포함될 수 있으므로 트레이닝 세트는 이전과 같은 크기를 가지고 있지만, 테스트 세트에는 더 많은 사용자가 포함된다. 이러한 방법을 부트스트래핑이라 하며 recommenderlab 패키지에서 지원한다. evaluationScheme 함수의 매개변수는 이전 방법과 거의 유사하지만, 차이점은 [method = "split"] 대신 [method = "bootstrap"]으로 지정한다는 것이다.

percentage_training <- 0.8
items_to_keep <- 15
rating_threshold <- 3
n_eval <- 1
eval_sets <- evaluationScheme(data = ratings_movies, method = "bootstrap",
                              train = percentage_training, given = items_to_keep,
                              goodRating = rating_threshold, k = n_eval)

트레이닝 세트의 사용자 수는 여전희 전체 데이터의 80%다.

nrow(getData(eval_sets, "train")) / nrow(ratings_movies)
[1] 0.8

하지만 테스트 세트의 아이템들은 이전과 같지 않다.

perc_test <- nrow(getData(eval_sets, "known")) / nrow(ratings_movies)
> perc_test
[1] 0.4375

테스트 세트는 이전보다 두 배 이상 커졌다.

트레이닝 세트에서 고유한 사용자를 확인할 수 있다.

length(unique(eval_sets@runsTrain[[1]]))
[1] 315

트레이닝 세트의 고유한 사용자의 백분율은 다음과 같이 테스트 세트의 사용자 백분율과 보완적이어야 한다.

perc_train <- length(unique(eval_sets@runsTrain[[1]])) / nrow(ratings_movies)
perc_train + perc_test
[1] 1

트레이닝 세트에서 사용자별로 얼마나 반복됐는지 셀 수 있다.

table_train <- table(eval_sets@runsTrain[[1]])
n_repetitions <- factor(as.vector(table_train))
qplot(n_repetitions) + ggtitle("Number of repetitions in the traing set")

다음의 도표는 트레이닝 세트의 사용자 반복 횟수를 나타낸다.

사용자 대부분은 네 번 미만으로 샘플링 됐다.

 

k-fold를 사용해 모델 확인

이제까지 살펴본 두 접근법은 사용자 중 일부에 대한 추천 결과를 테스트했다. 대신에, 사용자별 추천 결과를 테스트하면 훨씬 더 정확하게 성능을 측정할 수 있다. 데이터를 몇 개의 덩어리들로 나눌 수 있고, 테스트 세트로 이 덩어리를 가져와 정확도를 평가할 수 있다. 그런 다음, 덩어리별로 같게 평균 정확도를 계산할 수 있다. 이러한 방법을 k-fold라고 하며 recommenderlab 패키지에서 지원한다.

evaluationScheme 함수를 사용할 때, 트레이닝 세트에 넣을 데이터의 비율을 지정하는 대신에 원하는 덩어리의 개수를 지정하는 것이 차이점이다. 매개변수는 이전 예제에서의 반복 횟수와 마찬가지로 k다. 이전과는 달리 train은 지정할 필요가 없다.

n_fold <- 4
eval_sets <- evaluationScheme(data = ratings_movies, method = "cross-validation", k = n_fold,
                              given = items_to_keep, goodRating = rating_threshold)

세트별로 얼마나 많은 아이템이 포함돼 있는지 셀 수 있다.

size_sets <- sapply(eval_sets@runsTrain, length)
size_sets
[1] 420 420 420 420

예상대로 모든 세트는 같은 크기다.

이 접근법은 더 많은 계산이 필요하겠지만 가장 정확한 방법이다.

지금까지 트레이닝 및 테스트 세트를 준비하기 위한 다양한 접근법을 살펴봤다. 이어서 평가를 진행한다.

 

추천 결과 평가

이제부터 추천 결과를 평가하기 위한 두 가지 일반적인 접근법을 알아본다. 이들은 지금까지 알아본 교차 검증 구조를 기반으로 한다.

첫 번째 방법은 알고리즘에 의해 추정되는 평점을 평가하는 것이고, 또 다른 방법은 추천 결과를 직접 평가하는 것이다. 이제부터 각 접근법을 알아본다.

 

예측 평점 평가

새로운 사용자에게 아이템을 추천하기 위해 협업 필터링은 아직 구매하지 않은 아이템의 평점을 추정한다. 그런 다음, 그 그중에서 최상위 아이템들을 추천한다. 지금은 마지막 단계에 대해서는 무시한다. 추정된 평점과 실제 평점을 비교하면 모델을 평가할 수 있다.

 

먼저, 이전에 설명한 것처럼 검증을 위한 데이터를 준비한다. 여기서는 k-fold가 가장 정확한 접근법이기 때문에 이를 사용한다.

n_fold <- 4
items_to_keep <- 15
rating_threshold <- 3
eval_sets <- evaluationScheme(data = ratings_movies, method = "cross-validation", k = n_fold,
                              given = items_to_keep, goodRating = rating_threshold)

먼저 평가할 모델을 정의해야 한다. 여기서는 아이템 기반 협업 필터링을 사용하는 추천 방식을 평가한다. 이를 위해 Recommender 함수를 사용해 모델을 만든다.

 

먼저 모델의 이름과 매개변수를 지정한다. 매개변수는 기본값을 사용한다면 NULL이다.

model_to_evaluate <- "IBCF"
model_parameters <- NULL

이제 다음의 코드를 사용해 모델을 만든다.

eval_recommender <- Recommender(data = getData(eval_sets, "train"),
                                method = model_to_evaluate, parameter = model_parameters)

IBCF는 새로운 아이템을 추천하거나 평점을 예측할 수 있다. 모델을 만들려면 매개변수를 사용할 필요가 없더라도 추천할 아이템 수(예를 들면 10)를 지정해야 한다.

items_to_recommend <- 10

predict 함수를 사용해 예측된 평점의 매트릭스를 만들 수 있다.

eval_prediction <- predict(object = eval_recommender, newdata = getData(eval_sets, "known"),
                           n = items_to_recommend, type = "ratings")
class(eval_prediction)
[1] "realRatingMatrix"
attr(,"package")
[1] "recommenderlab"

eval_prediction 객체는 평점 매크릭스유형이다. 사용자별로 얼마나 많은 영화를 추천하는지 살펴본다. 이를 위해 사용자별 영화의 분포를 시각화할 수 있다.

qplot(rowCounts(eval_prediction)) +
  geom_histogram(binwidth = 10) + 
  ggtitle("Distribution of movies per user")

다음 도표는 사용자별 영화의 분포를 보여준다.

 

사용자별 영화의 수는 대부분 150에서 300사이다.

calcPredictionAccuracy는 정확도를 측정하는 함수며 다음과 같은 값들을 계산한다.

  • RMSE(Root mean square error) : 실제 평점과 예측 평점 간 차이의 제곱에 대해 평균을 취하고 이를 제곱근한 것으로, 표준편차다.
  • MSE(Mean squared error) : 실제 평점과 예측 평점 간 차이의 제곱에 대해 평균을 취한 것이다. 그것은 RMSE의 제곱근이므로 같은 정보를 포함한다.
  • MAE(Mean absolute error) : 실제 평점과 예측 평점 간 차이의 절댓값의 평균이다.

byUser = TRUE를 지정해 사용자별로 계산할 수 있다.

eval_accuracy <- calcPredictionAccuracy(x = eval_prediction, data = getData(eval_sets, "unknown"), byUser = TRUE)
head(eval_accuracy)
       RMSE      MSE       MAE
1  2.025472 4.102539 1.6943907
12 1.249678 1.561696 0.7603773
14 1.461440 2.135807 1.0172610
26 1.398511 1.955833 1.1061089
38 1.774652 3.149389 1.2247439
42 1.050958 1.104514 0.8269555

 

사용자별 RMSE를 살펴본다.

qplot(eval_accuracy[, "RMSE"]) +
  geom_histogram(binwidth = 0.1) +
  ggtitle("Distribution of the RMSE by user")

다음 도표는 사용자별 RMSE의 분포를 보여준다.

RMSE의 범위는 대부분 0.8에서 2.0 사이며, 각 사용자의 모델을 평가했다. 전체 모델의 성능 지표를 확보하려면 byUser = FALSE를 지정해 평균 지수를 계산해야 한다.

eval_accuracy <- calcPredictionAccuracy(x = eval_prediction, data = getData(eval_sets, "unknown"), byUser = FALSE)
eval_accuracy
    RMSE      MSE      MAE 
1.431400 2.048907 1.084437 

 

이 측정값은 같은 데이터에 대한 서로 다른 모델의 성능을 비교하는 데 유용하다.

반응형

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

추천 시스템의 평가 - 04  (0) 2020.03.29
추천 시스템의 평가 - 03  (0) 2020.03.24
추천 시스템의 평가 - 01  (0) 2020.03.24
추천 시스템 - 05  (0) 2020.03.20
추천 시스템 - 04  (0) 2020.03.19