본문 바로가기

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

사례 연구 : 나만의 추천 시스템 만들기 - 04

반응형

모델 매개변수 최적화

evaluateModel 함수를 이용하면 추천 모델의 매개변수를 최적화할 수 있다. 이 절에서는 다음의 매개변수를 최적화한다.

  • number_neighbors : IBCF의 최근접 이웃 수
  • weight_description : 아이템 내용 정보 기반 거리에 부여한 가중치

다른 매개변수들도 최적화할 수 있지만, 단순화해 설명하기 위해 나머지는 기본값으로 둔다.

지금까지 만든 추천 모델은 IBCF와 아이템의 설명 정보를 결합한 것이다. 그러므로 먼저 IBCF를 최적화하는 것이 좋다. 먼저, number_neighbors 매개변수를 최적화한다.

 

우선 테스트할 값을 결정해야한다. 즉 k 값을 지정해야 하며, 이것은 적어도 아이템의 절반에 해당하는 80개의 아이템을 대상으로 하는 것이 좋다.

 

반면, 4보다 작은 값은 모델의 안정성을 위해 제외하는 것이 좋다. 값을 점진적으로 2씩 증가하게끔 지정하면, 테스트를 위한 벡터를 만들 수 있다.

 

nn_to_test <- seq(4, 80, by = 2)

 

이제는 number_neighbors 매개변수에 지정한 값에 따른 성능을 측정할 수 있다. 우리가 IBCF부분만 최적화하므로, weight_description 가중치는 0으로 설정한다. lapply 함수를 사용해 nn_to_test의 각 값에 대한 성능을 포함하는 리스트를 만든다.

 

list_performance <- lapply(X = nn_to_test, FUN = function(nn){
  evaluateModel(ratings_matrix = ratings_matrix,
                table_items = table_items,
                number_neighbors = nn,
                weight_description = 0)
})

 

리스트의 첫 번째 요소를 살펴본다.

 

list_performance[[1]]
          TP           FP           FN           TN 
  1.50961538   8.46153846   1.22115385 144.80769231 
   precision       recall          TPR          FPR 
  0.15096154   0.60466713   0.60466713   0.05511129 

 

리스트의 첫 번째 요소는 모든 성능 지표를 포함하고 있다. 모델을 평가하기 위해 정확도와 재현력을 사용할 수 있다. 자세한 내용은 '추천 시스템의 평가'에 설명됐다.

sapply함수를 사용해 정확도(또는 재현력) 벡터를 추출할 수 있다.

 

sapply(list_performance, "[[", "precision")
 [1] 0.1509615 0.1586538 0.1576923 0.1586538
 [5] 0.1596154 0.1596154 0.1625000 0.1634615
 [9] 0.1615385 0.1605769 0.1634615 0.1605769
[13] 0.1625000 0.1634615 0.1634615 0.1615385
[17] 0.1605769 0.1605769 0.1605769 0.1615385
[21] 0.1634615 0.1625000 0.1605769 0.1615385
[25] 0.1615385 0.1625000 0.1653846 0.1653846
[29] 0.1673077 0.1663462 0.1663462 0.1653846
[33] 0.1653846 0.1634615 0.1625000 0.1625000
[37] 0.1625000 0.1634615 0.1634615

 

출력된 결과를 분석하기 위해 nn_to_test, precision, recall 열을 갖는 테이블을 만들어본다.

table_performance <- data.table(
  nn = nn_to_test,
  precision = sapply(list_performance, "[[", "precision"),
  recall = sapply(list_performance, "[[", "recall")
  )

 

추가로, 최적화할 성능 지표를 정의할 수 잇다. 성능 지표는 정확도와 재현력 사이의 가중 평균으로 구할 수 있다. 이번 예제의 경우 가중치는 0.5로 설정한다.

 

weight_precision <- 0.5
table_performance[, perfomance := precision * weight_precision + recall * (1 - weight_precision)]

head(table_performance)
   nn precision    recall perfomance
1:  4 0.1509615 0.6046671  0.3778143
2:  6 0.1586538 0.6194559  0.3890549
3:  8 0.1576923 0.6212918  0.3894921
4: 10 0.1586538 0.6196276  0.3891407
5: 12 0.1596154 0.6202000  0.3899077
6: 14 0.1596154 0.6197808  0.3896981

 

정확도는 실제로 조회한 아이템 중 추천 아이템의 백분율이며 재현력은 추천 아이템 중 실제 조회 아이템의 백분율이다.

 

table_performance 테이블은 모든 평가 매트릭스를 포함한다. 이 매트릭스를 이용해서 최적의 nn을 찾는 데 도움의 되는 도표를 그려볼 수 있다.

 

도표를 작성하기 전에 ggplot2 함수와 함께 사용할 convertIntoPercent 함수를 정의해본다.

convertIntoPercent <- function(x){
  paste0(round(x*100), "%")
}

 

이제 도표를 만들 준비가 됐다. 첫 번재 도표는 nn을 기반으로 하는 정확도 도표다. 다음 함수를 사용해 도표를 만들 수 있다.

  • qplot : 산점도를 만들어준다.
  • geom_smooth : 부드러운 곡선을 추가해준다.
  • scale_y_continuous : y축의 스케일을 변경해준다. 이번 예제의 경우 퍼센트(%)로 표시한다.

