Classification Metrics

Classification Metrics

분류 모델의 평가지표에 대해서 알아보자

Classification 모델을 만든 후에 모델의 성능이 어떤지 알기 위해서는 성능 평가 지표가 필요하다.
분류 모델의 성능지표를 알아보면서, 데이터의 상태에 따라서 어떤 지표를 사용해야하는지 공부해보자.

0과 1로 결정값이 한정되는 이진 분류 성능 평가 지표에 대해서 집중적으로 다뤄보자.

분류 성능 평가 지표

  • 정확도(Accuracy)
  • 오차행렬(Confusion Matrix)
  • 정밀도(Precision)
  • 재현율(Recall)
  • F1스코어
  • ROC AUC

정확도(Accuracy)

정확도는 실제 데이터에서 예측 데이터가 얼마나 같은지를 판단하는 지표이다.
$$Accuracy = {TP+TN\over TP+TN+FP+FN}$$
정확도는 직관적으로 모델 예측 성능을 나타내는 평가 지표이며, 기본적으로 많이 사용하는 지표중 하나이다.
하지만 정확도는 치명적인 약점이 존재하는데, 바로 불균형한 데이터 셋에서는 제대로 평가가 안된다는 것이다. 예를 들어보자 1000개의 샘플에 10개만 문제가 있는 샘플이다. 이럴 경우에 엉터리 분류기, 즉 모든 샘플에 대해서 정상이라고 분류하는 분류기를 이용해서 분류하고 정확도로 성능 평가를 한다면, 결과는 990/1000, 99%의 정확도를 보이게 된다.
엉터리 분류기가 과연 좋은 분류기일지 생각해보자. 만약 이 분류기에 문제가 있는 샘플을 더 추가한다면, 정확도는 기하급수적으로 떨어지게 될 것이다.

오차행렬(Confusion Matrix)

오차행렬은 학습된 분류 모델이 예측을 수행하면서 얼마나 헷갈리고 있는지도 함께 보여주는 지표이다. 즉, 이진 분류의 예측 오류가 얼마인지와 어떤 유형의 예측 오류가 발생하고 있는지를 같이 나타내 주는 지표이다.

오차행렬은 다음과 같이 표현한다.

Negative(0) Positive(1)
Negative(0) TN(True Negative) FP(False Positive)
Positive(1) FN(False Negative) TP(True Positive)

위의 표에서 진하게 표시된 것이 예측 클래스에 대한 것이고(Predicted Calss) 옅게 표시된 것이 실제 클래스(Actual Class)이다.

  • TP는 예측값을 Positive값 1으로 예측했고, 실제 값 역시 Positive값 1
  • TN는 예측값을 Negative 0으로 예측했고, 실제 값 역시 Negative값 0
  • FP는 예측값을 Positive값 1으로 예측했고, 실제 값은 Negative 값 0
  • FN는 예측값을 Negative값 0으로 예측했고, 실제 값 역시 Positive값 1

오차행렬을 기반으로 해서 정확도의 식을 다시 보면 결국, True에 해당하는 값인 TP와 TN에 값이 좌우되고 있다는 것을 알 수 있다. 정확도 = 예측 결과와 실제 값이 동일한 건수 / 전체 데이터 수 라고 다시 말할 수 있다.

불균형한 이진 분류 데이터 셋에서는 Positive 건수가 매우 작기 때문에 이러한 데이터로 학습된 ML 알고리즘은 Positive보다는 Negative로 예측 정확도가 높아지는 경향이 발생한다. TN값이 높아진다는 것이다. 결과적으로 불균형 데이터 셋에서는 Positive에 대한 예측 정확도를 판단하지 못하고 Negative에 대한 예측 정확도만으로 분류의 정확도가 매우 높게 나타나는 수치적인 판단 오류를 일으키게 된다.

이런 판단 오류를 극복하기 위해서 정밀도(Precision)와 재현율(Recall)이 성능지표로 사용된다.

정밀도와 재현율 (Precision and Recall)

정밀도와 재현율은 다음과 같은 공식으로 정의된다.
$$Precision = {TP \over FP+TP}$$
$$Recall = {TP \over FN+TP}$$
정밀도는 예측을 Positive로 한 대상 중에 예측과 실제 값이 Positive로 일치한 데이터의 비율을 뜻한다. 정밀도의공식에서 분모는 예측을 Positive로 한 모든 데이터 건수이다. Positive 예측 성능을 더욱 정밀하게 측정하기 위한 평가 지표로 양성 예측도라고 불린다.

재현율은 실제 값이 Positive인 대상 중에 예측과 실제 값이 Positive로 일치한 데이터의 비율을 뜻한다. 공식의 분모는 실제 값이 Positive인 모든 데이터 건수이다. 민감도 또는 TPR(True Positive Rate)라고도 불린다.

정밀도와 재현율은 중요하게 생각하는 부분이 서로 다르기 때문에, 주어진 업무 특성에 따라서 특정 평가 지표가 더 중요한 지표로 간주될 수 있다. 재현율이 중요한 경우를 생각해보자. 재현율이 중요 지표로 사용되는 경우는 실제 Positive 양성 데이터를 Negative로 잘못 판단하게 되면 크리티컬한 영향이 발생하는 경우이다. 예를 들어 암 판단 모델은 재현율이 중요한데, 실제 Positive인 경우, 즉, 암환자를 Negative, 정상으로 분류하는 경우 오류의 대가가 생명이 될 수 있을 정도로 치명적이다. 만약 정상환자를 암환자로 분류하는 경우에는, 재검진을 하는 정도의 비용이 소모된다.(Positive–>Negative로 잘못분류)

정밀도가 중요한 경우를 생각해보자. 스팸메일 여부를 확인하는 예를 들어보면, 실제 Positive인 스팸 메일을 Negative 정상 메일이라고 분류하게 되면 사용자가 불편함을 느끼는 정도지만, 정상메일을 Spam으로 분류해 버리면 업무메일 등이 스팸으로 처리되어 메일을 받지 못하게 돼 업무에 차질이 생길 수 있다.(Negative–>Positive로 잘못분류)

