KS(Kolmogorov-Smirnov Statistics) 통계량 알아보기

2022. 7. 30. 10:24관심있는 주제/분석 고려 사항

728x90

Kolmogorov-Smirnov(KS) 통계는 예측 모델을 검증하는 데 사용되는 가장 중요한 메트릭 중 하나입니다.

특히 Banking, Financial services and Insurance (BFSI) 도메인에서 자주 사용됩니다.

 

은행에서 프로젝트를 수행하는 위험 또는 마케팅 분석 팀의 일원이라면 이 지표에 대해 들어봤을 것입니다.

 

정의

검색을 하면 가장 많이 나오는 정의는 다음과 같습니다.

K-S 통계량은 우량 집단과 불량집단의 누적 분포의 차이를 나타내는 지표로 신용평가모형의 변별력 평가 시 주요 판별 통계량으로 활용됩니다.

먼가 금융 용어가 많이 섞여 이해하기 어려울 수 있지만, 간단하게 말하면, 2개의 집단이 동일한 분포를 이루고 있는 지를 검증하는 검증 지표라고 할 수 있습니다.

 

위에 있는 Score에 대한 파란선과 빨간 선은 각 집단의 누적 분포를 의미합니다.

두 누적 분포를 비교하고 그 사이의 최대 차이를 반환하는 것이 ks 통계량입니다.

그리고 또 하나의 특징은 이와 같은 경우 특정 분포를 가정하지 않고 하는 방법이라 분포에 제한이 없는 방식입니다.

이는 데이터 분포와 관련된 가정을 테스트할 필요가 없음을 의미하는 비모수 테스트입니다.

 

가설

통계적 지표니 가설을 적으면 다음과 같습니다.

간단하게 적으면 다음과 같습니다.

 

H0 : 두 집단의 누적 분포가 같다

H1 : 두 집단의 누적 분포가 같지 않다.

 

해석을 하는 것에서는 예를 들어 P-Value가 0.05(임의) 보다 작게 돼서 귀무가설을 기각하게 되면, 두 집단의 누적 분포가 같다고 말할 근거가 없다. 

(틀렸을지도...ㅎ)

 

해석

 

머신 러닝 개발자 입장

결국 우리가 일반적으로 적용할 때 이것에 대한 해석을 머신러닝 입장에서 말하면, 두 집단의 분포가 얼마가 차이가 나는 지를 통계적으로 알 수 있고, 이것을 통해 두 집단을 얼마나 잘 구별할 수 있는 지를 이해할 수 있게 됩니다.

 

BFSI 도메인 마케터 분석팀 입장

특히 KS 통계량 같은 경우 신용 평가 모형에 대한 성능 측정 지표로 사용하는데, 신용 평가 모형이라 함은 다음과 같습니다.

신용 평가 모형이란?
과거의 신용 거래 행위를 기반으로 빌린 돈을 미래에 잘 상환할 가능성을 예측하는 모형
NICE 기준)
신용 평점 모형은 개인의 과거와 현재의 신용정보를 바탕으로 향후 1년내 90일 이상 장기연체 등 신용위험이 발생할 가능성을 예측하는 모형

즉 신용 등급, 신용 점수와 같은 것은 통계적 모형에 의해 산출된 확률(빌린 돈을 미래에 잘 상환할 가능성)을 의미합니다.

 

좋은 신용평가 모형이라는 것은

미래에 돈을 갚지 않은 고객들은 신용점수가 낮은 부분에 집중되어 있어야 하고,

미래에 돈을 잘 갚은 고객들은 신용점수가 높은 부분에 집중되어야 합니다.

 

즉 아래와 같이 미래에 상환하지 못할 사람들과 상환할 사람을 잘 분리하게 되면, 좋은 모형이고, 

두 개의 집단을 잘 분리하지 못하게 되면 리스크가 발생하게 됩니다.

 

그리고 이것에 대한 잘됬다는 지표는 현실 상황을 반영해서 정할 수 밖에 없게 됩니다.

일반적으로 잘 됬다라고 하는 것은 0.3~0.4 사이의 지표에 도달하게 되면 일반적이라고 하는 것 같습니다.

