.__.

[추천 시스템 입문] CH07. 추천 시스템 평가 - (1) 오프라인 평가 본문

추천 시스템/추천시스템입문

[추천 시스템 입문] CH07. 추천 시스템 평가 - (1) 오프라인 평가

yesjiyoung 2024. 3. 8. 00:00

들어가는 글


오프라인 평가 즉, 모델의 자체의 성능 평가를 위한 평가지표를 알아보고, 수많은 평가지표 중 어떤 지표를 선정하는 것이 좋을지에 대한 선정방법에 대해 공부해본다. 

 

7.2 오프라인 평가


오프라인 평가 지표 

예측 오차 지표 


  • 사용자가 아이템에 부여한 명시적인 평가값과 시스템이 예측한 평가값의 오차를 평가하는 것
  • 지표를 이해하기 위한 변수
MAE
  • MAE = Mean Absolute Error = 평균 절대값 오차 = 예측값과 실제값 차이의 절대값 평균을 나타내는 지표

$$ MAE = \frac{1}{n}\sum_{i=1}^{n}\left|{r_i - \hat{r_i}}\right| $$

MSE
  • MSE = Mean Squared Error = 평균 제곱 오차를 = 예측값과 실제값 차이의 제곱 평균을 나타내는 지표
  • 제곱을 함으로써 예측값과 실제값의 차이가 크면 그 값이 더 커지고, 그렇지 않으면 미미한 차이를 나타낸다.

$$ MSE = \frac{1}{n}\sum_{i=1}^{n}({r_i - \hat{r_i}})^2 $$

RMSE
  • RMSE = Root Mean Squared Error = 평균 제곱근 오차 = MSE의 제곱근을 구해 오차의 크기를 더 직관적으로 이해
  • 즉 MSE는 오차의 크기를 그대로 보존한다면, RMSE는 실제 오차의 크기에 대한 직관을 제공한여 일반적으로 더 많이 사용된다. 

 

$$ RMSE = \sqrt{\frac{1}{n}\sum_{i=1}^{n}({r_i - \hat{r_i}})^2} $$

 

집합 평가 지표


  • 모델이 사용자에게 클릭된다고 예측한 아이템 집합(예측 아이템 집합)과 사용자 실제로 클릭한 아이템 집합(적합 아이템 집합)의 값을 비교하여 계산한다.
  • 여기서는 어떤 사용자에 대해서만 값을 계산하는 예를 소개하지만, 일반적으로 추천 시스템 평가에서는 각 사용자에 대해 지표를 계산 한 후, 평가 대상 전체 사용자에 대한 평균을 구해 평가한다.
  • 지표를 이해하기 위한 변수

$$ C : 적합 아이템 집합 \\ K : 순위의 길이 \\ R_k : 예측한 아이템 집합의 k번째 이내 아이템 $$

 

  • 지표를 이해하기 위한 예시 데이터
# 예측 아이템 집합, 예측 점수가 높은 순으로 배열 
pred_items = ["p1", "p2", "p3", "p4", "p5"]

# 적합 아이템 집합,
true_items = ["p2", "p4", "p6", "p8"]

 

Precision@K
  • Precision = 정밀도 = 예측 아이템 집합 안에 존재하는 적합아이템의 비율을 의미
  • 순위의 길이가 K일 때, Precision@K 로 표현

 

$$ Precision@K = \frac {\left| C \cap R_k \right|}{K} $$

 

  • ex. Precision@3 은 예측 아이템 Top 3위 내에 속한 아이템 중 1개의 아이템이 적합하므로 Precision@3 =1/3
  • 코드
def precision_at_k(true_items: List[int], pred_items: List[int], k: int) -> float:
    if k == 0: return 0.0
	
    p_at_k = (len(set(true_items) & set(pred_items[:k]))) / k 
    
    return p_at_k

# 예시, k = 3 
print(precision_at_k(true_items, pred_items, 3)) # 0.333333333

 

 