정리하자면,

  • 재현율이 더 중요한 경우, 실제 Positive 양성 데이터 예측을 Negative로 잘못 판단하게 되면 업무 상 큰 차질이 발생하는 경우
  • 정밀도가 더 중요한 경우, 실제 Negative 음성 데이터 예측을 Positive로 잘못 판단하게 되면 업무 상 큰 차질이 발생하는 경우

공식을 다시살펴보면, Precision은 FN이 분모에 사용되고, Recall은 FP가 분모에 사용된다. 재현율은 FN을 낮추는 데, 정밀도는 FP를 낮추는 데 초점이 맞춰진다. 가장 좋은 것은 둘다 높은 것인데, 두 성능 지표가 상호 보완적이기 때문에 Trade off가 존재한다.

정밀도/재현율 트레이드 오프

정밀도나 재현율은 분류의 결정 임계값을 조정해 정밀도나 재현율의 수치를 높일 수 있다. sklearn의 분류 모델들에서 threshold를 조절할 수 있는 파라미터를 찾아보면 된다. threshold값을 낮추면 보통 재현율 값이 올라가고 정밀도 값이 떨어진다. threshold값은 Positive 예측값을 결정하는 확률의 기준이 되고 낮출 수록 True값이 많아지기 때문이다.

Positive 예측값이 많아지면 상대적으로 Recall 값이 높아진다. 양성 예측을 많이 하다보니 실제 양성을 음성으로 예측하는 횟수가 상대적으로 줄어들기 때문이다(FN값이 떨어진다).

  • 임계값 증가하면 Negative 예측 값이 증가한다(FP값이 떨어짐) ==> Precision 증가
  • 임계값 감소하면 Positive 예측 값이 증가한다(FN값이 떨어짐) ==> Recall 증가

정밀도와 재현율의 맹점

Positive 예측의 임계값을 변경함에 따라 Precision과 Recall의 수치가 변경되는 것을 확인해 봤다. Threshold의 이런 변경은 업무 환경과 목적에 맞게 두 수치를 상호 보완할 수 있는 수준에서 적용되어야 한다. 단순히 성능지표로서 숫자를 올리는 수단으로 사용되면 안된다.

정밀도 100% 만들기

확실한 기준이 되는 것만 Positive로 예측하고 나머지는 모두 Negative로 예측한다. 정밀도 = TP / (TP+FP) 이다. 예를 들어 암환자를 예측한다고 해보자. 전체환자 1000명 중에 확실한 Positive 징후만 가진 환자가 단 1명이라면(죽기 일보직전의) 한명만 Positive로 예측하고 나머지는 모두 Negative로 예측하더라도 FP는 0, TP는 1이기 때문에, 정밀도는 1/(1+0)으로 100%가 된다. Precision은 100%지만, 초기 암진단을 예측하는 경우는 희박하고, 위험한 정도의 암환자도 정상이라고 분류할 수 있기 때문에 좋은 분류기라고 할 수 없을 것이다.

재현율 100% 만들기

모든 환자를 Positive로 예측하면 된다. 재현율 = TP / (TP+FN)이므로 전체 환자 1000명을 다 Positive로 예측하는 것이다. 이 중 실제 양성인 사람이 30명 정도라도 TN이 수치에 포함되지 않고 FN은 아예 0이므로 30/(30+0)으로 100%가 된다. 이렇게 되면 재현율은 100%지만 모델을 정말 신뢰할 수 있는지에 대해 의심이 발생할 것이다. 이런 모델은 정상인 사람도 암 환자로 예측하게 되므로, 재검사 비율을 매우 높이게 된다. 병원에서 재검사 비용을 대줘야 한다면, 혹은 환자로 분류된 사람이 재검사 비용을 내야 한다면, 병원이 손해를 막심하게 보거나, 고객들이 병원에 대해 신뢰를 하지 않을 것이다.

따라서 정밀도와 재현율을 적절하게 고려한 평가 지표가 필요하게 된다.

F1 Score

F1-Score는 정밀도와 재현율을 조화 평균한 지표이다. F1-Score는 정밀도와 재현율이 어느 한 쪽으로 치우치지 않는 수치를 나타낼 때 상대적으로 높은 값을 가진다. 공식은 다음과 같다.
$$F1={2\over{1\over{recall}}+{1\over{precision}}}=2\times{precision*\space recall\over precision+recall}$$

만일 A 예측 모델의 경우 Precision이 0.9, Recall이 0.1로 극단적인 차이가 나고, B 예측 모델은 Precision과 Recall이 0.5로 큰 차이가 없다면 A의 F1-Score는 0.18이고, B의 F1-Score는 0.5로 B의 모델이 좋은 점수를 얻게 된다. 사실 F1 Score는 Precision과 Recall에 동일한 가중치인 0.5를 적용한 값이다. F-Measure는 $\beta$를 이용해 가중치를 조절한다. 공식을 살펴보자.

$F_\beta=$$(1+\beta^2)(Precision * Recall)\over{\beta^2 Precision + Recall}$

$\beta$가 1보다 크면 Recall이 강조되고 1보다 작으면 Precision이 강조된다. 1일때의 점수를 $F_1$점수라고 한다.

ROC & AUC

ROC곡선(Receiver Operation Characteristic Curve)은 수신자 판단 곡선으로, 2차대전 때 통신 장비 성능 평가를 위해 고안된 수치이다. 요즘에는 이진 분류의 성능 평가 지표로 자주 사용된다. ROC Curve는 FPR(False Positive Rate)이 변할 때 TPR(True Positive Rate)이 어떻게 변하는지를 나타내는 곡선이다. FPR을 x축으로, TPR을 y축으로 잡으면 FPR에 대한 TPR의 변화가 곡선 형태로 나타난다.

TPR은 True Positive Rate의 약자이며, Recall을 나타낸다. 따라서 TPR은 TP/(TP+FN) 이다. 민감도라고도 불리며 민감도에 대응하는 지표로 TNR(True Negative Rate)이라고 불리는 특이성이 있다.

  • 민감도(TPR)는 실제값 Positive가 정확히 예측되어야 하는 수준을 나타낸다.(질병이 있는 사람은 질병이 있는 것으로 양성 판정)
  • 특이성은(TNR) 실제값 Negative가 정확이 예측되어야 하는 수준을 나타낸다.(정상인 사람은 정상으로 음성 판정)

TNR은 TN/(TN+FP)이며 X축의 기준인 FPR은 FP/(FP+TN)이므로 1-TNR로 표현할 수 있다.