(신용평가모형에서 콜모고로프-스미르노프 검정기준의 문제점 논문 기준)

 

통계량에 따른 등급(일반적 사용)

기준 등급
0.2 이하 판별력 낮은 모형
0.2 ~ 0.4 적정한 모형
0.4 ~ 0.5 판별록이 좋은 모형
0.5 이상 판별력이 아주 좋은 모형

 

2005 년에 Joseph 라는 저자는 다음과 같이 표를 정해서 기준을 정했다고 합니다.

하지만 주의 깊게 봐야하는 것은 정규 분포를 가정해서 한 것이기 때문에, 실제 현실 분포랑은 많은 괴리가 있는 판단 기준이라고 생각됩니다.

 

예시

 

특정 제품을 구입할 가능성이 있는 잠재 고객을 식별하는 것이 목표인 성향 모형을 만들고 있다고 가정합니다.

 

이 경우 종속(목표) 변수는 0(비 사건) 또는 1(사건)의 두 가지 결과만 갖는 이진 분류 형식입니다.

"Event"는 제품을 구매한 사람을 의미합니다. "Non-Event"는 제품을 구매하지 않은 사람들을 말합니다.

KS 통계량은 모형이 전망과 비전망을 구별할 수 있는지 여부를 측정합니다.

 

 

KS Statistic 표현하는 2가지 방법

Method 1 : Decile Method

방법 1은 이진 예측 모델을 검증하기 위해 KS 통계를 계산하는 가장 일반적인 방법입니다. 

 

단계

  1. KS를 계산하기 전에 두 개의 변수가 필요합니다.
    하나는 바이너리여야 하는 종속 변수입니다.
    두 번째는 통계 모델에서 생성된 예측 확률 점수입니다.
  2. 확률을 10개 부분으로 나누는 것을 의미하는 예측된 확률 열을 기반으로 십분위수를 만듭니다. 
    첫 번째 십분위수에는 가장 높은 확률 점수가 포함되어야 합니다.
  3. 각 십분위에서 Event 및 Non-eVENT의 누적 퍼센트를 계산한 다음 이 두 누적 분포의 차이를 계산합니다.
  4. KS 통계량은 그중에서 차이가 최대인 곳입니다.
  5. KS가 상위 3분위 안에 있고 40점 이상이면 좋은 예측 모형으로 간주됩니다.
    동시에 모델이 과적합 문제로 어려움을 겪고 있지 않은지 확인하기 위해 다른 성능 메트릭을 확인하여 모델을 검증하는 것이 중요하다.

위의 순서를 정리하면 아래 표와 같이 된다고 합니다.

파이썬 코드

import pandas as pd
import numpy as np
df = pd.read_csv("https://raw.githubusercontent.com/deepanshu88/data/master/data.csv")

 

 

KS Decile 버전 코드

def ks(data=None,target=None, prob=None):
    data['target0'] = 1 - data[target]
    # 확률값을 정렬 후 균등하게 10등분
    data['bucket'] = pd.qcut(data[prob], 10)
    grouped = data.groupby('bucket', as_index = False)
    kstable = pd.DataFrame()
    kstable['min_prob'] = grouped.min()[prob]
    kstable['max_prob'] = grouped.max()[prob]
    kstable['events']   = grouped.sum()[target]
    kstable['nonevents'] = grouped.sum()['target0']
    kstable = kstable.sort_values(by="min_prob", ascending=False).reset_index(drop = True)
    # 전체 집단에서 이벤트 발생 수(분위수별)
    kstable['event_rate'] = (kstable.events / data[target].sum()).apply('{0:.2%}'.format)
    # 전체 집단에서 이벤트 발생 하지 않은 수(분위수별)
    kstable['nonevent_rate'] = (kstable.nonevents / data['target0'].sum()).apply('{0:.2%}'.format)
    kstable['cum_eventrate']=(kstable.events / data[target].sum()).cumsum()
    kstable['cum_noneventrate']=(kstable.nonevents / data['target0'].sum()).cumsum()
    # 2개의 집단의 누적 차
    kstable['KS'] = np.round(kstable['cum_eventrate']-kstable['cum_noneventrate'], 3) * 100

    #Formating
    kstable['cum_eventrate']= kstable['cum_eventrate'].apply('{0:.2%}'.format)
    kstable['cum_noneventrate']= kstable['cum_noneventrate'].apply('{0:.2%}'.format)
    kstable.index = range(1,11)
    kstable.index.rename('Decile', inplace=True)
    pd.set_option('display.max_columns', 9)
    print(kstable)
    
    #Display KS
    from colorama import Fore
    # 가장 차이가 많은 부분 찾기
    print(Fore.RED + "KS is " + str(max(kstable['KS']))+"%"+ " at decile " + str((kstable.index[kstable['KS']==max(kstable['KS'])][0])))
    return(kstable)

