kaggle风控(二)——lending club

本案例数据取自kaggle竞赛lending club(美国最大的P2P公司)。
导入包

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 解决坐标轴刻度负号乱码
plt.rcParams['axes.unicode_minus'] = False
# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Simhei']

import warnings
warnings.filterwarnings("ignore")

#显示全部特征
pd.set_option('display.max_columns', None)

读入数据

data=pd.read_csv('data_all_values.csv')
data.head()

查看数据维度

data.shape

数据维度是(103434, 19)。
查看数据类型

data.info()

可以看到,只有“贷款目的”是字符型变量。
查看标签分布

data['target'].value_counts()

y的分布大致为10:1的比例,存在数据不平衡的情况。

1、LightGBM重要性选择变量

我们采用LightGBM对特征进行筛选(本案例总共只有18个特征,其实可以不需要做特征筛选;如果实际工程中有成百上千的特征,可以按照这个步骤筛选出重要特征)。
查看每个变量的取值个数用以判断是否为分类变量。

data_copy=data.copy()

allFeatures = list(data.columns)   
allFeatures.remove('target')
for i in allFeatures:
    print('变量 [{}] 的不同水平值有 {} 个'.format(i,len(data[i].unique())))   

可以看出,取值个数少的变量为分类变量,将连续变量和分类变量分别拆开。

# 分类变量
categorical_var=['贷款期限', '贷款等级', '工作年限', '房屋所有权', '收入是否由LC验证', '贷款目的', 
'过去6个月内被查询次数', '留置税数量']

# 连续变量
continuous_var=['贷款金额', '利率', '每月还款金额', '年收入', '月负债比', '过去两年借款人逾期30天以上的数字', 
'摧毁公共记录的数量', '额度循环使用率', '总贷款笔数', '拖欠的逾期款项']

查看分类变量的取值范围。

# 查看分类变量数据
for var in categorical_var:
    print('变量 {} 的取值为:{}'.format(var,set(data[var])))

将连续变量标准化

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()                                 
data[continuous_var] = sc.fit_transform(data[continuous_var])  

将数值型的分类变量转为整型

# 字符分类变量
string_var=list(data.select_dtypes(include=["object"]).columns) 
# 从分类变量中减去字符分类变量就是数值分类变量
col=list(set(categorical_var)-set(string_var))
data[col]=data[col].astype(int)

字符分类变量按照坏样本率进行编码(之前我们已经看过了,字符型的变量只有“贷款目的”)

def Encoder(df, col, target):           
    encoder = {}
    for v in set(df[col]):
        if v == v:
            subDf = df[df[col] == v]
        else:
            xList = list(df[col])
            nanInd = [i for i in range(len(xList)) if xList[i] != xList[i]]
            subDf = df.loc[nanInd]
        encoder[v] = sum(subDf[target])*1.0/subDf.shape[0]
    newCol = [encoder[i] for i in df[col]]
    return newCol

string_var=list(data.select_dtypes(include=["object"]).columns) 
col=list(set(categorical_var)&set(string_var))

for i in col:
    data[i] = Encoder(data, i, 'target')
data['贷款目的'].value_counts()

此时再查看一下我们的数据集data。



LighGBM模型有个非常好的功能,就是能指定分类变量,省去了one-hot编码的步骤。

# 保存变量和文件
import pickle
f =open('lgb_col.pkl','wb')
pickle.dump(col,f)
f.close() 

# 建模
allFeatures = list(data.columns)   
allFeatures.remove('target')
X = data[allFeatures]
y = data['target']
from sklearn.model_selection import train_test_split as sp
X_train, X_test, y_train, y_test = sp(X, y, test_size=0.3, random_state=1)

# 加载分类变量
f =open('lgb_col.pkl','rb')
col = pickle.load(f)
f.close()

# lightgbm建模
import lightgbm as LGB
params = {
'objective': 'binary', 
"boosting" : "gbdt",
'num_leaves': 4,    
'min_data_in_leaf': 20,
"subsample": 0.9,
"colsample_bytree": 0.8,
'learning_rate':0.09,
'tree_learner': 'voting',
'metric': 'auc'
        }
dtrain = LGB.Dataset(X_train, y_train, categorical_feature=col)
dtest = LGB.Dataset(X_test, y_test, reference=dtrain, categorical_feature=col)
lgb = LGB.train(params, dtrain, valid_sets=[dtrain, dtest], 
                num_boost_round=3000, early_stopping_rounds=100, verbose_eval=10)