ROC 곡선은 FPR을 0부터 1까지 변경하며 TPR의 변화 값을 구한다. Threshold값을 변경하면서, 처음에는 1로 지정해 FPR을 0으로 만든다. Threshold가 1일 때 Positive 예측 기준이 매우 높기 때문에 분류기가 Threshold보다 높은 확률을 가진 데이터를 Positive로 예측할 수 없다. 즉, 아예 Positive로 예측을 하지 않기 때문에 FP가 0이 되어 FPR이 0이된다. FPR = FP/(FP+TN)

반대로, FPR을 1로 만들려면 TN을 0으로 만들면 된다. Threshold를 0으로 지정하게 되면, 분류기가 모든 데이터에 대해서 Positive로 예측을 하게 된다. 이렇게 되면 Negative 예측은 없기 때문에 FPR이 1이 된다.

일반적으로 ROC Curve자체는 FPR과 TPR의 변화 값을 보는 데 이용하고, 분류의 성능 지표로 실제로 사용되는 것은 AUC(Area Under Curve)이다. 이 값은 ROC 곡선 밑의 면적을 구한 것으로, 일반적으로 1에 가까울수록 좋은 수치이다. AUC가 커지려면, FPR이 작은 상태에서 얼마나 큰 TPR을 구할 수 있는 지가 중요하다. 가운데 직선에서 멀어지고 좌상단 모서리로 곡선이 바짝 붙을 수록 직사각형에 가까운 곡선이 되어 면적이 1에 가까워진다. 가운데의 직선은 랜덤 수준의 이진 분류 AUC값으로 0.5이다.

PCA

Dimensional Reduction에 쓰이는 PCA에 대해 알아보자

PCA(Principal Component Analysis)

데이터 분석을 하다보면 답답한 경우가 자주 발생한다. 모델을 돌려야 하는데 feature가 너무 많아서 연산 코스트가 너무 많이 들고, 계산하는데 너무 오랜 시간이 걸리는 것이다. 결과를 봤더니, 복잡한 feature때문에 지저분하게 나오고, 노이즈도 많이 껴있는 것 같다. PCA는 이런 경우에 자주 사용되는 알고리즘이다. PCA는 그러니까 relative하지만 redundant한 feature를 제거하는데 자주 사용되거나 데이터를 단순화 할때 사용된다.

데이터를 단순화하는데는 다음의 두 가지 방법이 있다.

  • 차원 축소(Dimensional Reduction) : 데이터를 표현하는 속성의 수를 축소
  • 요소 분석(Factor Analysis) : 관찰 가능한 데이터 = 잠재적인 변수(latent variable)와 noise의 선형결합

우리는 차원 축소에 대한 내용을 살펴볼 것이다.

아까의 상황을 다시 가져와보자. 이전의 예에서 복잡한 feature들은 사실 highly correlated 되어 있기 때문에 문제가 있는 것이다. 변수들의 서로 연관되어 있으면 설명량은 올라가지만, 좋은 모델이라고 볼 수 없고, 어떤 변수가 타겟에 어떻게 영향을 주는지 알 수 없다. 불필요한(서로 연관되어 있거나, 결과와 상관없는) 변수들은, 변수들을 모으고 분석하는데 드는 비용을 증가시켜서, 예측 모델 또는 분류 모델을 만들 때 전체 비용을 증가시키는 원인이 된다.

따라서 불필요한 변수들을 제거할 필요가 있고, Machine Learning 영역에서는 본래 모델이 가지고 있던 성질이나 정확도를 최대한 유지하면서 차원을 줄이는 방법을 통하여 위에서 설명된 문제점을 해결하려고 한다.

모델의 차원(dimensionality)은 모델에 사용되는 독립(independence) 변수 또는 입력(input) 변수의 개수(number)를 의미한다. 우리가 GLM(Generalized Linear Model)을 사용하는 이유처럼 독립변수가 타겟에 미치는 영향을 제대로 알기 위해서 독립적인 변수가 필요한 것이다. 통계에서 항상 IID 조건을 사용하는 것과 의미가 비슷할 것이다.

정리하자면 PCA를 사용하는 이유는 다음과 같다.

  • feature가 너무 많으면 연산에 사용되는 cost가 너무 높고, 시간도 너무 오래 걸리기 때문에, 변수들을 줄여줄 필요가 있다.
  • 많은 feature들 중에서는 상관관계가 높은 feature들이 있다(high correlated). 이런 feature들은 모델의 설명량은 높일 수 있지만, 모델의 성능은 떨어트릴 수 있다. 또한 우리가 흥미 있어 하는 결과와 상관없는 변수들이 존재할 수 있는 상황이 발생할 수 있다.

Dimensional Reduction

Dimensional Reduction의 핵심 아이디어는, 상관도가 높은(interrelated, correlated) 변수들이 많이 존재하는 데이터 집합의 차원(Dimensionality)을 줄이면서, 동시에 데이터 집합에 존재하고 있는 차이(Variation, 정보)를 최대한 유지하는 것이다. 즉, 차원을 줄이되 “정보 손실을 최소화”하는 것이다. 여기서 정보란 데이터간의 거리, 실제적인 위치를 정보라고 표현한다. 다시말하면 위치, 상대적인 거리를 뜻한다. 하지만 차원축소는 정보의 손실을 어느 정도 감수해야 한다.

Dimensional Reduction은 원래 공간에서 데이터가 퍼져 있는 정도를 변환된(축소된) 공간에서 얼마나 잘 유지하느냐를 척도로 삼는다. 원래 공간의 정보가 변환된 공간에서 얼마나 잘 유지하는지는 변환된 공간에서의 데이터의 분산으로 측정한다. 따라서, 변환된 공간에서 데이터의 분산을 최대로 유지 할 수 있는 좌표축을 찾아야 한다.

즉, PCA는 원래 공간에서 데이터가 분산되어 있는 주요한 방향(Principal direction)을 찾는 것이 목표가 된다.
여러축으로 구성되어 있는 데이터를 주성분 분석으로 통해 기존의 feature들과는 다른 새로운 축으로써 다시 구성해보되, 분산을 최대로 유지한다.

PCA 수행방법

