Scott Lundberg의 Interpretable Machine Learning with XGBoost를 번역했습니다.


기계 학습 모형을 잘못 해석할 때의 위험성 그리고 올바르게 해석할 때의 가치에 관한 이야기다. 그래디언트 부스팅 머신이나 랜덤 포레스트 같은 앙상블 트리 모형의 굳건한 정확도를 확인했다면, 또 결과를 해석해야 한다면 유익하고 도움이 될 내용이다.

은행에서 고객의 재정 상태를 예측하는 업무가 있다고 상상해보자. 모형이 정확할수록 은행은 많은 돈을 벌겠지만 예측값이 대출 신청에 사용될 터이니 해당 예측을 한 합법적 이유를 설명해야 한다. 여러 모형을 실험한 결과 XGBoost가 구현한 그래디언트 부스팅 트리 정확도가 가장 높다는 걸 알았다. XGBoost 예측의 이유를 설명하기 까다로워 보이므로 선형 모형으로 돌아가거나 XGBoost 모형을 해석할 수 있는 방안을 고심해봐야 한다. 데이터 과학자라면 정확도를 포기하고 싶지 않을 것이기에 후자를 시도하며 복잡한 XGBoost 모형(깊이가 6인 1,247개의 트리)을 해석해보기로 결정했다.

고전적인 전역 변수 중요도 측정

첫 번째 확실한 선택은 파이썬 XGBoost 인터페이스에서 plot_importance() 메서드를 사용해 보는 것이다. 메서드는 데이터셋 각 변수의 중요도를 나타내는 흥미롭고 단순한 막대 차트를 제공한다(본문을 재현하는 코드는 주피터 노트북에 있음)

그림1

고전적인 “성인” 인구 조사 데이터셋에서 각 사람의 수입이 5만 달러 이상일지 예측하기 위해 (로지스틱 손실을 적용하여) 훈련시킨 모형에 xgboost.plot_importance(model)을 실행한 결과.

XGBoost가 출력한 변수 중요도를 보면 다른 변수를 뛰어넘는 수입에 관한 가장 중요한 예측 변수로 연령을 꼽고 있다. 여기서 멈추고 관리자에게 나이가 가장 중요한 변수이고 주당 근무 시간교육 수준이 뒤를 잇는다고 상식적으로 만족할만한 보고를 드릴 수 있다. 그러나 훌륭한 데이터 과학자라면 문서를 보고 XGBoost에 변수 중요도를 측정하는 세 가지 선택 사항이 있음을 확인할 것이다.

  1. 가중치. 모든 트리에서 각 변수가 데이터를 분할하는 데 사용된 횟수.

  2. 적용 범위. 모든 트리에서 각 변수가 데이터를 분할하는 데 사용된 횟수. 단, 분할을 거치는 훈련 데이터 개수에 따라 가중치를 적용함.

  3. 이득. 분할에 각 변수를 사용할 때마다 감소한 평균 훈련 손실.

이는 트리 기반 모델링 패키지에서 찾을 수 있는 중요도의 대표적 척도이다. 가중치가 기본 선택 사항이었기에 다른 두 가지 접근법과 차이가 있는지 살펴보았다.

그림2

importance_type = “cover”와 importance_type = “gain” 모두 사용하여 xgboost.plot_importance를 실행한 결과.

XGBoost에서 제공하는 세 가지 선택 사항마다 변수 중요도 순서가 매우 다르다는 사실을 알게 되었다! 적용 범위 방식을 보면 자본 이익 변수가 소득에서 가장 중요한 예측 변수인 것처럼 보이지만 이득 방식을 보면 결혼 상태 변수가 다른 모든 변수를 압도한다. 어떤 방식이 가장 적합한지 알지 못한 채 변수 중요도 보고를 이런 척도 선택에 맡겨야 한다는 점이 마음을 매우 불편하게 만든다.

변수 중요도를 측정하는 기준으로 어떤 걸 좋거나 나쁘다고 할 수 있을까?

변수 기여도를 측정하는 하나의 방식을 다른 방식과 비교할 기준은 명확하지 않다. 데이터 정리, 편향 탐지 등의 작업을 통해 각 방식의 최종 사용자 성능을 측정해볼 수 있겠다. 그러나 이 작업은 변수 기여도 분석 방식의 품질에 관한 간접적 측정이 될 뿐이다. 대신 여기서 변수 기여도 방식이 가져야 할 두 가지 좋은 성질을 정의해보자.

  1. 일관성. 변수를 더 많이 사용하게끔 모형을 변경할 때마다 기존 변수가 기여한 중요도는 감소하지 말아야 한다.

  2. 정확성. 각 변수 중요도의 합계가 모형의 전체 중요도여야 한다. 예를 들어 중요도가 R2 값으로 측정되는 경우 각 변수 기여도의 합이 전체 모형 R2이 되어야 한다.

