협업 필터링 추천 시스템 구축하기

반응형
협업 필터링 추천 시스템 구축하기

1. recommenderlab 패키지 설치

  • recommenderlab 패키지는 추천 엔진 구축에 사용되는 사용자 기반의 협업 필터와 아이템 기반의 협업 필터, SVD, 연관성 규칙 기반 알고리즘과 같은 추천 알고리즘을 개발하고 테스트하기 위한 R 패키지입니다.

    library(recommenderlab)
  • recommenderlab 패키지에는 기본 데이터 세트가 제공됩니다.

    data_packages <- data(package = "recommenderlab")
    data_packages$results[, c("Item", "Title")]
    ##      Item                         
    ## [1,] "Jester5k"                   
    ## [2,] "JesterJokes (Jester5k)"     
    ## [3,] "MSWeb"                      
    ## [4,] "MovieLense"                 
    ## [5,] "MovieLenseMeta (MovieLense)"
    ##      Title                                      
    ## [1,] "Jester dataset (5k sample)"               
    ## [2,] "Jester dataset (5k sample)"               
    ## [3,] "Anonymous web data from www.microsoft.com"
    ## [4,] "MovieLense Dataset (100k)"                
    ## [5,] "MovieLense Dataset (100k)"
  • 이번에는 Jester5k 데이터를 가지고 실습해보겠습니다.

    data(Jester5k)
    • 해당 데이터는 1999년 4월부터 2003년 5월까지 Jester Online Joke 추천인 시스템에서 수집한 5,000명 사용자의 샘플을 포함하고 있습니다.
    • 5,000명의 사용자와 100개의 농담을 포함한 평가 행렬이며 평가값의 범위는 -10~10 사이 값을 갖습니다. 선택된 모든 사용자는 최소 36개의 농담에 대해서 평가를 합니다.
    • 실제 농담 데이터는 JesterJokes에 포함되어 있습니다.

2. 데이터 탐색

  • 5,000명의 사용자와 100개의 아이템이 있는 평가 행렬입니다.

    dim(Jester5k)
    ## [1] 5000  100
  • 평가 값을 탐색하기 위하여 getRatings() 함수를 이용하고 히스토그램으로 나타내보았습니다.

    hist(getRatings(Jester5k), main = "Distribution of ratings")

    • 음수값(부정적 평가)을 갖는 것은 균일해보이나 양수값(긍정적 평가)을 갖는 부분은 점수가 높아질수록 상대적으로 감소하는 추세를 보입니다.
  • 이를 행렬로 변환시켜 어떻게 생겨먹었는지 몇 줄만 확인해보겠습니다.

    as(Jester5k, "matrix")[1:10, 1:10]
    ##           j1    j2    j3    j4    j5    j6    j7    j8    j9   j10
    ## u2841   7.91  9.17  5.34  8.16 -8.74  7.14  8.88 -8.25  5.87  6.21
    ## u15547 -3.20 -3.50 -9.56 -8.74 -6.36 -3.30  0.78  2.18 -8.40 -8.79
    ## u15221 -1.70  1.21  1.55  2.77  5.58  3.06  2.72 -4.66  4.51 -3.06
    ## u15573 -7.38 -8.93 -3.88 -7.23 -4.90  4.13  2.57  3.83  4.37  3.16
    ## u21505  0.10  4.17  4.90  1.55  5.53  1.50 -3.79  1.94  3.59  4.81
    ## u15994  0.83 -4.90  0.68 -7.18  0.34 -4.32 -6.17  6.12 -5.58  5.44
    ## u238    2.91  4.76    NA    NA    NA    NA -9.47  3.69    NA -2.38
    ## u5809  -2.77 -6.31  2.23    NA  0.19  1.26  2.43 -5.00    NA -5.49
    ## u16636 -3.35 -5.92 -5.63 -3.01  1.70 -2.52  1.60 -0.53  1.65 -7.28
    ## u12843 -1.99 -6.89  2.09 -4.42 -4.90  2.43 -3.06  3.98 -1.46  0.68
  • 이제 training dataset과 test dataset을 7:3의 비율로 분리 해보겠습니다.

    set.seed(2017)
    index <- sample(1:nrow(Jester5k), size = nrow(Jester5k) * 0.7)
    
    train <- Jester5k[index, ]
    test <- Jester5k[-index, ]
    
    dim(train) 
    ## [1] 3500  100
    dim(test)
    ## [1] 1500  100

3. 사용자 기반 협업 필터링 (UBCF)

