今年四五月份参加的平安的机器学习挑战赛获了二等奖奖,本来想忙完这阵好好吧比赛的经过分享一下的,但是做完比赛之后很快又忙于毕业设计。在细节淡忘之前想要好好把做的东西整理记录一下。

初赛赛题解析

题目非常简单,就是利用借款人的身份信息,借款记录,信用评级等信息,预测这个借款人是否会欺诈的而分类问题。
提供了test集,train集,特征的说明文件和提交样品sample。参赛队伍有近一个月的时间建立模型,训练模型,提交结果。一个队伍最多有3个人,最多提交五次,取最高分作为成绩。

特征的理解

由于初赛时间充裕,我们可以逐个(64个)对特征进行分析,进而选择最好的处理方法。首先为了便于理解我们翻译了主办方提供的特征说明文档。其中acc_now_deling是我们的Label,下面的都是提供的特征。有些特征的理解需要一些金融知识,我们这些外行只有强行看懂了。
特征说明

特征的分析

光看懂文档当然是不够了,我们还调用Python的Pandas包对特征数据进行了初步的分析。

Label

首先对Y值进行分析,可以看出,正负类高度不平衡,达到了200:1的水平。这会对预测的结果造成深刻影响。我们后面会说一些我们解决这个问题的方法。

1
2
3
4
>>> y_train.value_counts()
0 706610
1 3293
Name: acc_now_delinq, dtype: int64

Y值正负例比较

年份对贷款量对影响

1
2
3
4
5
>>> plt.figure(figsize=(12,8))
>>> sns.barplot('year', 'loan_amnt', data=all_df, palette='tab10')
>>> plt.title('Issuance of Loans', fontsize=16)
>>> plt.xlabel('Year', fontsize=14)
>>> plt.ylabel('Average loan amount issued', fontsize=14)

年份对贷款量对影响

贷款量随年份逐年增加,上面的短线事贷款量的方差。

loan_status对Y值对影响

1
2
3
4
5
6
7
8
9
10
11
>>> td1=train_df[train_df['acc_now_delinq'] == 1].groupby(['loan_status', 'acc_now_delinq']).size()
>>> td2=train_df[train_df['acc_now_delinq'] == 0].groupby(['loan_status', 'acc_now_delinq']).size()
>>> a = td2.values
>>> b = td1.values.astype(float)
>>> values= b/a
>>> td3=pd.Series(values, index=index)

>>> fig, ax1= plt.subplots(nrows=1, ncols=1, figsize=(14,6))
>>> cmap = plt.cm.coolwarm_r
>>> td3.unstack().plot(kind='bar', stacked=True, colormap=cmap, ax=ax1, grid=False)
>>> ax1.set_title('Type of Loans by Grade', fontsize=14)

loan_status对Y值对影响

贷款状态对违约的影响,我们可以清楚看到处在LATE状态下的违约率明显偏高。Changed off字段下则完全没有违约问题。

各个特征相对于Y值的协方差

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
28
29
>>> data_corr.acc_now_delinq.sort_values(ascending=False)
acc_now_delinq 1.000000
sub_grade 0.029486
int_rate 0.027148
total_acc 0.027063
tot_cur_bal 0.024064
issue_d_year 0.023436
collections_12_mths_ex_med 0.021125
home_ownership_MORTGAGE 0.015780
annual_inc 0.015264
out_prncp 0.013659
out_prncp_inv 0.013650
total_rev_hi_lim 0.009018
emp_length 0.008985
verification_status_Source Verified 0.007455
installment 0.007122
verification_status_Verified 0.006521
region 0.005690
term 0.005633
purpose_home_improvement 0.005144
funded_amnt_inv 0.004894
funded_amnt 0.004691
loan_amnt 0.004580
purpose_debt_consolidation 0.004071
total_rec_late_fee 0.003755
dti 0.003273
total_rec_int 0.002244
home_ownership_OWN 0.002197
...

协方差衡量了每个特征与Y值的互相惯性,协方差的绝对值越小,特征越不重要。不过这种方法没有考虑到特征的组合,不能完全依照这个。

每个特征值NULL的数量

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
28
29
30
>>> LoanStats_df.isnull().sum().sort_values(ascending=True)
idx 19
hardship_flag 19
zip_code 19
addr_state 19
application_type 19
policy_code 19
last_pymnt_amnt 19
collection_recovery_fee 19
recoveries 19
total_rec_late_fee 19
total_rec_int 19
revol_bal 19
total_rec_prncp 19
total_pymnt_inv 19
initial_list_status 19
out_prncp 19
purpose 19
out_prncp_inv 19
total_pymnt 19
pymnt_plan 19
debt_settlement_flag 19
loan_amnt 19
funded_amnt 19
funded_amnt_inv 19
term 19
int_rate 19
installment 19
grade 19
...

原则是NULL数量超过80%弃用这个特征,只有少量NULL的会填补特征,视具体情况补充均值,最大最小值,或者其他值。特殊情况会删除整条数据。

独热编码

1
2
>>> train_df.home_ownership.unique()
array(['MORTGAGE', 'RENT', 'OWN', 'OTHER', 'NONE', 'ANY'], dtype=object)

像这样的非数值类型变量要数值化,具体方法有二值化和独热编码。

经过对题目给的所有数据对分析之后,下一步就是对数据的预处理了。