训练好LightGMB模型后,计算变量重要性。

# lightgbm重要性选择变量
importace = list(lgb.feature_importance())
allFeatures=list(lgb.feature_name())
featureImportance = zip(allFeatures,importace)
featureImportanceSorted = sorted(featureImportance, key=lambda k: k[1],reverse=True)

plt.figure(figsize = (5, 10))                                                                                   
sns.barplot(x=[k[1] for k in featureImportanceSorted],y=[k[0] for k in featureImportanceSorted])
plt.xticks(rotation='vertical') 
plt.show()

我们从18个特征中选取重要性排名前13的变量。

feature_selection_lgb = [k[0] for k in featureImportanceSorted[:13]] 

2、分箱

分箱方法有手动、等频、等宽、卡方和决策树分箱5种。本案例选择手动分箱的方法。
为避免在原数据集上修改,我们将数据集复制一份。

data=data_copy.copy()
data=data[feature_selection_lgb+['target']]
data_copy=data.copy()

2.1 分类变量的分箱

分类变量不用做离散化,可以先拿来分箱。

# 定义计算WOE的函数
def Ln_odds(df, col, target):
    # 每个箱子总人数
    total = df.groupby([col])[target].count()
    total = pd.DataFrame({'total': total})
    # 每个箱子坏样本个数
    bad = df.groupby([col])[target].sum()   
    bad = pd.DataFrame({'bad': bad})
    # 合并
    regroup = total.merge(bad, left_index=True, right_index=True, how='left')
    regroup.reset_index(level=0, inplace=True)
    # 计算总人数和总坏客户数
    N = sum(regroup['total'])  
    B = sum(regroup['bad'])
    # 每个箱子好样本个数
    regroup['good'] = regroup['total'] - regroup['bad']
    # 好样本总人数
    G = N - B
    # 计算每个箱子的WOE值
    regroup['bad_pcnt'] = regroup['bad'].map(lambda x: x*1.0/B)
    regroup['good_pcnt'] = regroup['good'].map(lambda x: x * 1.0 / G)
    regroup[col+'_WOE'] = regroup.apply(lambda x: np.log(x.good_pcnt*1.0/x.bad_pcnt),axis = 1)
    # 合并,得到总的WOE表
    df=pd.merge(df, regroup[[col,col+'_WOE']], on=col, how='left')
    return df

# 对分类变量进行分箱
categorical_var=list(set(categorical_var)&set(feature_selection_lgb))
categorical_var=['贷款期限', '房屋所有权', '贷款等级', '过去6个月内被查询次数','工作年限']
for i in categorical_var:   
    data=Ln_odds(data, i, 'target')
    sns.pointplot(x=i, y=i+'_WOE', data=data)      
    plt.xticks(rotation=0)     
    plt.show()





一般分箱会遵循以下3个原则:
①分箱个数不宜过多,一般不超过5个
②每个箱子中的样本比例不宜过少,一般不少于整体个数的5%
③分箱曲线尽量呈现单调性
我们可以看到,只有“贷款等级”和“过去6个月内被查询次数”是单调的,我们需要对每个特征进行逐一地调整分箱。

2.1.1 贷款等级

data=data_copy.copy()

data['贷款等级'].value_counts()

可以看到,贷款等级最后3个箱子样本个数过少。

i='贷款等级'
data[i]=data[i].apply(lambda x: 2 if 2<=x<5 else x)
data[i]=data[i].apply(lambda x: 3 if x>=5 else x)

data=Ln_odds(data, i, 'target')
sns.pointplot(x=i, y=i+'_WOE', data=data)     
plt.xticks(rotation=0)     
plt.show()

下面左图为调整分箱前,右图为调整分箱后的WOE曲线(后同)。


2.1.2 过去6个月内被查询次数

i='过去6个月内被查询次数'
data[i].value_counts()

直接将分类3之后的箱子合并

data[i]=data[i].apply(lambda x: 4 if x>3 else x)

data=Ln_odds(data, i, 'target')
sns.pointplot(x=i, y=i+'_WOE', data=data)  
plt.xticks(rotation=0)     
plt.show()

2.1.3 工作年限

i='工作年限'
data[i].value_counts()