3. 1. 모델링

  • recommenderlab에서 사용 가능한 추천 모델은 다음과 같습니다.

    recommender_models <- recommenderRegistry$get_entries(dataType = "realRatingMatrix")
    recommender_models
    ## $ALS_realRatingMatrix
    ## Recommender method: ALS for realRatingMatrix
    ## Description: Recommender for explicit ratings based on latent factors, calculated by alternating least squares algorithm.
    ## Reference: Yunhong Zhou, Dennis Wilkinson, Robert Schreiber, Rong Pan (2008). Large-Scale Parallel Collaborative Filtering for the Netflix Prize, 4th Int'l Conf. Algorithmic Aspects in Information and Management, LNCS 5034.
    ## Parameters:
    ##   normalize lambda n_factors n_iterations min_item_nr seed
    ## 1      NULL    0.1        10           10           1 NULL
    ## 
    ## $ALS_implicit_realRatingMatrix
    ## Recommender method: ALS_implicit for realRatingMatrix
    ## Description: Recommender for implicit data based on latent factors, calculated by alternating least squares algorithm.
    ## Reference: Yifan Hu, Yehuda Koren, Chris Volinsky (2008). Collaborative Filtering for Implicit Feedback Datasets, ICDM '08 Proceedings of the 2008 Eighth IEEE International Conference on Data Mining, pages 263-272.
    ## Parameters:
    ##   lambda alpha n_factors n_iterations min_item_nr seed
    ## 1    0.1    10        10           10           1 NULL
    ## 
    ## $IBCF_realRatingMatrix
    ## Recommender method: IBCF for realRatingMatrix
    ## Description: Recommender based on item-based collaborative filtering.
    ## Reference: NA
    ## Parameters:
    ##    k   method normalize normalize_sim_matrix alpha na_as_zero
    ## 1 30 "Cosine"  "center"                FALSE   0.5      FALSE
    ## 
    ## $POPULAR_realRatingMatrix
    ## Recommender method: POPULAR for realRatingMatrix
    ## Description: Recommender based on item popularity.
    ## Reference: NA
    ## Parameters:
    ##   normalize    aggregationRatings aggregationPopularity
    ## 1  "center" new("standardGeneric" new("standardGeneric"
    ## 
    ## $RANDOM_realRatingMatrix
    ## Recommender method: RANDOM for realRatingMatrix
    ## Description: Produce random recommendations (real ratings).
    ## Reference: NA
    ## Parameters: None
    ## 
    ## $RERECOMMEND_realRatingMatrix
    ## Recommender method: RERECOMMEND for realRatingMatrix
    ## Description: Re-recommends highly rated items (real ratings).
    ## Reference: NA
    ## Parameters:
    ##   randomize minRating
    ## 1         1        NA
    ## 
    ## $SVD_realRatingMatrix
    ## Recommender method: SVD for realRatingMatrix
    ## Description: Recommender based on SVD approximation with column-mean imputation.
    ## Reference: NA
    ## Parameters:
    ##    k maxiter normalize
    ## 1 10     100  "center"
    ## 
    ## $SVDF_realRatingMatrix
    ## Recommender method: SVDF for realRatingMatrix
    ## Description: Recommender based on Funk SVD with gradient descend.
    ## Reference: NA
    ## Parameters:
    ##    k gamma lambda min_epochs max_epochs min_improvement normalize verbose
    ## 1 10 0.015  0.001         50        200           1e-06  "center"   FALSE
    ## 
    ## $UBCF_realRatingMatrix
    ## Recommender method: UBCF for realRatingMatrix
    ## Description: Recommender based on user-based collaborative filtering.
    ## Reference: NA
    ## Parameters:
    ##     method nn sample normalize
    ## 1 "cosine" 25  FALSE  "center"
  • 이제 사용자 기반 협업 필터링 모델을 구축하기 위해서 Recommender() 함수를 사용하겠습니다.

    recomm_model <- Recommender(data = train, method = "UBCF")
    recomm_model
    ## Recommender of type 'UBCF' for 'realRatingMatrix' 
    ## learned using 3500 users.
    recomm_model@model$data
    ## 3500 x 100 rating matrix of class 'realRatingMatrix' with 254183 ratings.
    ## Normalized using center on rows.
  • 다음으로 predict() 함수를 이용하여 테스트 데이터를 예측해보겠습니다. 최상위 10개 추천을 하겠습니다.

    pred <- predict(recomm_model, newdata = test, n = 10)
    • 추천 결과 값은 pred@items 객체에 저장됩니다. 이는 테스트데이터에 있는 해당 사용자가 몇 번째 아이템을 추천받을지를 뽑습니다.
  • 그 결과를 list 타입으로 바꾸어 결과를 확인하는게 편합니다. sapply() 함수를 이용하겠습니다.

    pred_list <- sapply(pred@items, function(x) { colnames(Jester5k)[x] })
    
    pred_list[1]
    ## $u15547
    ##  [1] "j89" "j81" "j93" "j83" "j96" "j88" "j76" "j87" "j80" "j71"
    pred_list[1500]
    ## $u15348
    ##  [1] "j76"  "j89"  "j93"  "j96"  "j97"  "j100" "j92"  "j82"  "j73"  "j83"
  • 다음은 모든 테스트 사용자들에 대해 각 몇 개의 추천이 생성되었는지 확인해보겠습니다.

    table( unlist( lapply(pred_list, length) ) )
    ## 
    ##    0    1    2    3    4    5    6    7    8    9   10 
    ##  413    6    2    6    5    3    2    4    5    5 1049
    • 일부 사용자들은 0개의 추천을 받았는데 이는 원래 Jester5k 데이터에서 그 사용자들이 모두 평가점수를 매겼기 때문이고, 반대로 10개의 추천을 받은 사용자들은 모두 평가점수를 매기지 않았기 때문입니다.

3. 2. 데이터 탐색

  • 모형을 평가하기 앞서 사람들이 평균적으로 얼만큼의 농담을 평가했는지 알아보면 다음과 같습니다. 이 때는 rowCounts() 함수를 사용합니다.

    table(rowCounts(Jester5k))
    ## 
    ##   36   37   38   39   40   41   42   43   44   45   46   47   48   49   50 
    ##  114   77   80   78   74   70   74   75   80   81   70   60   69   61   62 
    ##   51   52   53   54   55   56   57   58   59   60   61   62   63   64   65 
    ##   47   42   52   52   48   56   54   34   43   48   41   42   42   41   53 
    ##   66   67   68   69   70   71   72   73   74   75   76   77   78   79   80 
    ##   51   39   39   29   87  221  364  312  131   48   36   19   33   32   38 
    ##   81   82   83   84   85   86   87   88   89   90   91   92   93   94   95 
    ##   20   19   18   15   23   21   12   12   11   14   16   10   12   12   11 
    ##   96   97   98   99  100 
    ##   16   13    8   16 1422
    • 1400명이 넘는 사람이 100개의 농담에 대해 모두 평가했습니다.
    mean(rowCounts(Jester5k))
    ## [1] 72.4212
    • 1인당 평균 72개의 농담을 평가한것으로 보입니다.
  • 따라서 평균 이상의 농담을 평가한 사용자의 레코드를 제거하고 사용자들의 평가점수 평균 분포를 확인해보겠습니다.

    data_modify <- Jester5k[rowCounts(Jester5k) <= 72]
    dim(data_modify)
    ## [1] 2650  100
    boxplot(Matrix::rowMeans(data_modify))

    • 이상점이 어느 정도 존재해보입니다. (-5 이하와 7 이상을 평가한 사용자)