결과물 및 시각화

mydf = ks(data=df,target="y", prob="p")
max_idx = mydf["KS"].idxmax()

cum_event_rate_max = mydf['cum_eventrate'].str.replace("%","").astype(float).tolist()[max_idx]
cum_non_event_rate_max = mydf['cum_noneventrate'].str.replace("%","").astype(float).tolist()[max_idx]
y_min = min([cum_event_rate_max , cum_non_event_rate_max])
y_max = max([cum_event_rate_max , cum_non_event_rate_max])
import matplotlib.pyplot as plt
plt.plot(range(1,11), mydf['cum_eventrate'].str.replace("%","").astype(float).tolist(),"o-", label="cumsum event rate")
plt.plot(range(1,11), mydf['cum_noneventrate'].str.replace("%","").astype(float).tolist() , "o-",label="cumsum non-event rate")
plt.vlines(x=max_idx+1 , ymin= y_min, ymax = y_max,color='r',label=f"KS : {y_max-y_min}")
plt.legend()

 

Method 2 : KS Two Sample Test

Scipy python 라이브러리를 사용하면 두 개의 샘플 KS Statistic을 계산할 수 있습니다. 여기에는 data1과 data2의 두 가지 모수가 있습니다.

데이터 1에 비사건에 해당하는 모든 확률 점수를 입력합니다. 데이터 2에서는 이벤트에 대한 확률 점수를 사용합니다.

from scipy.stats import ks_2samp
df = pd.read_csv("https://raw.githubusercontent.com/deepanshu88/data/master/data.csv")
ks_2samp(df.loc[df.y==0,"p"], df.loc[df.y==1,"p"])
# KstestResult(statistic=0.6033333333333334, pvalue=1.5892772996981769e-31)

구현 방식에 따라서 값의 차이가 발생하는 것을 알 수 있습니다.

https://github.com/scipy/scipy/blob/v1.9.0/scipy/stats/_stats_py.py#L7664-L7857

 

GitHub - scipy/scipy: SciPy library main repository

SciPy library main repository. Contribute to scipy/scipy development by creating an account on GitHub.

github.com

 

 

 

 

 

참고

(논문 : 신용평가모형에서 콜모고로프-스미르노프 - KoreaScience)

https://www.koreascience.or.kr/article/JAKO200804050608356.pdf

https://zzinnam.tistory.com/entry/R%EC%8B%A4%EC%8A%B5K-S-%ED%86%B5%EA%B3%84%EB%9F%89-%EC%82%B0%EC%B6%9C%ED%95%98%EA%B8%B0

 

[R실습]K-S 통계량 산출하기

1. K-S(Kolmogorov - Smirnov Statistics) 통계량 본래 K-S 통계량(Kolmogorov - Smirnov Statistics)은 서로 다른 두개의 집단이 동일한 분포를 이루고 있는지를 검증하는 검증지표로 통계학의 용어입니다. K-S통..

zzinnam.tistory.com

https://www.listendata.com/2019/07/KS-Statistics-Python.html#:~:text=What%20is%20KS%20Statistics%3F,the%20maximum%20difference%20between%20them.

 

Calculate KS Statistic with Python

This articles explains multiple ways to calculate KS Statistic with Python. KS Statistics is one of the most important metrics used for validating predictive models

www.listendata.com

 

728x90