협업 필터링 추천 시스템 구축하기
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개의 추천을 받은 사용자들은 모두 평가점수를 매기지 않았기 때문입니다.
- 일부 사용자들은 0개의 추천을 받았는데 이는 원래
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")
'Statistical Modeling & ML > Recommender system' 카테고리의 다른 글
추천 엔진에 이용되는 데이터 마이닝 기법 (0) | 2017.10.09 |
---|---|
추천 엔진의 이해 (0) | 2017.10.09 |
Bulid a recommendation system using R (2) | 2017.10.09 |
Introduction: Recommendation System (1) | 2017.10.09 |