3. 3. 모형 평가

  • recommenderlab 패키지에는 evaluationScheme() 함수를 사용해 모델 평가를 하는 인프라를 제공합니다. 이 함수는 evaluationScheme 이라는 객체를 생성하고 이 scheme은 training-test data로 나뉘어져 k-fold Cross-Validation과 같은 검증을 이루어지도록 합니다.

    evaluationScheme(data, method = "cross-validation", train, k, goodRating, given)
    • data : 평가 행렬 데이터
    • k : k-folds
    • goodRating : 평가를 위해 고려해야 할 최소값
    • given : 각 행이 포함하는 레코드의 최소값
    eval_sets <- evaluationScheme(data = data_modify,
                                  method = "cross-validation",
                                  train = 0.7,
                                  k = 10,
                                  goodRating = 3,
                                  given = 30)
  • k개의 겹들의 크기는 다음과 같이 확인할 수 있습니다.

    sapply(eval_sets@runsTrain, length)
    ##  [1] 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385
  • getData() 함수를 사용하여 데이터세트를 추출할 수 있습니다.

    • “train” : 훈련 데이터
    • “known” : 테스트 데이터, 추천을 구축하기 위해 사용되는 아이템으로 구성
    • “unknown” : 테스트 데이터, 추천을 테스트하기 위해 사용되는 아이템으로 구성
    getData(eval_sets, "train")
    ## 2385 x 100 rating matrix of class 'realRatingMatrix' with 131709 ratings.
  • 이제 본격적으로 모델링을 평가하기 위한 코딩을 하겠습니다. Recommender() 함수를 모델링 후, predict() 함수로 ratings 값을 구한 다음 calcPredictionAccuracy() 함수를 통해 모델의 정확도 메트릭을 계산합니다.

    # Training dataset modeling
    recomm_eval <- Recommender(data = getData(eval_sets, "train"),
                               method = "UBCF", 
                               parameter = NULL)
    recomm_eval
    ## Recommender of type 'UBCF' for 'realRatingMatrix' 
    ## learned using 2385 users.
    # Prediction
    pred_eval <- predict(recomm_eval, 
                         newdata = getData(eval_sets, "known"),
                         n = 10, type = "ratings")
    pred_eval
    ## 265 x 100 rating matrix of class 'realRatingMatrix' with 18550 ratings.
    # Calculate accuracy
    accuracy_eval <- calcPredictionAccuracy(x = pred_eval,
                                            data = getData(eval_sets, "unknown"),
                                            byUser = TRUE) # byUser = TRUE : 각 사용자들에 대한 모델의 정확도가 계산
  • 그 결과를 일부만 살펴보면 다음과 같습니다.

    head( accuracy_eval, 10 )
    ##            RMSE       MSE      MAE
    ## u20747 3.776014 14.258285 3.001405
    ## u1143  3.086840  9.528582 2.479899
    ## u17742 4.276830 18.291275 3.622810
    ## u12353 4.375728 19.146995 3.583866
    ## u14852 4.110138 16.893233 3.301245
    ## u5677  5.835490 34.052944 5.268571
    ## u15683 4.997584 24.975843 4.113507
    ## u13094 5.774912 33.349605 5.230295
    ## u5065  3.475128 12.076515 2.785195
    ## u14030 4.938428 24.388071 4.021243
  • 전체적인 정확도는 다음과 같습니다.

    colMeans(accuracy_eval)  # 혹은 byUser = FALSE 하면 바로 출력
    ##      RMSE       MSE       MAE 
    ##  4.101142 18.689548  3.398017
  • RMSE와 MAE가 아닌 정밀도, 재현율을 이용하여 정확도를 평가하고 싶다면 confusion matrix를 출력하는 evaluate() 함수와 getConfusionMatrix() 함수를 이용합니다.

    accuracy_eval2 <- evaluate(x = eval_sets, 
                               method = "UBCF")
    ## UBCF run fold/sample [model time/prediction time]
    ##   1  [0.02sec/1.59sec] 
    ##   2  [0.02sec/1.5sec] 
    ##   3  [0.02sec/1.93sec] 
    ##   4  [0.01sec/1.72sec] 
    ##   5  [0.03sec/1.74sec] 
    ##   6  [0.02sec/1.54sec] 
    ##   7  [0.04sec/1.45sec] 
    ##   8  [0.01sec/1.32sec] 
    ##   9  [0.01sec/1.42sec] 
    ##   10  [0sec/1.47sec]
    head( getConfusionMatrix(accuracy_eval2) )
    ## [[1]]
    ##           TP        FP       FN       TN precision     recall        TPR
    ## 1  0.5924528 0.4075472 9.841509 59.15849 0.5924528 0.08290521 0.08290521
    ## 2  1.1584906 0.8415094 9.275472 58.72453 0.5792453 0.15603500 0.15603500
    ## 3  1.6830189 1.3169811 8.750943 58.24906 0.5610063 0.22191606 0.22191606
    ## 4  2.2226415 1.7773585 8.211321 57.78868 0.5556604 0.28106648 0.28106648
    ## 5  2.7018868 2.2981132 7.732075 57.26792 0.5403774 0.33258064 0.33258064
    ## 6  3.1622642 2.8377358 7.271698 56.72830 0.5270440 0.38280228 0.38280228
    ## 7  3.6000000 3.4000000 6.833962 56.16604 0.5142857 0.42789819 0.42789819
    ## 8  3.9622642 4.0377358 6.471698 55.52830 0.4952830 0.46495618 0.46495618
    ## 9  4.3622642 4.6377358 6.071698 54.92830 0.4846960 0.50012699 0.50012699
    ## 10 4.6792453 5.3207547 5.754717 54.24528 0.4679245 0.52634107 0.52634107
    ##            FPR
    ## 1  0.006554958
    ## 2  0.013482425
    ## 3  0.021243754
    ## 4  0.028556060
    ## 5  0.036864801
    ## 6  0.045464289
    ## 7  0.054438315
    ## 8  0.064781228
    ## 9  0.074303933
    ## 10 0.085258080
    ## 
    ## [[2]]
    ##           TP        FP       FN       TN precision     recall        TPR
    ## 1  0.6188679 0.3811321 9.305660 59.69434 0.6188679 0.09307772 0.09307772
    ## 2  1.1698113 0.8301887 8.754717 59.24528 0.5849057 0.17785835 0.17785835
    ## 3  1.6679245 1.3320755 8.256604 58.74340 0.5559748 0.23677963 0.23677963
    ## 4  2.1509434 1.8490566 7.773585 58.22642 0.5377358 0.28882292 0.28882292
    ## 5  2.6150943 2.3849057 7.309434 57.69057 0.5230189 0.34758919 0.34758919
    ## 6  3.0264151 2.9735849 6.898113 57.10189 0.5044025 0.39220085 0.39220085
    ## 7  3.4075472 3.5924528 6.516981 56.48302 0.4867925 0.43110851 0.43110851
    ## 8  3.7584906 4.2415094 6.166038 55.83396 0.4698113 0.46562323 0.46562323
    ## 9  4.1245283 4.8754717 5.800000 55.20000 0.4582809 0.50143219 0.50143219
    ## 10 4.3924528 5.6075472 5.532075 54.46792 0.4392453 0.52435576 0.52435576
    ##            FPR
    ## 1  0.005946865
    ## 2  0.013102388
    ## 3  0.020999936
    ## 4  0.029131451
    ## 5  0.037592471
    ## 6  0.046889191
    ## 7  0.056777800
    ## 8  0.067110514
    ## 9  0.077149475
    ## 10 0.088974774
    ## 
    ## [[3]]
    ##           TP        FP       FN       TN precision     recall        TPR
    ## 1  0.5358491 0.4641509 9.181132 59.81887 0.5358491 0.08666175 0.08666175
    ## 2  1.1245283 0.8754717 8.592453 59.40755 0.5622642 0.17995607 0.17995607
    ## 3  1.6490566 1.3509434 8.067925 58.93208 0.5496855 0.25267287 0.25267287
    ## 4  2.1094340 1.8905660 7.607547 58.39245 0.5273585 0.30739794 0.30739794
    ## 5  2.5509434 2.4490566 7.166038 57.83396 0.5101887 0.35988659 0.35988659
    ## 6  2.9584906 3.0415094 6.758491 57.24151 0.4930818 0.40934454 0.40934454
    ## 7  3.3698113 3.6301887 6.347170 56.65283 0.4814016 0.44891090 0.44891090
    ## 8  3.7320755 4.2679245 5.984906 56.01509 0.4665094 0.48321436 0.48321436
    ## 9  4.1207547 4.8792453 5.596226 55.40377 0.4578616 0.51993781 0.51993781
    ## 10 4.4150943 5.5849057 5.301887 54.69811 0.4415094 0.54898920 0.54898920
    ##            FPR
    ## 1  0.007246624
    ## 2  0.013705866
    ## 3  0.021211806
    ## 4  0.029650195
    ## 5  0.038515553
    ## 6  0.047900027
    ## 7  0.057111247
    ## 8  0.067180227
    ## 9  0.076779775
    ## 10 0.088023678
    ## 
    ## [[4]]
    ##           TP        FP       FN       TN precision    recall       TPR
    ## 1  0.6264151 0.3735849 8.947170 60.05283 0.6264151 0.1107841 0.1107841
    ## 2  1.1886792 0.8113208 8.384906 59.61509 0.5943396 0.1971903 0.1971903
    ## 3  1.6792453 1.3207547 7.894340 59.10566 0.5597484 0.2644046 0.2644046
    ## 4  2.1849057 1.8150943 7.388679 58.61132 0.5462264 0.3282580 0.3282580
    ## 5  2.6603774 2.3396226 6.913208 58.08679 0.5320755 0.3825021 0.3825021
    ## 6  3.0603774 2.9396226 6.513208 57.48679 0.5100629 0.4200731 0.4200731
    ## 7  3.4339623 3.5660377 6.139623 56.86038 0.4905660 0.4561269 0.4561269
    ## 8  3.8075472 4.1924528 5.766038 56.23396 0.4759434 0.4934105 0.4934105
    ## 9  4.1320755 4.8679245 5.441509 55.55849 0.4591195 0.5207681 0.5207681
    ## 10 4.4603774 5.5396226 5.113208 54.88679 0.4460377 0.5529575 0.5529575
    ##            FPR
    ## 1  0.005836866
    ## 2  0.012789720
    ## 3  0.020941835
    ## 4  0.028722334
    ## 5  0.036995861
    ## 6  0.046436103
    ## 7  0.056310459
    ## 8  0.066230371
    ## 9  0.076965659
    ## 10 0.087577871
    ## 
    ## [[5]]
    ##           TP        FP       FN       TN precision     recall        TPR
    ## 1  0.6150943 0.3849057 9.305660 59.69434 0.6150943 0.07525278 0.07525278
    ## 2  1.1584906 0.8415094 8.762264 59.23774 0.5792453 0.15108314 0.15108314
    ## 3  1.6339623 1.3660377 8.286792 58.71321 0.5446541 0.21152719 0.21152719
    ## 4  2.1358491 1.8641509 7.784906 58.21509 0.5339623 0.27380352 0.27380352
    ## 5  2.5433962 2.4566038 7.377358 57.62264 0.5086792 0.31786348 0.31786348
    ## 6  2.9471698 3.0528302 6.973585 57.02642 0.4911950 0.36022039 0.36022039
    ## 7  3.3132075 3.6867925 6.607547 56.39245 0.4733154 0.39357695 0.39357695
    ## 8  3.6679245 4.3320755 6.252830 55.74717 0.4584906 0.42485843 0.42485843
    ## 9  4.0188679 4.9811321 5.901887 55.09811 0.4465409 0.46237148 0.46237148
    ## 10 4.3509434 5.6490566 5.569811 54.43019 0.4350943 0.49252946 0.49252946
    ##            FPR
    ## 1  0.005979416
    ## 2  0.013265977
    ## 3  0.021649733
    ## 4  0.029534179
    ## 5  0.039020674
    ## 6  0.048495643
    ## 7  0.058565453
    ## 8  0.068823949
    ## 9  0.079268859
    ## 10 0.089979706
    ## 
    ## [[6]]
    ##           TP        FP       FN       TN precision     recall        TPR
    ## 1  0.5584906 0.4415094 8.645283 60.35472 0.5584906 0.07571185 0.07571185
    ## 2  1.1245283 0.8754717 8.079245 59.92075 0.5622642 0.16668804 0.16668804
    ## 3  1.6113208 1.3886792 7.592453 59.40755 0.5371069 0.22905766 0.22905766
    ## 4  2.0641509 1.9358491 7.139623 58.86038 0.5160377 0.29562961 0.29562961
    ## 5  2.4754717 2.5245283 6.728302 58.27170 0.4950943 0.34786133 0.34786133
    ## 6  2.8566038 3.1433962 6.347170 57.65283 0.4761006 0.38956606 0.38956606
    ## 7  3.2150943 3.7849057 5.988679 57.01132 0.4592992 0.42925501 0.42925501
    ## 8  3.5509434 4.4490566 5.652830 56.34717 0.4438679 0.46399675 0.46399675
    ## 9  3.8264151 5.1735849 5.377358 55.62264 0.4251572 0.49212568 0.49212568
    ## 10 4.1132075 5.8867925 5.090566 54.90943 0.4113208 0.51768149 0.51768149
    ##            FPR
    ## 1  0.006850056
    ## 2  0.013733755
    ## 3  0.021853602
    ## 4  0.030511265
    ## 5  0.039870484
    ## 6  0.049665258
    ## 7  0.059898876
    ## 8  0.070369335
    ## 9  0.081929380
    ## 10 0.093223689