Recall@K
  • Recall = 재현율 = 예측 아이템 집합 요소가 얼마나 적합 아이템 집합의 요소를 커버하는지에 대한 비율을 의미
  • 순위의 길이가 K일 때, Recall@K 로 표현

$$ Recall@K = \frac {\left| C \cap R_k \right|}{C} $$

  • ex. Recall@3 은 적합 아이템 총 4개 중에서 예측 아이템 Top 3위 내에 속한 아이템의 개수를 적합아이템 수로 나눈 것 Recall@3 = 1/4
  • 코드
def recall_at_k(true_items: List[int], pred_items: List[int], k: int) -> float:
    if len(true_items) == 0 or k == 0:
		return 0.0

    r_at_k = (len(set(true_items) & set(pred_items[:k]))) / len(trun_items)
	
    return r_at_k

# 예시, k = 3 
print(recall_at_k(true_items, pred_items, 3)) # 0.25

 

F1@K
  • Precision과 Recall은 한 쪽 값이 올라가면, 다른 값이 내려가는 trade-off 관계이다.
  • Recall@K의 K값을 늘리면, 예측 아이템 집합에 포함된 적합 아이템이 늘어나기 때문에, Recall이 향상됨.
    한편 사용자에게 적합하지 않은 아이템의 비율도 증가하기 때문에 Preicsion은 낮아짐
  • 두 지표를 고려해 평가하는 지표 → F1-measure

$$ F1 = \frac{2Recall*Precision}{Recall + Precision} $$

  • ex. F1@3은 Precision@3=1/3 Recall@3=1/4 를 이용하여, 0.286
  • 코드
def f1_at_k(true_items: List[int], pred_items: List[int], k: int) -> float:
    precision = precision_at_k(true_items, pred_items, k)
    recall = recall_at_k(true_items, pred_itmes, k)
    
    if precision + recall == 0.0:
    	return 0.0
    
    return 2 * precision * recall / (precision + recall)

# 예시, K = 3 
print(f1_at_k(true_items, pred_items, 3)) # 0.2857

 

 

순위 평가 지표


  • 추천 대상 아이템에 점수를 부여하여 그 점수가 높은 순으로 아이템을 정렬한 순위를 만든다.
  • 이 순위에 대해 각 아이템의 배열을 고려하여, 좋고 나쁨을 평가하는 지표가 순위 평가 지표이다.
PR곡선
  • Top@K를 Top@1, Top@2, …, Top@N에 따라, Recall과 Precision의 여러 조합의 결과물을 얻을 수 있다.
  • 이 점들에 대해 Recall을 가로 축, Precision을 세로 축으로 플롯해서 각 점을 연결하는 것이 PR곡선이다.
  • ex. Top@K의 임계값을 바꿔(Recall, Precision)의 점을 플롯 

Recall과 Precision값

nDCG

 

  • nDCG는 Top K개의 아이템을 추천하는 경우, 추천 순서에 가중치를 두어 평가한다. 
  • nDCG@K값은 1에 가까울 수록 좋다. 
  • nDCG@K는 순서별로 가중치 값(관련도, relevance score)를 다르게 적용하여 계산한다. 

$$ nDCG@K = \frac{DCG@K}{DCG_{ideal}@K} $$

  • nDCG란 normalized Discounted Cumulative Gain으로 DCG(Discounted Cumulative Gain) 값을 순위가 이상적으로 나열되었을 때의 DCG로 나누는 것을 의미 ⇒ 정규화

$$ DCG@K = r_1 + \sum_{i=2}^{K}\frac{r_i}{log_2(i+1)} $$

  • 상위 순위에서 정답을 얻으면, DCG에 대한 기여도가 커지고
  • 하위 순위에서 정답을 얻으면, DCG에 대한 기여가 작아진다.
  • 예시1 )