将分类1-4合并为一箱,5-10合并为一箱。

data[i]=data[i].apply(lambda x: 1 if 1<=x<5 else x)
data[i]=data[i].apply(lambda x: 2 if x>=5 else x)

data=Ln_odds(data, i, 'target')
sns.pointplot(x=i, y=i+'_WOE', data=data)     
plt.xticks(rotation=0)     
plt.show()

可以看一下此时的数据集:


'''保存文件''' 
col=[]
for i in list(data.columns):
    if i.find('_WOE')<0:
        col.append(i)    
data=data[col]
data.to_csv('categorical_bins.csv', index=False, encoding='utf-8')

2.2 连续变量的分箱

先看一下连续型变量的描述性统计。

data=pd.read_csv('categorical_bins.csv')
data.head()

continuous_var=list(set(continuous_var)&set(feature_selection_lgb))
continuous_var=['总贷款笔数', '每月还款金额', '过去两年借款人逾期30天以上的数字', 
                '贷款金额', '年收入', '利率', '月负债比', '额度循环使用率']

describe=data[continuous_var].describe().T[['max','min']]
describe

2.2.1 总贷款笔数

i='总贷款笔数'
sns.distplot(data[i][data['target'] == 0].dropna(),color='blue') 
sns.distplot(data[i][data['target'] == 1].dropna(),color='red')
plt.show() 

选取20和30两个分割点

bins=[-1, 20, 30, 200]   #左开右闭,如果可能出现0,那么需要以-1开始
cats=pd.cut(list(data[i]), bins, precision=0)        #指定分组区间
cats.value_counts()  
data[i+'组别']=pd.Series(cats)
data=Ln_odds(data, i+'组别', 'target')
sns.pointplot(x=i+'组别', y=i+'组别_WOE', data=data.sort_values(i+'组别_WOE',ascending=False))      
plt.show()  

2.2.2 每月还款金额

i='每月还款金额'
sns.distplot(data[i][data['target'] == 0].dropna(),color='blue') 
sns.distplot(data[i][data['target'] == 1].dropna(),color='red')
plt.show() 

选择300和750两个分割点

bins=[-1, 300, 750, 2000]
cats=pd.cut(list(data[i]), bins, precision=0)        #指定分组区间
cats.value_counts()  
data[i+'组别']=pd.Series(cats)
data=Ln_odds(data, i+'组别', 'target')
sns.pointplot(x=i+'组别', y=i+'组别_WOE', data=data.sort_values(i+'组别_WOE',ascending=False))  
plt.show()  

2.2.3 过去两年借款人逾期30天以上的数字

i='过去两年借款人逾期30天以上的数字'
sns.distplot(data[i][data['target'] == 0].dropna(),color='blue') 
sns.distplot(data[i][data['target'] == 1].dropna(),color='red')
plt.show() 

分布呈现严重的长尾,选择1作为分割点将特征分为两箱。

bins=[-1, 1, 50]
cats=pd.cut(list(data[i]), bins, precision=0)        #指定分组区间
cats.value_counts()  
data[i+'组别']=pd.Series(cats)
data=Ln_odds(data, i+'组别', 'target')
sns.pointplot(x=i+'组别', y=i+'组别_WOE', data=data.sort_values(i+'组别_WOE',ascending=False))  
plt.show()  

2.2.4 贷款金额

i='贷款金额'
sns.distplot(data[i][data['target'] == 0].dropna(),color='blue') 
sns.distplot(data[i][data['target'] == 1].dropna(),color='red')
plt.show() 

选择10000和20000作为分割点

bins=[-1, 10000, 20000, 50000]
cats=pd.cut(list(data[i]), bins, precision=0)        #指定分组区间
cats.value_counts()  
data[i+'组别']=pd.Series(cats)
data=Ln_odds(data, i+'组别', 'target')
sns.pointplot(x=i+'组别', y=i+'组别_WOE', data=data.sort_values(i+'组别_WOE',ascending=False))  
plt.show() 

2.2.5 年收入

i='年收入'
sns.distplot(data[i][data['target'] == 0].dropna(),color='blue') 
sns.distplot(data[i][data['target'] == 1].dropna(),color='red')
plt.xlim([0,1000000])
plt.show() 

选择150000和300000作为分割点