일관성이 유지되지 못하면 임의의 두 모형 간 변수 기여도를 비교할 수 없다. 기여도가 더 높기 때문에 모형이 실제로 해당 변수에 더 의존한다고 말할 수 없기 때문이다.

정확성이 유지되지 못하면 각 변수의 기여도가 결합되어 전체 모형 출력 값으로 나타나는 과정을 알 수 없다. 방식의 일관성이 깨질 수 있기 때문에 방식을 수행한 다음 기여도를 정규화시키는 작업도 할 수가 없다.

현재의 기여도 방식은 일관되고 정확한가?

은행의 데이터 과학자 입장으로 돌아가면… 일관성과 정확성이 중요하다는 걸 이제 알고 있다. 사실 방식의 일관성이 없다면 가장 높은 기여도를 가진 변수가 실제로 가장 중요하리라는 보장은 없다. 그래서 은행 업무와 관련 없는 매우 간단한 트리 모형 두 개를 사용하여 각 방식의 일관성을 점검해보자.

그림3

2개의 변수를 사용한 간단한 트리 모델링. 기침은 모형 A보다 명백히 모형 B에서 중요하다.

모형 결괏값은 개인 증상을 바탕으로 한 위험 점수이다. 모형 A는 발열기침의 이진 값 변수에 대한 단순 “and” 함수에 지나지 않는다. 모형 B는 같은 함수지만 기침이 예인 경우 +10이다. 일관성을 확인하기 위해 “중요도”를 정의해야 한다. 여기서 중요도는 다음 두 가지 방법으로 정의할 것이다. 1) 일련의 변수를 제거할 때 변하는 모형의 기대 정확도와 2) 일련의 변수를 제거할 때 변하는 모형의 예상 출력 값.

중요도의 첫 번째 정의는 모형에 대한 변수의 전역적인 영향력을 측정한다. 두 번째 정의는 단일 예측값에 대한 변수의 개별화된 영향력을 측정한다. 단순 트리 모형의 경우, 기침 변수는 모형 B에서 명백히 더 중요하다. 전역 중요도와 발열기침이 모두 예일 때의 개별 예측 모든 면에서 말이다.

가중치, 적용 범위이득 방식 모두 각 변수의 전역 기여도를 측정하는 방식이다. 그러나 모형을 은행에 배포할 때는 각 고객에 대한 개별적인 설명이 필요하다. 일관성을 확인하기 위해 단순 트리 모형에 6개의 상이한 변수 기여도 방식을 수행했다.

  1. 트리 SHAP. 우리가 제안하는 새롭고 개별화된 방식.
  2. Saabas. 개별화된 휴리스틱 변수 기여도 방식.
  3. 평균 (|트리 SHAP|). 개별화된 트리 SHAP 기여도의 평균 크기를 기반으로 한 전역 기여도 방식.
  4. 이득. 위에서 사용한 XGBoost 방식과 같고 Scikit-Learn 트리 모형에서 사용하는 Gini 중요도 측정 방법과 동일하다.
  5. 분할 횟수. 밀접하게 연관된, XGBoost의 “가중치”와 “적용 범위” 방식 모두를 말하지만 여기서는 “가중치” 방식을 사용하여 계산했다.
  6. 순열. 시험 데이터셋에서 단일 변수를 무작위로 치환할 때 하락하는 모형 정확도 결과.

그림4

여섯 가지 방식을 사용하여 구한 모형 A와 모형 B의 변수 기여도. 알겠지만 자료의 방식들 모두 트리 고유의 변수 기여도 방식을 이야기한다.

변수 순열 이외 과거의 모든 방식이 일관성이 없다! 모형 A보다 모형 B에서 기침이 덜 중요하게 나오기 때문이다. 일관성 없는 방식은 가장 영향력 있는 변수에 중요도를 더 높게, 올바르게 할당했을 거라고 신뢰할 수 없다. 위에서 고전적 변수 기여도 방식이 동일한 모형에서 서로 상이한 결과로 나왔을 때 기민한 독자는 이런 비일관성을 일찍 눈치챘을 것이다. 정확성 속성은 어떨까? 트리 SHAP, Sabaas와 이득 방식은 앞에서 정의한 대로 정확하며 변수 순열 및 분할 횟수는 부정확하다.