PCA에서 데이터가 분산되어 있는 주요한 방향(Principal Component)을 찾는 단계는 다음과 같다.

  1. 데이터를 투영(Projection)하기
  2. 투영된 공간에서 분산 측정하기
  3. 분산의 최대치는 어떻게 찾는가?

데이터를 여러 축에 투영해보면서 투영된 공간에서 분산을 측정하고, 가장 분산이 큰 축을 선택하는 것이 바로 PCA이다.
새로운 축이 $u$이라고 했을때, 축으로 이동된 새 데이터 포인트 $X_{new} = u^TX$이다. (𝕦t 𝕩= 𝕦 ⋅ 𝕩 cos𝜃= 𝕩 cos𝜃)

이제 투영된 공간에서 분산을 측정해보자. 먼저, PCA를 실행하기 전에 데이터의 평균(mean)과 분산(variance)를 정규화(standardization) 해 준다.(Pre-process the data) 데이터는 특성 벡터로 표현되는데, 특성 벡터의 각 원소들에서 각각의 평균과 빼 주고, 분산의 제곱근으로 나누어 준다.

정규화 과정에서

  • 데이터에서 평균을 빼는것:데이터의 평균이 0이 되도록 만든다.
  • 데이터에서 분산의 제곱근을 나누어 주는 것 : 데이터의 값들이 unit variance를 갖게 해 준다.

새 축으로 이동된 데이터의 분산 구하기

각각의 attribute의 평균이 0이 되고, 분산이 1이 된다. 즉 같은 “scale”을 가지게 되어, attribute간의 비교가 가능 해진다.
데이터 포인트 $x_{1}, x_{2}, x_{3}, x_{4}, x_{5}$가 있을 때, u의 축으로 투영된 데이터 포인트$x_{1}^Tu, x_{2}^Tu, x_{3}^Tu, x_{4}^Tu, x_{5}^Tu$의 분산을 구해보자.

먼저 평균값을 구해놓자.

$$\mu={1\over{m}}\sum_{i=1}^{m}x_i^Tu = 0$$
투영된 공간에서의 기댓값은 0이다. 왜냐하면 데이터 포인트들은 이미 standardizing을 한 상태이기 때문이다. 평균의 평균을 구하니까 0이 되는 것이다.

분산을 구해보자.

$$\sigma^2={1\over{m}}\sum_{i=1}^{m}(x_i^Tu - \mu)^2 ={1\over{m}}\sum_{i=1}^{m}(x_i^Tu)^2$$
($\mu$가 0이므로)

$$={1\over{m}}\sum_{i=1}^{m}(u^Tx_ix_i^Tu) = u^T({1\over{m}}\sum_{i=1}^{m}(x_ix_i^T))u$$

($u$는 unit vector이다.)

이것은 결론적으로
$$=u^T({1\over{m}}\sum_{i=1}^{m}(x_i-\mathbb{o})(x_i-\mathbb{o})^T)u$$

$$=u^T\sum u$$
식이 도출된다.

Σ는 공분산 행렬로 기존 데이터의 공분산 행렬을 사용한다.
결국 투영하려고 하는 축과 기존 데이터의 공분산 행렬의 곱으로 간단하게 새 축의 분산을 구할 수 있다.

분산의 최대치 구하기

우리는 Principal Component, 즉, 주성분을 구하는 것이 목적이므로, 데이터의 분산이 최대가 되도록 만드는 축을 구해야 한다. 분산의 최대치를 구하기 위해서 변환된(투영된) 공간에서 분산을 최대화 해 줄 수 있는 벡터 $u$를 찾아야 한다. $u$는 unit vector라고 생각하자. 우리가 구하고자 하는 $u$는 방향이 중요하기 때문이다. 즉, $u^Tu = 1$이다.

따라서 문제는 $u$가 unit vector일 때의 $u^T\sum u$의 최대값을 구하는 조건부 최적화 문제가 된다.

$$\max u^T\sum u$$

$$s.t \space u^Tu=1$$

이 문제는 라그랑지 승수 (Laglange Multiplier)를 이용해 해결 할 수 있다.
$$\mathcal{L}(u,\lambda)= u^T\sum u - \lambda(u^Tu-1)$$

$\mathcal{L}(u,\lambda)$를 미분해서 $u$의 최대치를 구한다.

이렇게 구한 식을 나타내면
$$u^T\sum u = u^T\lambda u=\lambda u^T u=\lambda$$

즉, 분산을 최대화 하는 문제는 Σ의 eigenvalue를 최대화 하는 문제가 된다.
$$argmax_{u}u^T\sum u = argmax_{u}\lambda$$

따라서, 변환된(축소된) 공간에서 분산의 최대값은 Σ의 eigenvalue의 최대값이다.

분산의 최대값은, 𝕦가 Σ의 eigenvalue 중 가장 큰 값을 가지는 eigenvalue에 대응되는 eigenvector일 때 달성된다. 우리는 이것을 주성분이라고도 부른다.

이 다음의 주성분을 구하는 것은 간단하다. D차원에서 주성분은 데이터 공분산 행렬의 가장 큰 eigenvalue에서 부터 D번째로 큰 eigenvalue까지에 대응되는 D개의 eigenvector가 될 것이다.

Boosting

부스팅 기법(Boosting)에 대해 알아보자

Weak Learner

부스팅 기법에 대해 알아보기 전에 알아야 할 몇가지 용어들이 있다. 그 중 하나가 Weak Learner이다.
Weak Learner는 다른 말로 Simple Learner이라고도 불리우며, 간단한 학습기 정도로 보면 될 것이다.

대표적인 Weak Learner는 다음과 같다.

  • Decision stumps : depth가 1인 decision tree
  • Shallow decision trees
  • Naïve Bayes
  • Logistic regression

우리는 Weak Learner를 많이 가질 것이고, 많은 학습기들을 이용해서 예측작업을 할 것이다.
Weak Learner들의 앙상블을 통해 어떤 결과를 예측해보려는 것이다. 이렇게 다수의 Weak Learner들을 이용해서 학습하면, input space의 다른 부분들을 보완해줄 수 있다.

부스팅에 대해서 공부할 때 배깅이 자주 등장하는데 차이를 비교해보자면 다음과 같다.

Bagging

  • 훈련 데이터에서 다수의 표본을 추출하고, 개별 트리의 결과를 병합하여 단일 예측 모델을 생성
  • 각 bootstrap 과정이 독립적이므로 병렬 처리가 가능

