앞서 봤듯이, 이제 predict 함수를 사용해 아이템을 추천할 수 있다.
recc_predicted <- predict(object = recc_model,
newdata = recc_data_test,
n = n_recommended)
recc_predicted의 itemLabels 슬롯에는 아이템 이름, 즉 웹사이트 영역 번호가 들어있다.
head(recc_predicted@itemLabels)
[1] "1038" "1026" "1034" "1008" "1056" "1032"
웹사이트 영역에 대한 설명을 표시하기 위해 table_items 객체를 사용할 수 있다. itemLabels에 포함된 번호들과 동일하게 table_items를 정렬하는 것이다. 이를 위해 웹사이트 영역 번호가 포함된 data.frame을 생성하고, table_items 테이블과 조인시킨다. 다음 단계를 통해 확인해본다.
- 웹사이트 영역 번호 열을 갖는 데이터 프레임을 생성한다.
- table_labels와 table_items를 왼쪽 테이블 기준 결합(LEFT JOIN)한다. sort = FALSE로 지정함으로써 정렬 순서를 동일하게 둔다.
- description 열의 데이터 타입을 factor형에서 character형으로 변환한다.
table_labels <- data.frame(id = recc_predicted@itemLabels)
table_labels <- merge(table_labels, table_items,
by = "id", all.x = TRUE, all.y = FALSE,
sort = FALSE)
descriptions <- as(table_labels$description, "character")
이제 table_labels를 살펴본다.
head(table_labels)
id description url category
1 1038 SiteBuilder Network Membership /sbnmember product
2 1026 Internet Site Construction for Developers /sitebuilder product
3 1034 Internet Explorer /ie product
4 1008 Free Downloads /msdownload product
5 1056 sports /sports product
6 1032 Games /games product
이제 우리는 추천하고자 하는 웹사이트 영역을 뽑을 수 있다. 예를 들어 첫 번째 사용자에 대한 추천 영역을 뽑아보자.
recc_user_1 <- recc_predicted@items[[1]]
items_user_1 <- descriptions[recc_user_1]
head(items_user_1)
[1] "Support Desktop"
[2] "Internet Explorer"
[3] "Knowledge Base"
[4] "Microsoft.com Search"
[5] "Products "
[6] "Internet Site Construction for Developers"
이제 모든 사용자에 대한 추천 웹사이트 영역이 정리된 테이블을 만들 수 있다. 각 열은 사용자에 해당하고 각 행은 추천 영역에 해당한다. n_recommended를 10으로 설정하면 테이블은 10개의 행을 갖게 된다. 이를 위해 sapply 함수를 사용함으로써 recc_predicted@items의 각 요소에 대한 descriptions를 식별한다.
그러나 사용자당 추천 웹사이트 영역의 수는 한 개에서 10개 사이며, 사용자마다 개수가 다르다. 10개의 행이 있는 구조화된 테이블을 정의하려면 각 사용자에 대해 같은 수의 값이 필요하다. 따라서 빠진 개수만큼의 추천 영역은 빈 문자열로 대체한다. 빈 문자열로 대체하는 작업은 빈 문자열을 rep 함수로 복제해 수행한다.
recc_matrix <- sapply(recc_predicted@items, function(x){
recommended <- descriptions[x]
c(recommended, rep("", n_recommended - length(recommended)))
})
dim(recc_matrix)
[1] 10 198
처음 세 사용자에 대한 추천 결과를 살펴본다.
head(recc_matrix[, 1:3])
10047 10089 10129
[1,] "Support Desktop" "Free Downloads" "Internet Explorer"
[2,] "Internet Explorer" "Microsoft.com Search" "Windows Family of OSs"
[3,] "Knowledge Base" "Windows95 Support" "Products "
[4,] "Microsoft.com Search" "Windows Family of OSs" "Windows95 Support"
[5,] "Products " "Products " "Internet Site Construction for Developers"
[6,] "Internet Site Construction for Developers" "Internet Site Construction for Developers" "SiteBuilder Network Membership"
추천된 웹사이트 영역을 보면, Products와 Internet Site Construction for Developers 가 세 사람에게 공통으로 추천된 것을 알 수 있다. 따라서 몇몇 영역은 추천될 확률이 더 높으리라 추정해볼 수 있다.
3장. '추천 시스템'에서 했던 것처럼 결과를 탐색해본다. 각 영역이 사용자들에게 몇 번 추천됏는지 확인해볼 수 있다.
table_recomm_per_item <- table(recc_matrix)
recomm_per_item <- as(table_recomm_per_item, "numeric")
결과를 시각화하기 위해 cut 함수를 사용해 구간 단위로 묶어준다.
bin_recomm_per_item <- cut(recomm_per_item, breaks = c(0, 10, 20, 100, max(recomm_per_item)))
qplot을 사용하면 recomm_per_item의 분포를 시각화할 수 있다.
qplot(bin_recomm_per_item) + ggtitle("Recommendations per item")
다음 그림은 웹사이트 영역의 추천 수를 표시한다.
대부분은 10번 이하로 추천됐으며, 일부 영역은 100번 이상 추천됐다. 즉, 롱테일 분포를 따르고 있다.
또한 우리는 recomm_per_item을 정렬해 가장 인기 있는 추천 영역을 확인할 수 있다.
recomm_per_item_sorted <- sort(table_recomm_per_item, decreasing = TRUE)
recomm_per_item_top <- head(recomm_per_item_sorted, n = 4)
table_top <- data.frame(name = names(recomm_per_item_top),
n_recomm = recomm_per_item_top)
table_top[, c(1,3)]
name n_recomm.Freq
1 Internet Explorer 126
2 Windows Family of OSs 125
3 Microsoft.com Search 118
4 Windows95 Support 118
이 장에서는 하이브리드 추천 모델을 만들고 탐색해봤다. 다음 단계는 만들어본 추천 모델을 평가하고 매개변수를 최적화하는 것이다.
모델 평가 및 최적화
이 장에서는 추천 시스템의 성능을 평가하는 방법을 설명한다. 모델을 평가하는 것부터 시작해서, 매개변수를 조정하고 최고의 성능을 내는 매개변수의 선택 과정을 다룰 것이다. 자세한 내용은 전 글 '추천 시스템의 평가'를 참고한다.
다음 모델을 평가하고 최적화하는 과정이다.
- 주어진 매개변수를 조정해 모델을 평가하는 함수를 생성한다.
- 함수를 사용해 매개변수를 다양하게 조정하면서 테스트하고, 최고 성능을 내는 설정을 찾는다.
이러한 단계를 자세히 살펴본다.
모델을 평가하는 함수 만들기
이 절에서는 다음과 같은 기능을 하는 함수를 정의할 것이다.
- k-fold를 사용해 교차 검증을 할 수 있도록 설정한다.
- 하이브리드 IBCF를 만든다.
- 테스트 세트의 사용자에게 아이템을 추천한다.
- 추천 결과를 평가한다.
함수의 입력 데이터는 다음과 같다.
- 데이터 : 웹사이트 영역의 내용 정보를 결합해서 만든 평점 매트릭스
- k-fold 매개변서 : K 겹의 수, 테스트 데이터 세트에 포함할 아이템의 수
- 모델 매개변수 : 최근접 이웃의 수, 아이템 설명 정보 기반 거리에 대한 가중치, 추천할 아이템 개수
이제 함수의 인자들을 정의해본다. 인자 옆에 주석으로 설명을 추가했다.
evaluateModel <- function(
# 입력데이터
ratings_matrix, # 평점 매트릭스(rating matrix)
table_items, # 아이템 설명 정보 테이블
#K-fold 매개변수
n_fold = 10, # 겹의 개수
items_to_keep = 4, # TEST 데이터 세트에 포함할 아이템 개수
# 모델 매개변수
number_neighbors = 30, # 최근접 이웃의 수
weight_description = 0.2, # 아이템 설명 정보 기반 거리에 대한 가중치
items_to_recommend = 10 # 추천 아이템의 개수
){
# 평가 (evalueate) 모델 파트
}
이제 함수의 바디에 들어갈 내용을 단계별로 살펴본다. 좀 더 자세한 설명을 위해 이전 글 '추천 시스템의 평가'를 참조할 수 있다.
1. 먼저 evaluationScheme 함수를 사용해 k-fold를 설정한다. 매개변수 k와 given은 각각 n_fold와 items_to_keep에 입력된 조건에 따라 설정된다. set.seed(1) 명령은 예제를 재현할 수 있게 하기 위해 입력한다. 즉, set.seed(1)을 지정하면 명령어를 반복 수행했을 때 임의의 구성 요소들이 동일하게 적용된다.
set.seed(1)
eval_sets <- evaluationScheme(data = ratings_matrix,
method = "cross-validation",
k = n_fold,
given = items_to_keep)
2. 그다음에는 Recommender 함수를 사용해 거리 계산 방법을 Jaccard로 정의하고, k 인자를 최근접 이웃의 숫자로 정의하는 IBCF 모델을 만든다.
recc_model <- Recommender(data = getData(eval_sets, "train"),
method = "IBCF",
parameter = list(method = "Jaccard",
k = number_neighbors))
3. 이제 모델에서 평점 기반 거리 매트릭스를 추출한다.
dist_ratings <- as(recc_model@model$sim, "matrix")
vector_items <- rownames(dist_ratings)
4. table_items 입력으로부터 아이템 설명 정보 기반 거리 매트릭스도 정의한다.
dist_category <- table_items[, 1 - as.matrix(dist(category == "product"))]
rownames(dist_category) <- table_items[, id]
colnames(dist_category) <- table_items[, id]
dist_category <- dist_category[vector_items, vector_items]
5. dist_ratings와 dist_category를 조합해 거리 매트릭스를 정의한다. 조합은 가중 평균을 사용하며, 가중치는 weight_description 입력 값에 의해 정의한다.
dist_tot <- dist_category * weight_description + dist_ratings * (1 - weight_description)
recc_model@model$sim <- as(dist_tot, "dgCMatrix")
6. recc_model을 이용해서 테스트 세트의 사용자들에 대해 예측한다. 우리는 0과 1의 평점만을 가진 테이블을 사용하기 대문에 type = "topNList" 인수로 상위 n개의 추천 아이템을 구하도록 지정할 수 있다. 추천 아이템 수를 정의하는 인수 n은 items_to_recommended 입력으로 정의한다.
eval_prediction <- predict(object = recc_model,
newdata = getData(eval_set, "known"),
n = items_to_recommend,
type = "topNList")
7. calcPredictionAccuracy() 를 사용해 모델 성능을 평가한다. byUser = FALSE를 지정해 정확도와 재현력 같은 평균적인 지표를 구한다.
eval_accuracy <- calcPredictionAccuracy(x = eval_prediction,
data = getData(eval_sets, "unknown"),
byUser = FALSE,
given = items_to_recommend)
8. 함수의 출력 값은eval_accuracy 테이블이 된다.
return(eval_accuracy)
9. 이제 함수를 테스트해본다.
model_evaluation <- evaluateModel(ratings_matrix = ratings_matrix,
table_items = table_items)
model_evaluation
TP FP FN TN precision recall TPR FPR
1.68269231 8.31730769 1.04807692 144.95192308 0.16826923 0.67772057 0.67772057 0.05416236
지표에 대한 자세한 설명은 '추천 시스템의 평가'에서 확인할 수 있다.
이 절에서는 주어진 설정을 통해 모델을 평가하는 함수를 정의했다. 이 함수는 매개변수 최적화에 도움을 줄 것이다.
'R > R로 만드는 추천 시스템' 카테고리의 다른 글
사례 연구 : 나만의 추천 시스템 만들기 - 04 (0) | 2020.04.03 |
---|---|
사례 연구 : 나만의 추천 시스템 만들기 - 02 (0) | 2020.03.31 |
사례 연구 : 나만의 추천 시스템 만들기 - 01 (0) | 2020.03.30 |
추천 시스템의 평가 - 04 (0) | 2020.03.29 |
추천 시스템의 평가 - 03 (0) | 2020.03.24 |