이득(Gini 중요도)과 같이 널리 사용되는 방식이 이렇게 명확하게 비 일관적인 결과를 가져온다는 사실은 좀 놀랍다. 왜 이런 일이 발생하는지 더 잘 이해하기 위해 모형 A와 모형 B를 두고 이득 계산 방식을 살펴보겠다. 단순화하기 위해 데이터셋의 25%가 각 리프에 속하고 각 모형의 데이터셋 레이블은 모형의 출력 값과 정확히 일치한다고 가정하자.

손실 함수로 평균 제곱 오차(MSE)를 고려하면 모형 A는 임의의 분할을 수행하기 전 1,200의 MSE로 시작한다. 이건 20이라는 상수 평균 예측으로부터의 오차이다. 모형 A는 발열로 분할된 이후 MSE가 800으로 떨어지므로 이득 방식은 이 400의 하락분을 발열 변수가 기여한 것으로 본다. 기침 변수로 다시 분할하면 MSE가 0이 되고 이득 방식은 이 800의 하락분을 기침 변수가 기여한 것으로 본다. 모형 B는 같은 과정을 통해 발열 변수에 800의 중요도를, 기침 변수에 625의 중요도를 할당한다.

그림5

모형 A와 모형 B의 이득 점수(Gini 중요도) 계산.

일반적으로 트리 루트 쪽에 있는 변수가 리프 근처에서 분할한 변수보다 더 중요할 거라고 기대한다(트리는 탐욕스럽게 구성되기 때문에). 그러나 이득 방식은 낮은 쪽 분할의 기여 중요도가 더 높게끔 편향되어있다. 편향은 비일관성으로 이어지고 기침이 더 중요해지면(따라서 루트에서 분할하면) 실제 기여 중요도는 하락한다. treeinterpreter 패키지가 사용하는 개별화된 Saabas 방식은 트리를 내려가며 예측 차이를 계산하므로 트리 낮은 쪽 분할에 대해 동일한 편향을 갖는다. 트리 깊이가 깊어질수록 이러한 편향은 더욱 커진다. 이와 달리 트리 SHAP 방식은 트리에서의 위치가 지정한 순서가 아니라 변수의 모든 가능한 순서에 대해 예측 차이를 구해 평균 낸 것과 수리적으로 동일하다.

트리 SHAP만이 일관되고 정확한 건 우연이 아니다. 일관되며 정확한 방법을 원할 경우 변수 중요도를 할당하는 방식은 유일하다. 세부 사항은 최근 NIPS 논문에 나와 있지만 요약하면 수익의 공정한 배분에 관한 게임 이론적 증명은 기계 학습에서 변수 기여 방식의 유일성 결론으로 이어진다. 1950년대 Lloyd Shapley가 유도한 이래 이 유일한 값을 Shapley 값으로 부른다. 여기서 사용하는 SHAP값은 Shapley 값에 연결된, 개별화된 모형 해석 방식 여러 개를 통합한 결과이다. 트리 SHAP는 고전적인 지수 실행 시간 (arXiv 참조) 대신 다항식 시간 안에 트리의 SHAP 값을 정확히 계산할 수 있는 고속 알고리즘이다.

신뢰도 있게 모형 해석하기

견고한 이론적 토대에 빠르고 실용적인 알고리즘이 더해져 SHAP 값은 XGBoost 그래디언트 부스팅 머신 같은 트리 모형을 신뢰도 있게 해석할 수 있는 강력한 도구가 된다. 이 새로운 접근법으로 무장하고 은행의 XGBoost 모형을 해석하는 작업으로 돌아가 보자.

그림6

소득 예측 모형에 사용한 전역 평균(|트리 SHAP|) 방법. x축은 본질적으로 모형에서 변수가 “숨겨질” 때 모형 출력 값이 변화하는 크기의 평균이다.(이 모형의 경우 출력 값은 로그 오즈 단위를 갖는다.) 자세한 내용은 논문을 참조하라. “숨김”은 모형에서 해당 변수를 적분하여 소거하는 걸 의미한다. 변수를 숨겼을 때 영향력은 숨겨진 다른 변수에 따라 달라지므로 일관성과 정확성 유지를 위해 Shapley 값이 사용된다.

실제로 관계 변수가 가장 중요함을 알 수 있으며 연령 변수가 그 뒤를 잇는다. SHAP 값은 일관성을 보장하므로 이득과 분할 횟수 계산 방법을 적용할 때 문제 되었던 상반된 결과에 관해 걱정할 필요가 없다. 이제 모든 사람마다 개별화된 설명이 가능하므로 대형 막대 도표 그리는 일 이상의 것을 할 수 있다. 데이터셋의 각 고객마다 변수 중요도를 그려볼 수 있다. shap 파이썬 패키지는 이 일을 쉽게 만든다. 먼저 shap.TreeExplainer(model).shap_values(X)를 호출하여 모든 예측값을 설명하고 shap.summary_plot(shap_values, X)를 호출하여 해당 설명 내용을 그려본다.