bins=[-1, 150000, 300000, 10000000]
cats=pd.cut(list(data[i]), bins, precision=0)        #指定分组区间
cats.value_counts()  
data[i+'组别']=pd.Series(cats)
data=Ln_odds(data, i+'组别', 'target')
sns.pointplot(x=i+'组别', y=i+'组别_WOE', data=data.sort_values(i+'组别_WOE',ascending=False))  
plt.show() 

2.2.6 利率

i='利率'
sns.distplot(data[i][data['target'] == 0].dropna(),color='blue') 
sns.distplot(data[i][data['target'] == 1].dropna(),color='red')
plt.show() 

选择8和13作为分割点

bins=[0, 8, 13, 50]
cats=pd.cut(list(data[i]), bins, precision=0)        #指定分组区间
cats.value_counts()  
data[i+'组别']=pd.Series(cats)
data=Ln_odds(data, i+'组别', 'target')
sns.pointplot(x=i+'组别', y=i+'组别_WOE', data=data.sort_values(i+'组别_WOE',ascending=False))  
plt.show()  

2.2.7 月负债比

i='月负债比'
sns.distplot(data[i][data['target'] == 0].dropna(),color='blue') 
sns.distplot(data[i][data['target'] == 1].dropna(),color='red')
plt.xlim([0,200])
plt.show() 

选择20作为分割点

bins=[-1, 20, 1000]
cats=pd.cut(list(data[i]), bins, precision=0)        #指定分组区间
cats.value_counts()  
data[i+'组别']=pd.Series(cats)
data=Ln_odds(data, i+'组别', 'target')
sns.pointplot(x=i+'组别', y=i+'组别_WOE', data=data.sort_values(i+'组别_WOE',ascending=False))  
plt.show() 

2.2.8 额度循环使用率

i='额度循环使用率'
sns.distplot(data[i][data['target'] == 0].dropna(),color='blue') 
sns.distplot(data[i][data['target'] == 1].dropna(),color='red')
plt.show() 

选择50作为分割点

bins=[-1, 50, 200]
cats=pd.cut(list(data[i]), bins, precision=0)        #指定分组区间
cats.value_counts()  
data[i+'组别']=pd.Series(cats)
data=Ln_odds(data, i+'组别', 'target')
sns.pointplot(x=i+'组别', y=i+'组别_WOE', data=data.sort_values(i+'组别_WOE',ascending=False))  
plt.show() 
'''保存文件''' 
col=[]
for i in list(data.columns):
    if i.find('_WOE')<0:
        col.append(i)    
data=data[col]
data.to_csv('cut_bins.csv', index=False, encoding='utf-8')

查看一下此时的数据集data,可以看到,连续变量已经分箱了。


2.3 计算WOE和IV值

# 定义函数计算WOE和IV
def CalcWOE(df, col, target):
    # 每个箱子总人数
    total = df.groupby([col])[target].count()
    total = pd.DataFrame({'total': total})
    # 每个箱子坏样本数
    bad = df.groupby([col])[target].sum()   
    bad = pd.DataFrame({'bad': bad})
    # 合并
    regroup = total.merge(bad, left_index=True, right_index=True, how='left')
    regroup.reset_index(level=0, inplace=True)
    # 计算总人数和总坏样本数
    N = sum(regroup['total']) 
    B = sum(regroup['bad']) 
    # 计算好客户个数
    regroup['good'] = regroup['total'] - regroup['bad']
    G = N - B
    # 计算好客户比例和坏客户比例,并算出WOE
    regroup['bad_pcnt'] = regroup['bad'].map(lambda x: x*1.0/B)
    regroup['good_pcnt'] = regroup['good'].map(lambda x: x * 1.0 / G)
    regroup['WOE'] = regroup.apply(lambda x: np.log(x.good_pcnt*1.0/x.bad_pcnt),axis = 1)
    WOE_dict = regroup[[col,'WOE']].set_index(col).to_dict(orient='index')
    for k, v in WOE_dict.items():
        WOE_dict[k] = v['WOE']
    # 计算每个变量的IV值
    IV = regroup.apply(lambda x: (x.good_pcnt-x.bad_pcnt)*np.log(x.good_pcnt*1.0/x.bad_pcnt),axis = 1)
    IV = sum(IV)
    return {"WOE": WOE_dict, 'IV':IV}

# 取出经过分箱的连续变量和分类变量
all_var=[]
for i in list(data.columns):
    if i.find('组别')>0:
        all_var.append(i)      