4. 아이템 기반 협업 필터링 (IBCF)

4. 1. 모델링

  • UBCF와 함수의 option argument만 다를뿐이지 비슷합니다. 역시 Recommender() 함수를 이용합니다.
  • 여기서 추가되는 점은 parameter = list()라는 옵션입니다. 여기서 list(k = k)는 유사도 값을 계산하는데 고려되는 이웃의 수를 의미합니다.

    recomm_model2 <- Recommender(data = train, 
                                 method = "IBCF",
                                 parameter = list(k = 30))
    recomm_model2
    ## Recommender of type 'IBCF' for 'realRatingMatrix' 
    ## learned using 3500 users.
  • 모형을 생성하면, 모형에 대한 상세 정보를 확인해야 합니다. getModel() 함수를 이용해 상세 정보를 확인해볼 수 있습니다.

    str( getModel(recomm_model2) )
    ## List of 9
    ##  $ description         : chr "IBCF: Reduced similarity matrix"
    ##  $ sim                 :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
    ##   .. ..@ i       : int [1:3000] 1 2 5 9 18 33 37 38 69 72 ...
    ##   .. ..@ p       : int [1:101] 0 15 30 41 93 104 121 142 168 212 ...
    ##   .. ..@ Dim     : int [1:2] 100 100
    ##   .. ..@ Dimnames:List of 2
    ##   .. .. ..$ : chr [1:100] "j1" "j2" "j3" "j4" ...
    ##   .. .. ..$ : chr [1:100] "j1" "j2" "j3" "j4" ...
    ##   .. ..@ x       : num [1:3000] 0.194 0.1892 0.1199 0.159 0.0916 ...
    ##   .. ..@ factors : list()
    ##  $ k                   : num 30
    ##  $ method              : chr "Cosine"
    ##  $ normalize           : chr "center"
    ##  $ normalize_sim_matrix: logi FALSE
    ##  $ alpha               : num 0.5
    ##  $ na_as_zero          : logi FALSE
    ##  $ verbose             : logi FALSE
    • 모형의 상세정보를 보면 기본적으로 코사인 유사도 값을 이용하였으며 $sim을 통해 그 값을 확인할 수 있습니다.
  • predict() 함수를 이용하여 테스트 데이터에 대한 내용을 예측해봅니다.

    pred2 <- predict(recomm_model2, newdata = test, n = 10)
    • 추천 결과 값은 pred2@items 객체에 저장됩니다. 이는 테스트데이터에 있는 해당 사용자가 몇 번째 아이템을 추천받을지를 뽑습니다.
  • 그 결과를 list 타입으로 바꾸어 결과를 확인하는게 편합니다. sapply() 함수를 이용하겠습니다.

    pred_list2 <- sapply(pred2@items, function(x) { colnames(Jester5k)[x] })
    
    pred_list2[1]
    ## $u15547
    ##  [1] "j99" "j95" "j75" "j90" "j71" "j79" "j74" "j86" "j82" "j58"
    pred_list2[1500]
    ## $u15348
    ##  [1] "j75" "j86" "j79" "j77" "j74" "j99" "j73" "j84" "j90" "j71"