Boosting

  • Bagging과는 달리 순차적으로 시행되며 bootstrap 과정이 없음
  • Original dataset에서 약간의 수정을 거친 데이터를 개별적으로 학습한 후, 결합되어 강력한 분류기 생성

부스팅의 아이디어는 간단하다. 약한 학습기들을 이용해서 학습된 학습기들을 결합해 strong learner를 만드는 것이다. Classifier의 경우 학습기들의 결합방법은 Majority voting방식이 될 것이고, Regressor의 경우 학습기들의 결합방법은 평균이 될 것이다.

부스팅의 알고리즘도 심플하다. 앙상블 내, $t$번째 분류기 $c_t$와 $t+1$번째 분류기 $c_{t+1}$이 연관성을 가지고 생성하는 것이다.

  1. 훈련데이터 X의 샘플을 $c_t$가 옳게 분류하는 것과, 그렇지 않은 것으로 나눈다.
  2. 옳게 분류하는 샘플들은 인식이 가능하므로 가중치를 낮춘다.
  3. 틀리게 분류하는 샘플들은 가중치를 높인다.
  4. $c_{t+1}$학습시키기 위한 정책으로 sampling과정에서 가중치가 높은 샘플이 뽑힐 확률이 높아지게 한다.

Ada Boost(Adaptive Boosting)

Yoav Freund & Robert Schapire가 제안하였고, Weak learner를 반복적으로 사용하고, 그 결과를 합하여 모델의 accuracy를 향상시킨다.

AdaBoosting은 위에서 살펴본 알고리즘이 작동하는 방식과 거의 비슷하게 동작한다.

그림과 함께 살펴보자
Ada Boosting의 작동원리
첫번째 그림에서 약한 학습기인, 결정 그루터기가 하나의 결정경계를 가지고 +와 -를 나누고 있다. 이렇게 나눴을 때 위쪽의 3개의 +들은 잘못 분류가 되어 가중치가 높아진다. 두번째 그림에서는 오른쪽의 - 두 개만 잘 분류가 되었고 결정경계 왼쪽의 대개의 -들은 잘못 분류가 되어버렸다. 이 역시 가중치가 높아지고 학습된 3개의 Weight를 결합해서 + -를 잘 분류해내는 하나의 강 분류기를 만들어낸다. 결국 Weak Learner들의 앙상블이다.

가중치 업데이트 규칙은 다음과 같다.
$w^{(i)} = w^{(i)}$, $\hat{y_j}{(i)}= y_{(i)}$ 일때
$w^{(i)} = w^{(i)}exp(\alpha_j)$, $\hat{y_j}{(i)}\neq y_{(i)}$ 일때
그런 다음 모든 샘플의 가중치를 정규화 한다.(즉, $\sum_{i}^{m}w^{(i)}$로 나눠준다.)

마지막으로 새 예측기가 업데이트된 가중치를 사용해 훈련되고 전체 과정이 반복된다. 새 예측기의 가중치가 계산되고 샘플의 가중치를 업데이트해서 또 다른 예측기를 훈련시키는 방식이다.

Adaboost는 지정된 예측기 수에 도달하거나 완벽한 예측기가 만들어지면 중지된다.

Adaboost의 예측은 $\hat{y}(x)=\sum_{i=1}^{N}\alpha_j$로 이루어진다.($N$은 예측기의 수)

Gradient Boosting

그래디언트 부스팅은 Ada부스팅처럼 이전까지의 오차를 보정하도록 예측기를 순차적으로 추가한다. 하지만 Ada처럼 반복마다 샘플의 가중치를 수정하는 대신 이전 예측기가 만든 잔여 오차(residual error)에 새로운 예측기를 학습시킨다. 다시말해서 약한 분류기가 이전 학습에서 발견하기 어려웠던 문제성 관측값, 즉, 예측이 틀린 관측값에 집중하게 하는 것이다.

다른 boosting 기법처럼 모델을 단계적으로 구축해 나가는 것은 같지만 임의의 미분 가능한 손실 함수를 최
적화하는 문제로 일반화한 방법이다. GB는 여러개의 간단한 모델의 ensemble을 학습한다.

Motivation of Gradient Boosting

($x_1$,$y_1$),($x_2$,$y_2$) …, ($x_n$,$y_n$) 총 n개의 데이터가 있고, 이 데이터를 이용하여 회귀모형 $F(x)$ 를 학습하는 프로젝트를 진행한다고 생각해보자. 팀원이 모델 $F$를 만들었다. 하지만 성능이 그다지 좋지 않다. $F(x_1)$ = 0.8의
예측값을 생성한다. 하지만 실제 $y_1$ = 0.9이다. $y_2$ = 1.3인데, $F(x_2)$ = 1.4의 값이 나온다. 이 모델의 성능을
향상시켜야 하는데 한가지 제약조건이 있다. 팀원이 만든 모델 $F$는 절대 건드리지 않고, 모델을 향상시켜야
한다. 어떤 방법이 있을까?

방법은 간단하다. 원래 모델은 그냥 두고, 차이만큼을 더해주는 함수 $h(x)$를 만들어주면 되는 것이다.
완벽하게 우리의 목적을 달성시키지는 못하지만, 근사적으로 달성할수는 있다.

그렇다면$h(x)$는 어떻게 구할 수 있을까?
$h(x_1) = y_1 - F(x_1)$
$h(x_2) = y_2 - F(x_2)$
$…$
$h(x_n) = y_n - F(x_n)$ 이므로,$(x1, y_1-F(x_1))$, $(x2, y_2-F(x_2))$,$…,$,$(x_n, y_n-F(x_n))$을 학습하면 된다.

학습데이터를 이용하여 75%정도의 정확도까지 모델을 학습하고, 나머지 미설명 부분은 오차항에 남겨둔다.
$Y = F(x) + E$
오차항을 이용하여 다른 모델을 학습시킨 후, 그 전 모델에서는 미설명 부분이었으나 이번 학습에서는 설명
이 되는 부분을 찾아내 원 모델에 추가한다. 단, 추가 모델은 반드시 전체 정확도를 향상시켜야만 한다.
$Gradeint(E) = G(x) + E2$