all_var=all_var+categorical_var

# 得到每个特征变量的WOE和IV值
WOE_dict = {}
IV_dict = {}
for var in all_var:
    woe_iv = CalcWOE(data, var, 'target')
    WOE_dict[var] = woe_iv['WOE']
    IV_dict[var] = woe_iv['IV']

# 查看每个特征变量的IV值
pd.Series(IV_dict).sort_values(ascending=False)

3、LR建模

3.1 IV特征筛选

IV值同样可以对特征重要性进行筛选:
IV<0.02 无作用
0.02-0.1 弱作用
0.1-0.3 中等
0.3-0.5 强作用
IV>0.5 过强,需要检查是否有问题

'''选取IV>=0.02的变量'''
IV_dict_sorted = sorted(IV_dict.items(), key=lambda x: x[1], reverse=True)
IV_values = [i[1] for i in IV_dict_sorted]
IV_name = [i[0] for i in IV_dict_sorted]

high_IV = {k:v for k, v in IV_dict.items() if v >= 0.02}
high_IV_sorted = sorted(high_IV.items(),key=lambda x:x[1],reverse=True)
print ('总共',len(high_IV_sorted),'个变量IV >= 0.02')  

总共 6 个变量IV >= 0.02

3.2 WOE映射

将IV值筛选出来的6个特征做WOE映射,将各自的每个箱子替换成对应的WOE值。

# short_list记录6个特征名,short_list_2记录6个新的WOE特征名
short_list = high_IV.keys()
short_list_2 = []
for var in short_list:
    newVar = var + '_WOE'
    data[newVar] = data[var].map(lambda x:WOE_dict[var][x])
    short_list_2.append(newVar)

dataWOE = data[short_list_2]
dataWOE.head()

3.3 共线性检验

做LR建模需要检验变量之间的共线性。

# 生成相关性矩阵
corr = round(dataWOE.corr(),2)