sungkee-book.tistory.com/11 글 참고

 

  • 예시2 ) 
    • 이익 = relvence score(not click = 0, click = 1, conversion = 2
    • 모델의 DCG / 이상적인 DCG

모델의 순위 및 이익

 

 

$$ DCG = 0 + \frac{2}{log_23} + \frac{0}{log_24} + \frac{1}{log_25} + \frac{0}{log_26} = 2.5 $$

 

이상적인 순위 및 이익

 

$$ DCG_{ideal} = 2 + \frac{1}{log_23} + \frac{0}{log_24} + \frac{0}{log_25} + \frac{0}{log_26} = 3.0 $$

$$ nDCG@5 = \frac{2.5}{3.0} = 0.833 $$

  • 코드
def dcg_at_k(user_relevances: List[int], k: int) -> float:
    user_relevances = user_relevances[:k]
    
    if len(user_relevances) == 0: return 0.0
    
    return user_relevances[0] + np.sum(user_relevances[1:] / np.log2(np.arange(3, len(user_relevances) + 2)) 


def ndcg_at_k(user_relevances: List[int], k: int) -> float:
    dcg_max = dcg_at_k(sorted(user_relevances, reverse=True), k)
    
    if not dcg_max:
    	return 0.0
        
    return dcg_at_k(user_relevances, k) / dcg_max

print(ndcg_at_k([0,2,0,1,0], 5)) # 0.8333
더보기
MRR@K

 

AP@K

 

MAP@K

 

 

기타 평가 지표

  • 예측 오차, 집합 평가, 순위 평가 모두 “사용자가 클릭한 아이템을 가급적 상위에 나타내기 위한 추천 시스템 지표”이다.
  • 하지만 정밀도만 추구하는 것은 비슷한 상품만 추천해버리는 *필터 버블 문제를 비롯해 서비스에서 바람직하지 않은 부작용을 일으킬 위험이 있다.
  • 또한, 영화나 음악과 같은 도메인에서는 사용자가 예측하지 못한 미지의 추천이 오히려 사용자의 만족도가 더 높을 수가 있다.
  • 따라서 정밀도 이외에 커버리지, 신규성, 다양성, 흥미로움 지표도 존재한다.
  • 필터 버블?

카탈로그 커버리지
  • 카탈로그 커버리지의 분자는 실제로 추천한 상품의 수이고 분모는 모든 상품의 수이다.
  • 이처럼 커버리지는 추천 범위(폭)을 측정하는 지표이다.
  • 이 카탈로그 커버리지를 측정함으로써 인기 상품에 치우친 추천을 검출할 수 있다.

$$ Catalogue Coverage = \frac{\left|\hat{I}\right|}{\left|I\right|} $$

사용자 커버리지
  • 사용자 커버리지는 어느 정도의 사용자에게 추천되었는지를 측정하는 지표이며, 분자는 실제로 추천이 수행된 사용자 수, 분모는 모든 사용자 수이다.
  • 사용자 커버리지는 콜드 스타트 문제 검출에 사용할 수 있다.
    • 서비스를 막 시작한 초기 사용자로 필터링해 사용자 커버리지를 측정함으로써 초기 사용자에게 어느 정도 추천했는지를 측정할 수 있다.
    • 이 초기의 사용자에 대해 사용자 커버리지가 낮을 경우 초기 사용자에 대해 추천이 수행되지 않는 콜드 스타트 문제가 발생했다는 것을 의미한다.
    • 커버리지를 일 단위로 측정하는 것은 시스템 이상 검출에도 도움이 된다. 예를들어 커버리지가 어느날 갑자기 하락된 경우 로그의 결손이나 모델의 업데이트 오류가 발생한 것으로 생각할 수 있음.

$$ User Coverage = \frac{\left|\hat{U}\right|}{\left|U\right|} $$

신규성
  • 신규성은 추천 아이템이 정말로 새로운지를 나타낸다. 
  • p(i)는 모든 사용자에 대해 과거 그 아이템이 추천된 확률을 나타낸다. 
  • 이 정의에 따라 사용자에게 표시되기 어려운 아이템을 폭넓게 표시하면 신규성이 커진다.

$$ Novelty(R) = \frac{\sum_{i\in R}-log_2p(i)}{\left|R\right|} $$

$$ R : 순위 \\ p(i) = \frac{\sum_{i\in R}-imp(u,i)}{\left|U\right|} \\ imp(u,i) = \begin{cases} 1, & \text{사용자 u에게 아이템 i가 과거에 추천된 경우} \\ 0, & \text{그 외 } \end{cases} $$

 

다양성
  • 순위 R에서의 다양성은 순위의 각 아이템 간 유사도 거리의 평균값에 따라 정의
  • 예를들어, 유사도로 제곱오차를 생각하는 경우, 각 아이템 간의 거리가 먼 경우 다양성이 커진다.
  • 이 정의는 순위에만 존재하는 다양성 지표이다.

$$ Diversity(R) = \frac{\sum_{i\in R}\sum_{j\in R} Sim(i,j)}{\left|R\right|(\left|R\right| -1)} $$

 

흥미로움
  • 흥미로움은 순위에 대한 의외성을 가지면서도 유용한 아이템의 비율을 측정한다.
  • R : 순위
  • R_unexp : 순위 R에서 의외성이 있는 아이템의 집합
  • R_useful : 순위 R에서 유용한 아이템 집합

$$ Serendipity(R, u) = \frac{\left|R_{unexp} \cap R_{useful}\right|}{\left|R\right|} $$

 

평가지표 선정 방법


  • 방법1) 어떤 추천/검색시스템인지 정의를 하는 과정에서 경험적으로 어떤 피쳐가 더 좋을지 생각한다
    • Precision이 좋을지 / recall이 좋을지
  • 방법2) 경험이 부족하여 잘모르겠다면, 타겟팅한 온라인 평가와 관련된 오프라인 지표를 찾아내는 것이다.
    • Precision@K, Recall@K, MAP@K, nDCG@K 등 각 지표에서 가장 좋았던 모델을 실제로 릴리즈하고 매출 드의 지표가 높은 모델을 조사한다.
    • 그렇게 하면, 어떤 오프라인 지표가 해당 서비스에서 적절한지 알 수 있다.
  • 방법3) 온라인 평가와 일치하도록 여러 오프라인 지표를 조합해 새로운 오프라인 지표를 만드는 방법도 있다.
    • 실제로 어떤 연구에서는 예측 정밀도에 대한 평가 지표만 사용하는 것보다 흥미로움이나 커버리지 같은 오프라인지표도 조합하여 이를 타겟팅했을 때, 실제 클릭률이 높은 추천 모델을 만들었다고 함.
  • 방법4) 사용자의 행동이력을 가정해 지표를 선택
    • 사용자의 행동이력
      • 유도형(Navigational) : 어떤 특정 사이트를 방문하려는 의도 ex. 1개의 적합 아이템을 얻고 싶을 때 (열차시간표를 알기 위해 웹사이트 검색)
      • 정보수집형(Informational) : 1개 이상의 웹 페이지에 기록되어 있다고 생각되는 정보를 얻으려는 의도 ex.1개 이상의 적합 아이템 얻고 싶을 때 (온난화 원인을 조사하기 위해 검색)
      • 거래형(Transactional) : 웹을 매개로 한 액션을 실행하려는 의도 ex. 식당을 예약하는 경우
    • 1개이상의 적합아이템을 중요시하는 경우 → Average Precision이나 nDCG등을 이용
    • 1개의 적합아이템을 중요시하는 경우 → Reciprocal Rank나 EPR사용
    • 참고 (행동 의도에 따른 적합한 평가 지표 유형)

행동의도에 따른 적합한 평가 지표

  • 특히 ERR = Expected Reciprocal Rank는 정보 검색 분야에서 유명한 지표이다.
  • 주목한 아이템의 순위에 위치를 추가해, 해당 아이템보다 위에 있는 아이템으로부터 정의된 정지 확률에 의존하는 지표

=> ERR, MRR, AP, MAP 및 신규성, 다양성, 흥미로움 지표 다시 공부하기