모델이 약 80%의 정확도를 갖게 되면 식은 다음과 같게 된다.
$Y + F(x) + G(x) + E2$

이런 방법을 계속해서 사용해 나가고, GB는 단순 합보다 가중 평균을 사용하여(다른 모델보다 정확도가 높은 예측 결과를 가진 모델에 더 높은 중요도 점수를 부여) 모델의 정확도를 더 개선할 수 있다
$Y=\alpha{F(x)}+\beta{G(x)}+\gamma{H(x)} + E$ $…$

Gradient Boosting의 Loss Function

손실 함수는 해결하려는 문제에 따라 다르다. 부스팅에서는 처음부터 최적화를 하는 것이 아니라, 각 단계별로 이전 단계에서 설명되지 못한 손실에 관해 최적화를 수행한다.

  • 회귀 문제 : Least squares method (최소 자승법)
  • 분류 문제 : Log loss function (로그 손실 함수)

손실 함수를 최소화하기 위해 약한 분류기를 추가할 가법 모델(additive model)

  • 기존 트리는 변동이 없고 새로운 트리가 하나씩 추가된다.
  • 기울기 하강 절차가 사용되어 트리가 추가될 때의 손실을 최소화한다.

Leaf node마다 가중치, score가 부여가 된다. Gini계수 등을 사용하지 않는다.
분류 / 회귀 : Sklearn에서는 (friedman) mse를 사용한다.

Ensemble_Model

Ensemble에 대해 자세히 알아보자 (Bagging, Bootstrap, 그리고 RandomForest)

앙상블 모델에 대해서 공부하기 전에, 그 배경부터 알아볼 필요가 있다.

NFL (No Free Lunch)

No Free Lunch 이론은 David H. Wolpert가 정리한 이론으로 모든 문제에 대해 다른 모든 알고리즘을 능가하는 모델은 없다는 이론이다. ‘어떤 특정 정책에 의해 얼핏 보면 이득을 얻는 것 같지만, 그것은 한 측면의 이득일 뿐이고 반드시 이면에 다른 측면이 있고 그 측면에서 손해가 발생한다.’는 것이 핵심이다.

이 이론에 따라서 혼성모델의 필요성이 대두되었다. 혼성모델이란 여러 알고리즘을 결합하는 모델이다. 이 모델은 특정 문제가 주어진 상황에서 그 문제를 가장 높은 성능으로 풀 수 있는 알고리즘에 대한 필요성에 의해서 제시되었다.

Resampling

리샘플링은 데이터가 부족할 때 같은 샘플을 여러번 사용하는 것을 말한다. 성능 통계치의 신뢰도를 높이기 위해 사용된다. Resample을 하는 이유는 다음과 같다.

  • 실제 상황에서는 만족할 만한 큰 샘플을 얻기가 힘들다.
  • Bias-Variance Trade off를 통해 큰 샘플이 중요하다는 것을 알 수 있다.
    • sample의 집합이 커지면 variance가 감소한다!, MSE도 감소한다!
  • 모델의 선택은 별도의 검증이 필요하다.(검증용 데이터, 큰 샘플의 필요성)

Bootstrap, Statistical term for “roll n-face dice n times”

부트스트랩은 Resampling을 이용하여, 분류기의 성능을 측정하는 방법 중 하나이다. 통계에서는 추정치에 대한 검증용(가설 검증)으로 많이 사용된다. 부트스트랩의 장점은 한번도 뽑히지 않은 데이터가 발생한다는 것이다. 이를 통해 데이터를 아낄 수 있게 된다.

Ensemble

앙상블 모델은 혼성모델 중 하나이다. 앙상블은 두가지 방식이 존재한다.

  • 같은 문제에 대해 서로 다른 여러 알고리즘이 해를 구하고, 결합 알고리즘이 그들을 결합하여 최종 해를 만드는 방식
  • 문제와 유사한 여러 하위 문제들에 대해 하나의 알고리즘이 해를 구하고, 결합 알고리즘이 그들을 결합하여 최종 해를 만드는 방식

앙상블의 동기는 단순히 통계적, 수학적일 뿐만 아니라, 사람들의 심리 등 여러부분을 관통하는 내용이기도 하다.

1
2
어느 도시에서는 소를 광장에 매어 놓고 참가자들에게 체중을 추정하여 적어 내게 하고 실제 체중에 가장 가까운 사람에게
상품을 주는 대회가 있다고 한다. 수백 명이 참가하는데 그들이 적어낸 숫자들을 평균해 보면 답과 아주 근사하다고 한다.

사람들은 중요한 결정을 할때 여러 사람의 의견을 들어보고 결정하려는 경향이 있고, 이런 경향은, 통계학이 아닌 다른 분야에서도 사용되는 개념이다.

다양성

앙상블 모델의 핵심은 다양성이다. 앙상블에 참여한 모델이 모두 같은 결과를 낸다면, 그것은 앙상블 모델로써 어떠한 장점도 갖고 있지 않다. 한 분류기가 틀리는 어떤 문제를, 다른 분류기에서는 맞출 수 있어야 앙상블 모델로써 가치가 있을 것이다.

앙상블 분류기 시스템은 앙상블 생성, 앙상블 선택, 앙상블 결합의 단계를 거친다.

앙상블 생성

  • Resample을 이용해서 (Bagging, Bootstrap) 샘플 집합들을 생성하고, 분류기를 훈련한다.
  • Feature Vector의 subspace를 이용해서 샘플 부분 집합을 생성하고 분류기를 훈련한다.
  • 앙상블의 분류기는 요소분류기와 기초분류기로 구분된다.

앙상블 결합

요소 분류기(기초 학습기)들의 출력을 결합하여 하나의 분류 결과를 만드는 과정이다.
요소 분류기의 출력은 세가지의 방식으로 나뉜다.

  • Class Label
    • Majority Vote : class 라벨이 많이 나온 쪽으로 분류한다.
    • Weighted Majority Vote : 성능 좋은 분류기에 가중치를 부여한다.(Adaboost)
    • Behavior knowledge space(BKS/행위지식공간) : 경험한 케이스를 테이블로 갖고 분류기 결과를 보고 경험적으로 결정한다(테이블에서 찾아서). 다수결 방법의 성능을 고도화 할때 사용됨
  • Class Ranking
    • Borda 계수
  • Class Probability
    • Softmax

