金融分野では、y値と予測されるデフォルト確率は、分布が不明な2つの分布にすぎません。優れた信用リスク管理モデルは、一般に、精度、安定性、および解釈可能性の観点からモデルを評価します。
一般的に言えば。善人のサンプルの分布は、悪人のサンプルの分布とは大きく異なるはずです。KSは、有効性指標の識別能力指標です。** KSは、モデルのリスク識別能力を評価するために使用され、KS指標は、良いサンプルと悪いサンプルの蓄積を測定します。分布の違い。 ****
良いサンプルと悪いサンプルの累積差が大きく、KSインデックスが大きいほど、モデルがリスクを区別する能力が高くなります。
1、 ksの計算の中核となるクロス集計の実装は、善人と悪人の累積確率分布です。pandas.crosstab関数を使用して、累積確率分布を計算します。
2、 roc_curveの実装では、sklearnライブラリのroc_curve関数がrocとaucを計算するときに、計算プロセス中に善人と悪人の累積確率分布が取得され、sklearn.metrics.roc_curveを使用してks値を計算します。
3、 ks_2sampの実装では、stats.ks_2samp()関数を呼び出して計算します。 scipy.stats.ks_2samp¶をリンクしてks_2samp()のソースコードを実装します。詳細なプロセスはここに実装されています
4、 stats.ks_2samp()を直接呼び出して、ksを計算します
import pandas as pd
import numpy as np
from sklearn.metrics import roc_curve
from scipy.stats import ks_2samp
def ks_calc_cross(data,pred,y_label):'''
特徴:KS値を計算し、対応する分割点と累積分布関数曲線グラフを出力します
入力値:
data:モデルスコアと実際のラベルを含む2次元配列またはデータフレーム
pred:モデルスコア(通常はポジティブクラスを予測する確率)を表す1次元の配列またはシリーズ
y_label:実際のラベルを表す1次元の配列またはシリーズ({0,1}または{-1,1})
出力値:'ks':KS値、'crossdens':良い顧客と悪い顧客の累積確率分布とそれらの差のギャップ
'''
crossfreq = pd.crosstab(data[pred[0]],data[y_label[0]])
crossdens = crossfreq.cumsum(axis=0)/ crossfreq.sum()
crossdens['gap']=abs(crossdens[0]- crossdens[1])
ks = crossdens[crossdens['gap']== crossdens['gap'].max()]return ks,crossdens
def ks_calc_auc(data,pred,y_label):'''
特徴:KS値を計算し、対応する分割点と累積分布関数曲線グラフを出力します
入力値:
data:モデルスコアと実際のラベルを含む2次元配列またはデータフレーム
pred:モデルスコア(通常はポジティブクラスを予測する確率)を表す1次元の配列またはシリーズ
y_label:実際のラベルを表す1次元の配列またはシリーズ({0,1}または{-1,1})
出力値:'ks':KS値
'''
fpr,tpr,thresholds=roc_curve(data[y_label[0]],data[pred[0]])
ks =max(tpr-fpr)return ks
def ks_calc_2samp(data,pred,y_label):'''
特徴:KS値を計算し、対応する分割点と累積分布関数曲線グラフを出力します
入力値:
data:モデルスコアと実際のラベルを含む2次元配列またはデータフレーム
pred:モデルスコア(通常はポジティブクラスを予測する確率)を表す1次元の配列またはシリーズ
y_label:実際のラベルを表す1次元の配列またはシリーズ({0,1}または{-1,1})
出力値:'ks':KS値、'cdf_df':良い顧客と悪い顧客の累積確率分布とそれらの差のギャップ
'''
Bad = data.loc[data[y_label[0]]==1,pred[0]]
Good = data.loc[data[y_label[0]]==0, pred[0]]
data1 = Bad.values
data2 = Good.values
n1 = data1.shape[0]
n2 = data2.shape[0]
data1 = np.sort(data1)
data2 = np.sort(data2)
data_all = np.concatenate([data1,data2])
cdf1 = np.searchsorted(data1,data_all,side='right')/(1.0*n1)
cdf2 =(np.searchsorted(data2,data_all,side='right'))/(1.0*n2)
ks = np.max(np.absolute(cdf1-cdf2))
cdf1_df = pd.DataFrame(cdf1)
cdf2_df = pd.DataFrame(cdf2)
cdf_df = pd.concat([cdf1_df,cdf2_df],axis =1)
cdf_df.columns =['cdf_Bad','cdf_Good']
cdf_df['gap']= cdf_df['cdf_Bad']-cdf_df['cdf_Good']return ks,cdf_df
data ={'y_label':[1,1,1,1,1,1,0,0,0,0,0,0],'pred':[0.5,0.6,0.7,0.6,0.6,0.8,0.4,0.2,0.1,0.4,0.3,0.9]}
data = pd.DataFrame(data)
ks1,crossdens=ks_calc_cross(data,['pred'],['y_label'])
ks2=ks_calc_auc(data,['pred'],['y_label'])
ks3=ks_calc_2samp(data,['pred'],['y_label'])
get_ks = lambda y_pred,y_true:ks_2samp(y_pred[y_true==1], y_pred[y_true!=1]).statistic
ks4=get_ks(data['pred'],data['y_label'])print('KS1:',ks1['gap'].values)print('KS2:',ks2)print('KS3:',ks3[0])print('KS4:',ks4)
出力結果:
KS1:[0.83333333]
KS2:0.833333333333
KS3:0.833333333333
KS4:0.833333333333
データにNANデータがある場合、注意が必要な問題がいくつかあります。
たとえば、元のデータにy_label = 0、pred = np.nanを追加しました。
data = {‘y_label’:[1,1,1,1,1,1,0,0,0,0,0,0,0],
‘pred’:[0.5,0.6,0.7,0.6,0.6,0.8,0.4,0.2,0.1,0.4,0.3,0.9,np.nan]}
この時点で実行します
ks1,crossdens=ks_calc_cross(data,[‘pred’], [‘y_label’])
出力結果
KS1: [ 0.83333333]
実施した
ks2=ks_calc_auc(data,[‘pred’], [‘y_label’])
次のエラーが報告されます
ValueError: Input contains NaN, infinity or a value too large for dtype(‘float64’).
実施した
ks3=ks_calc_2samp(data,[‘pred’], [‘y_label’])
出力結果
KS3: 0.714285714286
実施した
ks4=get_ks(data[‘pred’],data[‘y_label’])
出力結果
KS4: 0.714285714286
上記の結果からわかる
3つの方法で計算されたks値はすべて異なります。
ks_calc_crossの計算では、NANは無視され、正しいデータの確率分布が計算されます。計算されたksは、手動で計算されたksと同じです。
ks_calc_auc関数の組み込み関数はNAN値を処理できないため、エラーを直接報告します。したがって、ks値を計算するためにks_calc_aucが必要な場合は、事前にNAN値を削除する必要があります。
ks_calc_2sampによって計算されたksはsearchsorted()関数によるものです(興味のある学生は自分でデータをシミュレートしてこの関数を見ることができます)。Nan値はデフォルトで最大にソートされ、データの元の累積分布確率が変更され、計算されたksになります。実際のksにエラーがあります。
総括する
実際の状況では、通常、デフォルトの確率のks値を計算しますが、現時点ではNAN値はありません。したがって、上記の3つの方法でks値を計算できます。ただし、単一の変数のks値を計算する場合、データ品質が良くなく、NAN値がある場合は、ks_calc_aucとks_calc_2sampを引き続き使用すると問題が発生します。
2つの解決策があります
事前にデータのNAN値を削除してください
ks_calc_crossを使用して直接計算します。
Pythonを使用してKSを計算する上記の詳細な例は、エディターによって共有されるすべてのコンテンツです。参照を提供したいと思います。
Recommended Posts