다음 명령어는 앞의 내용으로 작성했다.

qplot(table_performance[, nn],
      table_performance[, precision]) + geom_smooth() + scale_y_continuous(labels = convertIntoPercent)

다음 그림은 위 코드의 결과다.

파란색 선을 보면 nn = 65 부근에서 최댓값을 이룬다. 정확도는 성공적인 추천 비율을 나타내므로, 광고 등의 비용 집행에 대한 성과 지표로 사용하기에 유용하다.

 

유사한 명령어를 사용해 재현력을 살펴본다.

qplot(table_performance[, nn],
      table_performance[, recall]) + geom_smooth() + scale_y_continuous(labels = convertIntoPercent)

다음 그림은 이전 코드의 결과다.

최대 재현력은 약 nn = 70 선에서 정점을 이루고 있다. 이 지수는 우리가 추천하는 항목의 실제 조회 비율을 나타내므로, 사용자들의 조회를 예측하고 싶을 때 유용하다.

정확도와 재현력을 동시에 고려해 성능을 살펴볼 수도 있다. 이를 확인해본다.

qplot(table_performance[, nn],
      table_performance[, perfomance]) + geom_smooth() + scale_y_continuous(labels = convertIntoPercent)

최적의 성능은 nn 값이 약 60일 경우 나온다. which.max 함수를 사용해 최상의 nn을 식별할 수 있다.

 

row_best <- which.max(table_performance$perfomance)
number_neighbors_opt <- table_performance[row_best, nn]
number_neighbors_opt
[1] 60

 

최적 값은 60 이다. 우리는 IBCF 매개변수를 최적화했다. 다음 단계는 아이템 설명 정보의 가중치를 결정하는 것이다. 먼저, 시도할 가중치를 정의해본다. 가능한 가중치의 범위는 0에서 1 사이며, 가령 0.05씩 점진적으로 올려볼 필요가 있다.

wd_to_try <- seq(0, 1, by = 0.05)

 

lapply 함수를 사용해 우리는 가중치에 따른 추천 시스템을 테스트할 수 있다.

list_performance <- lapply(
  X = wd_to_try, FUN = function(wd){
    evaluateModel(ratings_matrix = ratings_matrix,
                  table_items = table_items,
                  number_neighbors = number_neighbors_opt,
                  weight_description = wd)
})

 

앞의 경우와 마찬가지로 정확도, 재현력, 성능이 포함된 테이블을 만들 수 있다.

table_performance <- data.table(
  wd = wd_to_try, precision = sapply(list_performance, "[[", "precision"),
  recall = sapply(list_performance, "[[", "recall")
)

table_performance[, performance := precision * weight_precision + 
                    recall * (1 - weight_precision)]

 

이제 도표를 통해 가중치를 기준으로 성능을 시각화할 수 있다.

qplot(table_performance[, wd], table_performance[, performance]) +
  geom_smooth() + scale_y_continuous(labels = convertIntoPercent)

 

다음 그림은 앞의 명령어 출력 결과다.

 

성능은 극단적인 값을 제외하고는 각 포인트에 대해 같다. 이 경우에 geom_smooth 옵션으로 회귀선과 신뢰 구간을 그려봐도 큰 도움은 되지 않는다.

지금까지 조회 평점과 아이템 설명 정보를 모두 고려해 최상의 성능을 내는 추천 시스템을 만들었다. 가중치를 극단적으로 0.00으로 지정한 결과는 순수하게 IBCF만을 적용한 결과에 해당하며, 이는 하이브리드 추천 시스템보다 성능이 다소 낮다. 가중치를 1.00 으로 지정한 모형은 아이템 설명 정보만으로 추천한 것이고, 따라서 성능이 매우 낮다.

 

성능이 많이 변하지 않는 이유는 아이템 설명 정보가 이진적인 특성을 가지기 때문이다. 다른 특징을 추가하면 더 높은 성능을 낼 수 있을 것이다.

 

이 절에서는 두 가지 매개변수를 기반으로 추천 알고리즘을 최적화하는 방법을 설명했다. 다음 단계는 나머지 IBCF 매개변수에 기초해 모델을 최적화하고 아이템 설명 정보를 개선하는 일일 것이다.

 

요약

이 장에서는 현실 세계에서 추천 시스템 기법들을 적용하는 방법을 설명했다. 구조화되지 않은 원시 데이터로부터 시작해서 협업 필터링의 입력 데이터 형태인 평점 매트릭스르 만들었고, 또한 아이템에 대한 설명 정보를 추출해 모델의 성능을 향상했으며, 모델의 성능 평가를 통해 매개변수를 최적화했다. 이와 같은 접근은 데이터를 적절하게 정제시켜놓은 경우 각 현실의 문제들에도 충분히 적용할 수 있다. 

 

이 책에는 머신 러닝의 기초와 실용적인 응용 방법들이 담겨 있다. 이 책을 완독하고 나면 가장 적절한 추천 기법을 찾아내는 현실 세계의 어려운 일들을 처리할 수 있을 것이다.

반응형