4. 2. 모형 평가

  • 3절에 이어 data_modify를 가지고 진행하겠씁니다. 마찬가지로 evaluationScheme() 함수를 사용합니다.

    evaluationScheme(data, method = "cross-validation", train, k, goodRating, given)
    • data : 평가 행렬 데이터
    • k : k-folds
    • goodRating : 좋은 평가로 간주되는 최소 평가
    • given : 추천 생성에 사용되는 아이템의 최소 개수
    eval_sets2 <- evaluationScheme(data = data_modify,
                                   method = "cross-validation",
                                   train = 0.7,
                                   k = 5,
                                   goodRating = 3,
                                   given = 15)
  • getData() 함수를 사용하여 데이터세트를 추출할 수 있습니다.

    getData(eval_sets2, "train")
    ## 2120 x 100 rating matrix of class 'realRatingMatrix' with 116977 ratings.
  • Recommender() 함수를 모델링 후, predict() 함수로 ratings 값을 구한 다음 calcPredictionAccuracy() 함수를 통해 모델의 정확도 메트릭을 계산합니다.

    # Training dataset modeling
    recomm_eval2 <- Recommender(data = getData(eval_sets2, "train"),
                                method = "IBCF", 
                                parameter = NULL)
    recomm_eval2
    ## Recommender of type 'IBCF' for 'realRatingMatrix' 
    ## learned using 2120 users.
    # Prediction
    pred_eval2 <- predict(recomm_eval2, 
                          newdata = getData(eval_sets2, "known"),
                          n = 10, type = "ratings")
    pred_eval2
    ## 530 x 100 rating matrix of class 'realRatingMatrix' with 44866 ratings.
    # Calculate accuracy
    accuracy_eval2 <- calcPredictionAccuracy(x = pred_eval2,
                                             data = getData(eval_sets2, "unknown"),
                                             byUser = TRUE) # byUser = TRUE : 각 사용자들에 대한 모델의 정확도가 계산
  • 그 결과를 일부만 살펴보면 다음과 같습니다.

    head( accuracy_eval, 10 )
    ##            RMSE       MSE      MAE
    ## u20747 3.776014 14.258285 3.001405
    ## u1143  3.086840  9.528582 2.479899
    ## u17742 4.276830 18.291275 3.622810
    ## u12353 4.375728 19.146995 3.583866
    ## u14852 4.110138 16.893233 3.301245
    ## u5677  5.835490 34.052944 5.268571
    ## u15683 4.997584 24.975843 4.113507
    ## u13094 5.774912 33.349605 5.230295
    ## u5065  3.475128 12.076515 2.785195
    ## u14030 4.938428 24.388071 4.021243
  • 전체적인 정확도는 다음과 같습니다.

    colMeans(accuracy_eval)  # 혹은 byUser = FALSE 하면 바로 출력
    ##      RMSE       MSE       MAE 
    ##  4.101142 18.689548  3.398017
  • RMSE와 MAE가 아닌 정밀도, 재현율을 이용하여 정확도를 평가하고 싶다면 confusion matrix를 출력하는 evaluate() 함수와 getConfusionMatrix() 함수를 이용합니다.

    accuracy_eval2 <- evaluate(x = eval_sets2, 
                               method = "IBCF", 
                               n = seq(10, 100, by = 10))
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.17sec/0.2sec] 
    ##   2  [0.15sec/0.16sec] 
    ##   3  [0.19sec/0.16sec] 
    ##   4  [0.12sec/0.19sec] 
    ##   5  [0.12sec/0.15sec]
    head( getConfusionMatrix(accuracy_eval2) )
    ## [[1]]
    ##            TP        FP           FN         TN precision     recall
    ## 10   1.149057  8.850943 14.949056604 60.0509434 0.1149057 0.06777921
    ## 20   2.749057 17.250943 13.349056604 51.6509434 0.1374528 0.16557899
    ## 30   4.669811 25.330189 11.428301887 43.5716981 0.1556604 0.28156465
    ## 40   6.681132 33.318868  9.416981132 35.5830189 0.1670283 0.41249246
    ## 50   8.892453 41.107547  7.205660377 27.7943396 0.1778491 0.55036255
    ## 60  11.262264 48.737736  4.835849057 20.1641509 0.1877044 0.70482888
    ## 70  13.547170 56.452830  2.550943396 12.4490566 0.1935310 0.84642916
    ## 80  15.456604 64.543396  0.641509434  4.3584906 0.1932075 0.95814392
    ## 90  16.092453 68.560377  0.005660377  0.3415094 0.1900565 0.99982911
    ## 100 16.092453 68.560377  0.005660377  0.3415094 0.1900565 0.99982911
    ##            TPR       FPR
    ## 10  0.06777921 0.1295888
    ## 20  0.16557899 0.2517166
    ## 30  0.28156465 0.3688990
    ## 40  0.41249246 0.4847410
    ## 50  0.55036255 0.5973814
    ## 60  0.70482888 0.7073277
    ## 70  0.84642916 0.8185126
    ## 80  0.95814392 0.9359717
    ## 90  0.99982911 0.9950275
    ## 100 0.99982911 0.9950275
    ## 
    ## [[2]]
    ##            TP        FP         FN         TN precision     recall
    ## 10   1.145283  8.854717 14.7679245 60.2320755 0.1145283 0.06924024
    ## 20   2.703774 17.296226 13.2094340 51.7905660 0.1351887 0.16938543
    ## 30   4.394340 25.605660 11.5188679 43.4811321 0.1464780 0.27422617
    ## 40   6.388679 33.611321  9.5245283 35.4754717 0.1597170 0.40934991
    ## 50   8.639623 41.360377  7.2735849 27.7264151 0.1727925 0.55946008
    ## 60  11.007547 48.992453  4.9056604 20.0943396 0.1834591 0.70677627
    ## 70  13.247170 56.752830  2.6660377 12.3339623 0.1892453 0.84228930
    ## 80  15.249057 64.750943  0.6641509  4.3358491 0.1906132 0.95899921
    ## 90  15.913208 68.635849  0.0000000  0.4509434 0.1882765 1.00000000
    ## 100 15.913208 68.635849  0.0000000  0.4509434 0.1882765 1.00000000
    ##            TPR       FPR
    ## 10  0.06924024 0.1294448
    ## 20  0.16938543 0.2519505
    ## 30  0.27422617 0.3725799
    ## 40  0.40934991 0.4884506
    ## 50  0.55946008 0.6002353
    ## 60  0.70677627 0.7099631
    ## 70  0.84228930 0.8215916
    ## 80  0.95899921 0.9367067
    ## 90  1.00000000 0.9932005
    ## 100 1.00000000 0.9932005
    ## 
    ## [[3]]
    ##            TP        FP           FN          TN precision    recall
    ## 10   1.177358  8.822642 13.905660377 61.09433962 0.1177358 0.0778735
    ## 20   2.681132 17.318868 12.401886792 52.59811321 0.1340566 0.1874937
    ## 30   4.390566 25.609434 10.692452830 44.30754717 0.1463522 0.3085186
    ## 40   6.233962 33.766038  8.849056604 36.15094340 0.1558491 0.4354029
    ## 50   8.235849 41.764151  6.847169811 28.15283019 0.1647170 0.5700067
    ## 60  10.305660 49.694340  4.777358491 20.22264151 0.1717610 0.7107474
    ## 70  12.350943 57.649057  2.732075472 12.26792453 0.1764420 0.8406120
    ## 80  14.222642 65.777358  0.860377358  4.13962264 0.1777830 0.9497810
    ## 90  15.077358 69.896226  0.005660377  0.02075472 0.1774262 0.9995480
    ## 100 15.077358 69.896226  0.005660377  0.02075472 0.1774262 0.9995480
    ##           TPR       FPR
    ## 10  0.0778735 0.1271627
    ## 20  0.1874937 0.2492767
    ## 30  0.3085186 0.3683406
    ## 40  0.4354029 0.4850879
    ## 50  0.5700067 0.5989564
    ## 60  0.7107474 0.7121531
    ## 70  0.8406120 0.8250675
    ## 80  0.9497810 0.9407469
    ## 90  0.9995480 0.9997119
    ## 100 0.9995480 0.9997119
    ## 
    ## [[4]]
    ##            TP        FP         FN         TN precision     recall
    ## 10   1.173585  8.826415 15.2320755 59.7679245 0.1173585 0.06900414
    ## 20   2.720755 17.279245 13.6849057 51.3150943 0.1360377 0.16889652
    ## 30   4.537736 25.462264 11.8679245 43.1320755 0.1512579 0.27775030
    ## 40   6.669811 33.330189  9.7358491 35.2641509 0.1667453 0.41291481
    ## 50   8.990566 41.009434  7.4150943 27.5849057 0.1798113 0.55820224
    ## 60  11.364151 48.635849  5.0415094 19.9584906 0.1894025 0.70765312
    ## 70  13.620755 56.379245  2.7849057 12.2150943 0.1945822 0.83810607
    ## 80  15.709434 64.290566  0.6962264  4.3037736 0.1963679 0.96035255
    ## 90  16.405660 68.262264  0.0000000  0.3320755 0.1938477 1.00000000
    ## 100 16.405660 68.262264  0.0000000  0.3320755 0.1938477 1.00000000
    ##            TPR       FPR
    ## 10  0.06900414 0.1301911
    ## 20  0.16889652 0.2541558
    ## 30  0.27775030 0.3734950
    ## 40  0.41291481 0.4880648
    ## 50  0.55820224 0.5995830
    ## 60  0.70765312 0.7098216
    ## 70  0.83810607 0.8217007
    ## 80  0.96035255 0.9366594
    ## 90  1.00000000 0.9949115
    ## 100 1.00000000 0.9949115
    ## 
    ## [[5]]
    ##            TP       FP           FN        TN precision     recall
    ## 10   1.194340  8.80566 14.477358491 60.522642 0.1194340 0.07277006
    ## 20   2.773585 17.22642 12.898113208 52.101887 0.1386792 0.17474464
    ## 30   4.584906 25.41509 11.086792453 43.913208 0.1528302 0.29782273
    ## 40   6.635849 33.36415  9.035849057 35.964151 0.1658962 0.43034731
    ## 50   8.877358 41.12264  6.794339623 28.205660 0.1775472 0.57416389
    ## 60  11.098113 48.90189  4.573584906 20.426415 0.1849686 0.71977344
    ## 70  13.198113 56.80189  2.473584906 12.526415 0.1885445 0.85193561
    ## 80  15.047170 64.95283  0.624528302  4.375472 0.1880896 0.96185352
    ## 90  15.662264 68.91887  0.009433962  0.409434 0.1852335 0.99934494
    ## 100 15.662264 68.91887  0.009433962  0.409434 0.1852335 0.99934494
    ##            TPR       FPR
    ## 10  0.07277006 0.1279062
    ## 20  0.17474464 0.2492623
    ## 30  0.29782273 0.3675434
    ## 40  0.43034731 0.4821690
    ## 50  0.57416389 0.5933350
    ## 60  0.71977344 0.7052697
    ## 70  0.85193561 0.8188223
    ## 80  0.96185352 0.9362005
    ## 90  0.99934494 0.9938766
    ## 100 0.99934494 0.9938766
  • 결과를 시각화 할 수도 있습니다.

    plot(accuracy_eval2, annotate = TRUE, main = "ROC Curve")

    plot(accuracy_eval2, "prec/rec", annotate = TRUE, main = "Precision-Recall")