그림7

모든 고객은 각 행마다 점 하나로 표현된다. 점의 x축 위치는 모형의 고객 예측에 해당 변수가 미치는 영향력이며 점의 색은 고객의 해당 변숫값을 나타낸다. 밀도가 드러나게끔 점들이 행 위로 삐뚤빼뚤 쌓여있다.(이 예에 고객 32,561명이 있음) XGBoost 모형은 로지스틱 손실을 사용하므로 x축은 로그 오즈 단위를 갖는다.(트리 SHAP는 모형 마진 출력 값의 변화분을 설명한다).

변수를 평균 (|트리 SHAP|)로 정렬해보면 연간 5만 달러 이상의 수입으로 이끄는 가장 강력한 예측 변수가 관계 변수임을 다시 한번 알 수 있다. 전체 샘플에 대해 변수의 영향력을 그려봄으로써 중대한 이상치 효과가 있는지 살펴볼 수 있다. 예를 들어, 자본 이익은 전체적으로 가장 중요한 변수는 아니지만, 일부 고객에게는 가장 중요하다. 변숫값에 따른 채색을 통해 나이가 어릴수록 5만 달러 이상을 버는 기회가 줄어드는 한편 고등 교육이 5만 달러 넘게 벌 기회를 증대시켜준다는 식의 패턴을 알 수 있다.

여기서 멈추고 이 그림들을 상사에게 보여줄 수 있지만 대신 이 변수 중 일부를 조금 더 깊게 파보자. 연령 변수를 파보기 위해 연령 변숫값에 대한 연령 SHAP 값(로그 오즈의 변화분)을 도표화했다.

그림8

y축은 연령 변수가 연간 5만 달러 이상 수입에 대한 로그 오즈를 얼마나 바꾸는지에 대한 것이다. x축은 고객 연령이다. 각 점은 데이터셋의 개별 고객을 나타낸다.

여기서 XGBoost 모형이 잡아낸, 잠재적 소득에 대한 연령의 명확한 영향력을 볼 수 있다. 변수 값이 변함에 따라 모형 출력 값 평균의 추이를 표시하는 기존 부분 종속성 도표와 달리 이러한 SHAP의 종속성 도표는 상호 작용 효과를 드러낸다. 데이터셋의 많은 사람들이 20대지만 20대 점들의 수직적 산포에서 알 수 있듯이 그들의 연령이 그들 예측값에 영향을 미치는 정도는 서로 매우 다르다. 이건 다른 변수가 연령 중요도에 영향을 미치고 있음을 의미한다. 어떤 변수가 영향의 일부인지 살펴보기 위해 각 점을 교육 연수로 채색해보자. 교육 수준이 높을수록 20대 연령의 영향력은 줄지만 30대의 경우 증대함을 알 수 있다.

그림9

y축은 연령 변수가 연간 5만 달러 이상 수입에 대한 로그 오즈를 얼마나 바꾸는지에 대한 것이다. x축은 고객 연령이다. Education-Num은 고객이 이수한 교육 연수이다.

주당 근무 시간에 대해 또 다른 종속성 도표를 그려보자. 주당 50시간을 넘어가면 추가 근무의 이점이 크게 없어지며 결혼 생활을 할 경우 추가 근무가 높은 수입으로 이어지지 못하는 걸 볼 수 있다.

그림10

주당 근무 시간 대비 소득 잠재력에 대한 근무 시간의 영향력.

자신의 모형 해석하기

이 간단한 워크 스루는 자신의 모형을 설계하고 배포할 때 경험할만한 진행 절차를 보여주기 위한 것이었다. shap 패키지는 pip를 통해 쉽게 설치할 수 있으며 모형을 신뢰도 있게 탐색하는데 도움이 될 것이다. 패키지는 SHAP 상호 작용 값, 모형 불가지론적 SHAP 값 추정과 추가 시각화 등 이 글에서 다뤘던 내용 이외의 것까지 포함하고 있다. 다양하고 흥미로운 데이터셋 상에서 이런 모든 기능을 보여주는 노트북을 사용해볼 수 있다. 예를 들어, XGBoost 사망률 모형을 설명하는 노트북의 건강 검진을 기반으로 사망 주요 원인을 확인할 수 있다. 파이썬 이외 언어의 경우, 트리 SHAP가 XGBoost와 LightGBM 핵심 패키지에 직접 병합되었다.