Bagging (Bootstrap + Aggregating)

부트스트랩을 다중 분류기 생성 기법으로 확장한 것이다. 부트스트랩 된 샘플 집합에서 훈련을 하고, 입력 값에 대해 분류기들의 평균값이나, 다수결 투표를 취한다. 샘플링은 복원추출하는 방식으로 하고, 훈련된 분류기의 결과를 모두 종합하기 때문에 Bagging이라고 부른다.

  • 반복적인 복원 추출 (Bootstrap)
  • 결과를 모두 종합 (Aggregation)

Bagging, 배깅은 언제 사용할까?

배깅은 편향이 작고 분산이 높은 모델에 사용하면 효과적이다.

  • 트리 분류기와 같이 불안정성을 보이는 분류기에 큰 효과를 발휘
  • 훈련 집합이 달라지면 차이가 큰 트리가 생성 ⇒ 다양성 확보
  • Bias를 변화시키지 않고 variance를 감소시킨다.(Bias를 쪼오오오오끔 희생한다.)

배깅은 분산을 감소시키기 위해, 훈련데이터에서 많은 샘플링을 하고(Bootstrap), 샘플들로 별도의 Decision Tree를 구성한 후, 회귀나 분류문제를 푸는데 사용된다. 회귀는 분류기 결과의 평균값을 사용하고, 분류는 최빈값을 취한다.

배깅은 이미 저분산 모델인 경우 별로 효과가 없다. Bias-Variance Tradeoff 를조금만 생각해보자. 분산이 이미 줄어있는 상태에서는 더 줄일 분산이 없다. 배깅은 오직 분산을 줄이는 데 효과적이다.

Out-of-Bag (OOB) Error Estimation