mask = np.zeros_like(corr, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True             
plt.figure(figsize = (5, 5))
cmap = sns.diverging_palette(220, 10, as_cmap=True) 
sns.heatmap(corr, mask=mask, cmap=cmap, center=0, annot =True, cbar_kws={"shrink": .5})
plt.show()

计算相关系数之后,还需要考虑多重共线性问题,即计算VIF值。VIF值越大,代表共线性越严重。VIF值:
0 10<=VIF<100,存在较强的多重共线性
VIF>=100,存在严重的多重共线性

# 选择方差共线性<10的变量
from statsmodels.stats.outliers_influence import variance_inflation_factor as vif

col = np.array(data[short_list_2],dtype='float')

for i in range(len(short_list_2)):                                              
    print ('{} VIF是{}'.format(short_list_2[i], vif(col, i))) 

可以看到,6个特征之间不存在多重共线性。

3.4 逻辑回归

在确定变量之间不存在多重共线性之后,就要对变量进行显著性分析,删除p值不显著的变量。

# 构建X和y
X = data[short_list_2]
for col in short_list_2:
    X[col]=X[col].astype('float')
X['intercept'] = [1]*X.shape[0]
y = data['target']

# 建模
import statsmodels.api as sm
lr_sm=sm.Logit(y, X).fit()
glmodel = sm.GLM(y,X,family=sm.families.Binomial()).fit()
glmodel.summary()

可以看到,6个变量都是显著的。
用机器学习中的LR建模。

from sklearn.model_selection import train_test_split as sp
X_train, X_test, y_train, y_test = sp(X, y, test_size=0.3, random_state=1)

from sklearn.linear_model import LogisticRegression as LR  
lr=LR(random_state=1)
lr.fit(X_train, y_train)
from sklearn import metrics
y_test_label = lr.predict(X_test)
y_test_value = lr.predict_proba(X_test)[:, 1] 
print("测试集准确率是: {:.2%}".format(metrics.accuracy_score(y_test, y_test_label)))  
print("测试集AUC是: {:.4}".format(metrics.roc_auc_score(y_test, y_test_value)))  

4、创建评分卡

在确定模型的准确度和AUC值的可接受范围后,可以对每个入模变量进行单变量得分计算,从而求出变量不同取值下的得分。
计算评分卡的公式:



其中A叫做“补偿”,B叫做“刻度”,log(odds)代表了一个人违约的可能性。A、B两个常数可以通过两个假设的分值带入公式求出。这两个假设分别是:
①某个特定的违约概率下的预期分值
②指定的违约概率翻倍的分数(PDO)

b=lr.intercept_       #截距

coe=lr.coef_          #系数
a0 = coe[0][0]        #每月还款金额组别 系数          
a1 = coe[0][1]        #贷款金额组别 系数 
a2 = coe[0][2]        #利率组别 系数 
a3 = coe[0][3]        #月负债比组别 系数 
a4 = coe[0][4]        #贷款等级 系数 
a5 = coe[0][5]        #过去6个月内被查询次数 系数 

A = 500
PDO = 20              #每增加20分,odds(好坏比)增加1倍
B=PDO/np.log(2)

接下来对6个变量做单变量得分。

4.1 每月还款金额

WOE_dict['每月还款金额组别']  #获取字典key,即变量水平值

woe1 = WOE_dict['每月还款金额组别']['(-1, 300]']
score1 = -(B * a0* woe1) + (A-B*b)/dataWOE.shape[0]

woe2 = WOE_dict['每月还款金额组别']['(300, 750]']
score2 = -(B * a0 * woe2) + (A-B*b)/dataWOE.shape[0]

woe3 = WOE_dict['每月还款金额组别']['(750, 2000]']
score3 = -(B * a0 * woe3) + (A-B*b)/dataWOE.shape[0]

4.2 贷款金额

WOE_dict['贷款金额组别']

woe1 = WOE_dict['贷款金额组别']['(-1, 10000]']
score1 = -(B * a1* woe1) + (A-B*b)/dataWOE.shape[0]

woe2 = WOE_dict['贷款金额组别']['(10000, 20000]']
score2 = -(B * a1 * woe2) + (A-B*b)/dataWOE.shape[0]

woe3 = WOE_dict['贷款金额组别']['(20000, 50000]']
score3 = -(B * a1 * woe3) + (A-B*b)/dataWOE.shape[0]

4.3 利率

WOE_dict['利率组别']

woe1 = WOE_dict['利率组别']['(0, 8]']
score1 = -(B * a2* woe1) + (A-B*b)/dataWOE.shape[0]

woe2 = WOE_dict['利率组别']['(8, 13]']
score2 = -(B * a2 * woe2) + (A-B*b)/dataWOE.shape[0]

woe3 = WOE_dict['利率组别']['(13, 50]']
score3 = -(B * a2 * woe3) + (A-B*b)/dataWOE.shape[0]

4.4 月负债比

WOE_dict['月负债比组别']

woe1 = WOE_dict['月负债比组别']['(-1, 20]']
score1 = -(B * a3* woe1) + (A-B*b)/dataWOE.shape[0]

woe2 = WOE_dict['月负债比组别']['(20, 1000]']
score2 = -(B * a3 * woe2) + (A-B*b)/dataWOE.shape[0]

4.5 贷款等级

WOE_dict['贷款等级']  

woe1 = WOE_dict['贷款等级'][1]
score1 = -(B * a4* woe1) + (A-B*b)/dataWOE.shape[0]

woe2 = WOE_dict['贷款等级'][2]
score2 = -(B * a4 * woe2) + (A-B*b)/dataWOE.shape[0]

woe3 = WOE_dict['贷款等级'][3]
score3 = -(B * a4 * woe3) + (A-B*b)/dataWOE.shape[0]

4.6 过去6个月内被查询次数

WOE_dict['过去6个月内被查询次数']  

woe1 = WOE_dict['过去6个月内被查询次数'][0]
score1 = -(B * a5* woe1) + (A-B*b)/dataWOE.shape[0]

woe2 = WOE_dict['过去6个月内被查询次数'][1]
score2 = -(B * a5 * woe2) + (A-B*b)/dataWOE.shape[0]

woe3 = WOE_dict['过去6个月内被查询次数'][2]
score3 = -(B * a5 * woe3) + (A-B*b)/dataWOE.shape[0]

woe4 = WOE_dict['过去6个月内被查询次数'][3]
score4 = -(B * a5 * woe4) + (A-B*b)/dataWOE.shape[0]

woe5 = WOE_dict['过去6个月内被查询次数'][4]
score5 = -(B * a5 * woe5) + (A-B*b)/dataWOE.shape[0]

你可能感兴趣的:(kaggle风控(二)——lending club)