美文网首页
用户贷款逾期预测

用户贷款逾期预测

作者: shenyuer | 来源:发表于2018-03-15 00:00 被阅读0次

    前言:去年参加了数据城堡的算法竞赛,一直没时间记录下来,趁今天来梳理下这个竞赛项目的方方面面。赛题为用户贷款风险预测,目标是利用用户基本信息、用户银行流水、用户信用卡账单以及用户浏览行为4个表的数据预测用户贷款后逾期的概率,其中带标签数据55596条,无标签数据13899条,个人最好成绩是排名前8%。

    解决方案概述

    此次大赛目标是从用户行为数据分析借款用户的信用状况,来判断其是否逾期。针对需要解决的问题和数据特征,主要从三个方面进行处理:数据预处理,特征工程,模型训练。

    首先,由于数据中存在缺失值,因此需要对缺失值数据进行预处理。其次,采用基于学习模型的特征排序方法做了特征选择。然后,针对类别不平衡问题,主要是对少量样本过采样,针对过程中出现的过拟合问题,采用了pca降维以及对特征进行选择的方法。

    本文框架如下:

    1. 好坏样本定义说明
    2. 样本概述
    3. 缺失值处理
    4. 构建新特征
    5. 特征选择
    6. 模型
    7. 最终结果

    1.好坏样本定义

    样本有55596条带标签数据,其中标签为0,1,1表示用户逾期。
    正负样本分布如下:

    print('训练集中各类别数据的个数:', trains.groupby('标签').size())
    
    训练集中各类数据的个数: 标签
    0.0    48413
    1.0     7183
    

    可以看出正负样本并不平衡,正样本大概是负样本的7倍,因此存在一个样本不平衡问题。

    2.样本概述

    提供的近7w条数据中,主要为四个表,分别是用户信息表,银行流水记录,用户浏览行为,信用卡账单。其中字段名如下:
    用户信息表:

    用户id 性别 职业 教育程度 婚姻状态 户口类型

    银行流水记录表:

    用户id 时间戳 交易类型 交易金额 工资收入标记

    用户浏览行为表:

    用户id 时间戳 浏览行为数据 浏览子行为编号

    信用卡账单表:

    用户id 时间 银行标识 上期账单金额 上期还款金额
    调整金额 循环利息 可用余额 预借现金额度 还款状态
    信用卡额度 本期账单余额 本期账单最低还款额 消费笔数 本期账单金额

    共计27个字段。字段数据都经过举办方脱敏处理,业务信息缺失。

    3.缺失值处理

    赛题数据中大部分样本都有缺失值,常用的缺失值处理方法是缺失值填充(用同类别数据的特征均值,中值等)

    feature=dataset[:]
    dataset=dataset.fillna(-1)
    d=feature['用户银行流水记录缺失统计']=(dataset==-1).sum(axis=1)
    

    用均值填充缺失值

    feature.fillna(feature.mean(),inplace=True)
    

    4.构建新特征

    赛题数据含有类别特征,很多算法(如逻辑回归,SVM)只能处理数值型特征,这种情况下需要对类别特征进行编码,这里采用了 One-Hot 编码,得到了 01 特征,解决了分类器不能处理类别特征的问题。

    dataset=pd.get_dummies(dataset,
                           columns=dataset[['用户性别','用户职业','用户教育程度',
                                                    '用户婚姻状态','用户户口类型']]).drop(['标签'],axis=1)
    

    根据放款时间来划分时间窗口,构建每个表的放款前特征和放款后特征。

    # ----------------------------------------银行流水特征------------------------------------------#
    print('银行流水记录')
    feature = pd.read_csv('../feature/训练放款时间表')
    d = pd.read_csv('../feature/银行流水记录表')
    d=pd.merge(d,feature,how='left', on = '用户标识')
    # ----------------------------------------放款前特征统计------------------------------------------#
    print('放款前特征统计')
    t = d[(d['流水时间'] <= d['放款时间'])] 
    gb1 = t[(t['交易类型'] == 0)].groupby(['用户标识'], as_index=False)  # 收入统计
    gb2 = t[(t['交易类型'] == 1)].groupby(['用户标识'], as_index=False)  # 支出统计
    gb3 = t[(t['工资收入标记'] == 1)].groupby(['用户标识'], as_index=False)  # 工资收入统计
    x1 = gb1['交易金额'].agg({'放款前用户收入笔数': 'count', '放款前用户收入总计': 'sum'})
    x2 = gb2['交易金额'].agg({'放款前用户支出笔数': 'count', '放款前用户支出总计': 'sum'})
    x3 = gb3['交易金额'].agg({'放款前用户工资收入笔数': 'count', '放款前用户工资收入总计': 'sum'})
    
    feature = pd.merge(feature, x1, how='left', on='用户标识')
    feature = pd.merge(feature, x2, how='left', on='用户标识')
    feature = pd.merge(feature, x3, how='left', on='用户标识')
    
    feature['放款前用户收入支出笔数差值'] = feature['放款前用户收入笔数'] - feature['放款前用户支出笔数']
    feature['放款前用户收入支出总计差值'] = feature['放款前用户收入总计'] - feature['放款前用户支出总计']
    feature['放款前用户非工资收入笔数'] = feature['放款前用户收入笔数'] - feature['放款前用户工资收入笔数']
    feature['放款前用户非工资收入总计'] = feature['放款前用户收入总计'] - feature['放款前用户工资收入总计']
    

    构建新特征后特征维度达到164维。

    5.特征选择

    构建特征后,特征维度达到164维,多维特征一方面可能会导致维数灾难,另一方面很容易导致过拟合,因此需要做降维处理,常见的降维方法有 PCA。除了采用降维算法之外,也可以用特征选择来降低特征维度。特征选择的方法很多:卡方检验、皮尔森相关系数、正则化方法(L1, L2)、基于模型的特征选择方法。

    # 特征选择,基于卡方检验
    # trains=SelectKBest(chi2,k=20).fit_transform(trains,target)
    
    # 基于惩罚项的特征选择法
    # trains=SelectFromModel(LogisticRegression(penalty='l1',C=0.1)).fit_transform(trains,target)
    
    # 基于树模型的特征选择
    
    # trains=SelectFromModel(GradientBoostingClassifier()).fit_transform(trains,target)
    
    # 降维,基于pca
    
    pca=PCA(n_components=50)
    
    trains=pca.fit_transform(trains)
    test=pca.fit_transform(test)
    

    6.模型

    这里主要尝试了LR和XGB,在效果上XGB更好,可能是因为XGB在训练的同时会进行特征选择。

    parameters= [{
                      'max_depth':[3,5,7], ##5)
                      'learning_rate':[0.1,0.5, 1.0],#0.1
                      'subsample':[0.75,0.8,0.85,0.9],#0.8
                      'min_child_weight':[1,3,5]#5
    
                      }]
    #parameters= [{'n_estimators':[100,200,500,1000]
    #                  }]
    clf = GridSearchCV(xgb.XGBClassifier(n_estimators=100,gamma=0,scale_pos_weight=1),
                       param_grid=parameters,scoring='roc_auc',n_jobs=4,iid=False,cv=5)
    print('开始训练')
    clf.fit(x_train, y_train)
    

    参数解释:
    learning_rate:学习速率
    min_child_weight :这个参数用来控制过拟合,如果数值太大可能会导致欠拟合。
    max_depth:设置树的最大深度,控制过拟合,如果树的深度太大会导致过拟合
    subsample:对原数据集进行随机采样来构建单个树。这个参数代表了在构建树时候对原数据集采样的百分比。eg:如果设为0.8表示随机抽取样本中80%的个体来构建树
    scale_pos_weight:在样本类别十分不平衡时,参数设定为一个正值,可以使算法更快收敛
    模型结果:

    AUC:0.87
    

    特征重要性输出:

    image.png

    可见最重要特征有用户性别、用户职业、用户婚姻状态、用户教育程度、用户户口类型、放款前浏览行为数据、放款前浏览行为数据最小值、放款前浏览子行为编号_8
    可见除了基本信息外,用户的浏览行为是强有力的特征。

    7.最终结果

    不同方法及模型线下表现效果:

    预处理 AUC(LR) AUC(XGB)
    标准化处理 0.8726 0.8722
    特征选择(卡方检验) 0.8742 0.8723
    基于惩罚项的特征选择 0.8741 0.8723
    基于树模型 0.8741 0.8711

    构建新特征后:

    预处理 AUC(LR) AUC(XGB)
    构建放款前后新特征 0.8973
    优化用户特征 0.9172

    最终结果以逾期概率的形式上传到平台:

    userid,probability
    55597,0.3506719172000885
    55598,0.3657565116882324
    55599,0.3827580213546753
    55600,0.36820918321609497
    55601,0.34563612937927246
    55602,0.36067867279052734
    55603,0.36357182264328003
    55604,0.3907186985015869
    55605,0.34469443559646606
    55606,0.3836720585823059
    55607,0.3370608389377594
    55608,0.38630616664886475
    55609,0.3718336224555969
    
    提交结果 image.png

    第一名成绩为0.4746,与之相比我还有很大差距,但经过这次比赛我学到了很多,主要是关于解决问题的思路,感谢诸位大神的博客,这次主要参考了微额借款用户人品预测大赛冠军的解决方案。
    以上就是这次比赛的大概内容了!

    相关文章

      网友评论

          本文标题:用户贷款逾期预测

          本文链接:https://www.haomeiwen.com/subject/kiiqqftx.html