샘플에 대해 Bootstrap을 하게 되면 부트스트랩 샘플은 전체 훈련데이터의 약 63.2%를 차지하게 된다.(왜 그러한가에 답은 $\lim_{n\to\infty} (1-{1\over n})^n$을 풀면 답이 나온다. $1\over e$로 0.378이 나온다. 자세한 내용은 링크를 참조하면 된다. [https://www.quora.com/Why-is-the-limit-1-frac-1-n-n-equal-to-frac-1-e])

부트스트랩되지 않은 샘플들은 한번도 사용되지 않은 샘플들로 검증데이터에 활용할 수 있다. 이런 training observations은 out-of-bag observations이라고 불린다.

OOB estimate of test error

  • 부트스트랩 샘플을 이용하여 개별 학습기를 학습한 후, OOB에 속하는 샘플들에 대한 예측값을 모두 구한다.
  • OOB의 실제 라벨값과 OOB의 예측값을 이용하여 OOB error를 구한다.
  • 모든 부트스트랩 샘플 sets에 대하여 위의 과정을 반복하면, 샘플 sets 수 만큼의, errors를 모을 수 있다.
  • OOB errors의 평균값을 이용하여 bagging 모델의 최종 테스트 error를 계산한다.

Weakness of Bagging

배깅은 엄청나게 효과적인 것처럼 보이지만 약점이 존재한다. 배깅은 feature를 모두 사용하고, row를 랜덤하게 선택하는 것이다. Decision Tree를 만든다고 해보자, 만약 영향력이 높은, Information Gain이 높은 모델을 사용한다고 했을때, 특정 Feature만 계속 선택되서 트리가 만들어질 가능성이 있다. 즉, 중요한 칼럼들이 트리의 초기 분기때 모든 표본에 그대로 존재하게 된다. 이렇게 되면 만들어진 대다수의 트리들의 결과가 비슷해진다. 이것이 반복되면 트리간의 상관관계가 발생해서 분산 감소의 효과가 줄어들게 된다.
(배깅의 약점은 IID condition이다. IID 조건을 만족하는 경우 분산은 $Var={\sigma^2\over n}$이 되지만, IID를 만족하지 못하는 경우, 상관관계가 발생하여 $Corr = p$이라고 할때, $Var = p\sigma^2$가 된다.)

그래서 혁신적인 아이디어와 함께 등장하게 된 것이 Random Forest이다.

Random Forest

랜덤 포레스트는 일반적으로 bagging 방법(또는 pasting)을 적용한 결정 트리의 앙상블이다.
랜덤 포레스트 알고리즘은 트리의 노드를 분할할 때 전체 특성 중에서 최선의 특성을 찾는 대신 무작위로 선택한 특성 후보 중에서 최적의 특성을 찾는 식으로 무작위성을 더 주입한다. 트리를 더욱 다양하게 생성하고 (트리의 의존성을 낮추고, 다양성을 증가) 편향을 손해 보는 대신 분산을 낮추어 전체적으로 더 훌륭한 모델을 생성한다.

Random Forest는 쉽게 말해 Tree 모델에 Bagging과 Subsampling기법을 사용한 모델이다.
훈련 데이터에서 bootstrap 샘플을 뽑아내고, 노드 분기 시, 모든 Feature가 아니라, 일정 Feature만 사용하는 것이 특징이다. 이를 통해 Tree간의 Correlation을 줄이고, 분산을 감소시킬 수 있다.

Subspace Sampling

샘플링 시에는 일반적으로 전체 변수가 p라고 할 때, $m = \sqrt{p}$를 사용한다.
(m = p이면 Bagging이다. 또한 회귀에서는 경험적으로 $m ={p\over3}$를 사용한다.)

Random Forest 모델의 장단점?

장점 : 굉장히 간편하다. 스케일링도 필요없고 파라미터 튜닝을 많이 안해도 성능이 뛰어나다. 의사결정의 트리의와 배깅의 단점은 극복하고 장점만을 가져온 것이라고 할 수 있다.

단점 : 차원이 높고 매우 희소한 데이터에서는 잘 작동하지 않는다. 이런 희소한 데이터에는 선형 모델이 더 적합할 수 있다.

Fearuture Selection with Information Value

Feature Selection에 Information Value를 이용해보자.

Information Value를 이용한 방법


Kaggle이나 데이터 분석을 하다보면 성능을 높이기 위해 여러가지 feature들을 만들어낸다. 그런데 feature를 무조건 많이 만든다고 성능이 올라갈까? 아니다. target에 대한 영향력이 큰 feature들이어야 성능에 영향을 줄 수 있을 것이다. 그렇다면 중요한 건, 만들어낸 feature들을 어떻게 평가할 것인가이다.

Kaggle에서 Feature Selection 하는 방법들을 보면 gbm모델들의 Feature Importance를 이용하거나 DecisionTree나 RandomForest의 Classifier 객체의 feature_importances_ 메서드를 활용해 Feature Importance를 구해서 비교하는 모습들이 자주 보인다.

하지만 또 다른 방법으로, Information Value를 이용한 Feature Selection을 소개해보고자 한다.

1. Information Value (정보 가치)

모델에서 변수의 사용유무를 판단하는 feature selection에서 유용한 방법이다. 주로 모델을 학습하기전 첫 단계에서 변수들을 제거하는 데 사용한다. 최종 모델에서는 대략 10개 내외의 변수를 사용하도록 한다(여러개 만들어 보고 비교해보는 것이 좋다). IV와 WOE 신용채무능력이 가능한(good) 고객과 불가능한(bad) 고객을 예측하는 로지스틱 회귀 모델링과 밀접한 관계가 있다. 신용 정보 관련분야에서는 good customer는 부채를 갚을 수 있는 고객, bad customer는 부채를 갚을 수 없는 고객을 뜻한다. 일반적으로 이야기할 때는 good customer는 non-events를 의미하고 bad customer는 events를 의미한다.

신용 관련 분야

$${WOE} = ln{\frac{\text{distribution of good}}{\text{distribution of bad}}}$$

$${IV} = \sum{(\text{WOE} \times (\text{distribution of good} - \text{distribution of bad}))}$$

일반적

$${WOE} = ln{\frac{\text{distribution of non-events}}{\text{distribution of events}}}$$

$${IV} = \sum{(\text{WOE} \times (\text{distribution of non-events} - \text{distribution of events}))}$$

  • Information Value 값의 의미
Information Value
예측력
0 to 0.02
무의미
0.02 to 0.1
낮은 예측
0.1 to 0.3
중간 예측
0.3 to 0.5
강한 예측
0.5 to 1
너무 강한 예측(의심되는 수치)

Information Value를 통해서 ‘이 feature를 꼭 사용해야하나?’에 대해 어느정도 답을 내릴 수 있다.

Information Value가 0.5~1.0인 구간을 보면, 강한 예측이지만 의심되는 수치라고 되어있다. 처음보면 이게 무슨 의미인지 잘 이해가 안될 것이다. ‘너무 예측을 잘하는데 수치를 의심하라고?’

하지만 잘 생각해보자. IV는 WOE를 활용한다. WOE는 good과 bad의 분포를 이용하는데, 데이터가 good으로 쏠려있을 경우 WOE는 무조건 잘 나올 수 밖에 없고, 이에 따라 IV값도 잘 나오게 된다.

따라서, IV의 값을 볼 때는 데이터가 어떻게 되어있는지 먼저 살펴보는 게 중요하다.

2. German Credit Data 이용해보기

1
2
path = 'https://archive.ics.uci.edu/ml/machine-learning-databases/statlog/german/german.data'
dataset = pd.read_csv(path, delimiter=' ', header=None)

Column이 제대로 되어있지 않기 때문에 노가다로 넣어준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
COL = [
'Status_of_existing_checking_account',
'Duration_in_month',
'Credit_history',
'Purpose',
'Credit_amount',
'Savings_account_bonds',
'Present_employment_since',
'Installment_rate_in_percentage_of_disposable_income',
'Personal_status_and_sex',
'Other_debtors_guarantors',
'Present_residence_since',
'Property',
'Age_in_years',
'Other_installment_plans',
'Housing',
'Number_of_existing_credits_at_this_bank',
'Job',
'Number_of_people_being_liable_to_provide_maintenance_for',
'Telephone',
'foreign_worker',
'Target'
]

Target값을 0, 1로 만들어준다.

1
dataset['Target'] = dataset['Target'] - 1

Information Value를 구하는 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
max_bin = 10  # 전체 데이터의 예측력에 해를 가하지 않는 한에서 구간을 테스트하였습니다. 통상적으로 10개로 나눔, 15개 20개 다 나눠보고
# 값이 잘나오는 bin을 선택함

def calc_iv(df, col, label, max_bin = max_bin):
"""IV helper function"""
bin_df = df[[col, label]].copy()
# Categorical column
if bin_df[col].dtype == 'object':
bin_df = bin_df.groupby(col)[label].agg(['count', 'sum'])
# Numerical column
else:
bin_df.loc[:, 'bins'] = pd.qcut(bin_df[col].rank(method='first'), max_bin)
# bin_df.loc[:, 'bins'] = pd.cut(bin_df[col], max_bin)
bin_df = bin_df.groupby('bins')[label].agg(['count', 'sum'])

bin_df.columns = ['total', 'abuse']
bin_df['normal'] = bin_df['total'] - bin_df['abuse']
bin_df['normal_dist'] = bin_df['normal'] / sum(bin_df['normal'])
bin_df['abuse_dist'] = bin_df['abuse'] / sum(bin_df['abuse'])
bin_df['woe'] = np.log(bin_df['normal_dist'] / bin_df['abuse_dist'])
bin_df['iv'] = bin_df['woe'] * (bin_df['normal_dist'] - bin_df['abuse_dist'])

bin_df.replace([np.inf, -np.inf], 0, inplace=True)
bin_df = bin_df[bin_df['total'] > 0]
iv_val = sum(filter(lambda x: x != float('inf'), bin_df['iv']))

return bin_df, col, iv_val
1
2
ch_df, ch, ch_i_val = calc_iv(dataset,'Credit_history', 'Target')
ch_df

| |total |abuse |normal |normal_dist |abuse_dist |woe |iv|
|:—-:||:—-:||:—-:||:—-:||:—-:||:—-:||:—-:||:—-:|
|Credit_history||||||||
|A30|40|25| 15|0.021429|0.083333|-1.358123|0.084074|
|A31|49|28| 21|0.030000|0.093333|-1.134980|0.071882|
|A32|530|169|361|0.515714|0.563333|-0.088319|0.004206|
|A33|88|28|60|0.085714|0.093333|-0.085158|0.000649|
|A34|293|50|243|0.347143|0.166667|0.733741|0.132423|