4. 3. 매개변수 튜닝

  • IBCF 모형을 구축하는 과정에서 최종적 모형을 구축하기 위해 몇 가지 최적의 값을 선택해야 합니다.
    • 아이템 간 유사도를 계산하는 데 이웃의 수에 대한 최적의 값
    • 코사인 또는 피어슨 상관계수 중 유사도 계산 기준 선택
  • 따라서 k값이 될 수 있는 후보군을 벡터로 설정합니다.

    vector_k <- c(5, 10, 20, 30, 40)
  • 다음으로 lapply() 함수를 이용해 다른 매개변수와 연결시키는 다양한 모델을 생성합니다.

mod1 <- lapply(vector_k, function(k, l) { list(name = "IBCF", parameter = list(method = "cosine", k = k)) })
names(mod1) <- paste0("IBCF_cos_k_", vector_k)
names(mod1)
## [1] "IBCF_cos_k_5"  "IBCF_cos_k_10" "IBCF_cos_k_20" "IBCF_cos_k_30"
## [5] "IBCF_cos_k_40"
mod2 <- lapply(vector_k, function(k, l) { list(name = "IBCF", parameter = list(method = "pearson", k = k)) })
names(mod2) <- paste0("IBCF_pea_k_", vector_k)
names(mod2)
## [1] "IBCF_pea_k_5"  "IBCF_pea_k_10" "IBCF_pea_k_20" "IBCF_pea_k_30"
## [5] "IBCF_pea_k_40"
  • 이제 append() 함수를 이용해 모든 방식을 조합합니다.

    mod <- append(mod1, mod2)   # vector merging
  • 이를 이제 적용합니다.

    list_results <- evaluate(x = eval_sets2, 
                             method = mod,
                             n = c(1, 5, seq(10, 100, by = 10)))
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.15sec/0.16sec] 
    ##   2  [0.2sec/0.16sec] 
    ##   3  [0.19sec/0.17sec] 
    ##   4  [0.15sec/0.13sec] 
    ##   5  [0.17sec/0.12sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.16sec/0.17sec] 
    ##   2  [0.22sec/0.22sec] 
    ##   3  [0.2sec/0.22sec] 
    ##   4  [0.2sec/0.2sec] 
    ##   5  [0.14sec/0.15sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.21sec/0.26sec] 
    ##   2  [0.2sec/0.27sec] 
    ##   3  [0.2sec/0.22sec] 
    ##   4  [0.17sec/0.27sec] 
    ##   5  [0.25sec/0.22sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.19sec/0.24sec] 
    ##   2  [0.19sec/0.23sec] 
    ##   3  [0.36sec/0.27sec] 
    ##   4  [0.2sec/0.21sec] 
    ##   5  [0.28sec/0.23sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.1sec/0.1sec] 
    ##   2  [0.29sec/0.43sec] 
    ##   3  [0.2sec/0.25sec] 
    ##   4  [0.22sec/0.26sec] 
    ##   5  [0.1sec/0.1sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.24sec/0.14sec] 
    ##   2  [0.25sec/0.17sec] 
    ##   3  [0.31sec/0.19sec] 
    ##   4  [0.31sec/0.19sec] 
    ##   5  [0.22sec/0.11sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.2sec/0.22sec] 
    ##   2  [0.24sec/0.31sec] 
    ##   3  [0.22sec/0.17sec] 
    ##   4  [0.26sec/0.16sec] 
    ##   5  [0.23sec/0.16sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.17sec/0.21sec] 
    ##   2  [0.17sec/0.2sec] 
    ##   3  [0.2sec/0.16sec] 
    ##   4  [0.22sec/0.2sec] 
    ##   5  [0.22sec/0.21sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.18sec/0.24sec] 
    ##   2  [0.2sec/0.19sec] 
    ##   3  [0.2sec/0.22sec] 
    ##   4  [0.21sec/0.18sec] 
    ##   5  [0.2sec/0.18sec] 
    ## IBCF run fold/sample [model time/prediction time]
    ##   1  [0.18sec/0.19sec] 
    ##   2  [0.19sec/0.2sec] 
    ##   3  [0.14sec/0.22sec] 
    ##   4  [0.23sec/0.25sec] 
    ##   5  [0.23sec/0.24sec]
  • 마지막으로 시각화를 통하여 최적의 매개변수를 택합니다.

    plot(list_results, annotate = c(1, 2), legend = "topleft")
    title("ROC Curve")

    plot(list_results, "prec/rec", annotate = 1, legend = "bottomright")
    title("Precision-Recall")

반응형
TAGS.

Comments