失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 消费者人群画像—信用智能评分 :信用分预测

消费者人群画像—信用智能评分 :信用分预测

时间:2023-09-02 16:29:09

相关推荐

消费者人群画像—信用智能评分 :信用分预测

前言

这是关于预测分数的一个比赛,本来也想了解别人的代码来思考别人是如何做的,顺便自己也要学习一下。废话不多说,这里看下如何处理数据的。

数据 探索可视化

数据集下载可以在kaggle 里找得到,kaggle 国内可以访问,并且也可以用他的平台来跑代码,很方便的做一些事情,先来看下数据探索这一块。这里把测试集和训练集都融合在一起做特征分析,其实是因为有可能出现在测试集而不存再训练集中的特征值,这里一同处理了,

import pandas as pdimport numpy as npimport lightgbm as lgbfrom sklearn.kernel_ridge import KernelRidgefrom sklearn.linear_model import ElasticNet, BayesianRidgefrom sklearn.model_selection import KFold, StratifiedKFold, RepeatedKFoldfrom sklearn.metrics import mean_squared_error as mse, mean_absolute_error as mae, mean_absolute_errorimport xgboost as xgbimport matplotlib.pyplot as pltimport catboost as ctb## 读取 数据集path = "../input/mobile-credit/"train = pd.read_csv(path + '/train_dataset.csv')print(train.shape)train['type'] = 1test = pd.read_csv(path + '/test_dataset.csv')test['type'] = 0data = pd.concat([train, test], ignore_index=True)print(data.shape)## 来看下数据大概情况data.info()print('-'*80)print(data.dtypes.value_counts())columnsList = list(data)print(columnsList)for col in columnsList:print('-'*20+' {} '.format(col)+'-'*20)print(' 不同值个数 = {} 最大值 = {} , 最小值 = {}'.format(len(data[col].value_counts()),data[col].max(),data[col].min()))print(data[col].value_counts())

代码运行结果:

['type', '信用分', '当月旅游资讯类应用使用次数', '当月是否体育场馆消费', '当月是否到过福州山姆会员店', '当月是否景点游览', '当月是否看电影', '当月是否逛过福州仓山万达', '当月火车类应用使用次数', '当月物流快递类应用使用次数', '当月网购类应用使用次数', '当月视频播放类应用使用次数', '当月通话交往圈人数', '当月金融理财类应用使用总次数', '当月飞机类应用使用次数', '是否4G不健康客户', '是否大学生客户', '是否经常逛商场的人', '是否黑名单客户', '用户实名制是否通过核实', '用户年龄', '用户当月账户余额(元)', '用户最近一次缴费距今时长(月)', '用户编码', '用户网龄(月)', '用户话费敏感度', '用户账单当月总费用(元)', '用户近6个月平均消费值(元)', '缴费用户当前是否欠费缴费', '缴费用户最近一次缴费金额(元)', '近三个月月均商场出现次数']-------------------- type --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 01 500000 50000Name: type, dtype: int64-------------------- 信用分 --------------------不同值个数 = 278 最大值 = 719.0 , 最小值 = 422.0640.0 605635.0 597644.0 595634.0 594629.0 592... 441.01455.01713.01436.01453.01Name: 信用分, Length: 278, dtype: int64-------------------- 当月旅游资讯类应用使用次数 --------------------不同值个数 = 934 最大值 = 87681 , 最小值 = 00 612061 53402 44853 25044 2317... 674 1546 11569 11313 1735 1Name: 当月旅游资讯类应用使用次数, Length: 934, dtype: int64-------------------- 当月是否体育场馆消费 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 625271 37473Name: 当月是否体育场馆消费, dtype: int64-------------------- 当月是否到过福州山姆会员店 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 9729512705Name: 当月是否到过福州山姆会员店, dtype: int64-------------------- 当月是否景点游览 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 524541 47546Name: 当月是否景点游览, dtype: int64-------------------- 当月是否看电影 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 756201 24380Name: 当月是否看电影, dtype: int64-------------------- 当月是否逛过福州仓山万达 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 9607713923Name: 当月是否逛过福州仓山万达, dtype: int64-------------------- 当月火车类应用使用次数 --------------------不同值个数 = 180 最大值 = 775 , 最小值 = 00950071 15422 12283 4644 330... 147 1234 1212 1170 192 1Name: 当月火车类应用使用次数, Length: 180, dtype: int64-------------------- 当月物流快递类应用使用次数 --------------------不同值个数 = 239 最大值 = 8235 , 最小值 = 00985341 1462 1273 774 72... 477 1114 1286 1625 1191 1Name: 当月物流快递类应用使用次数, Length: 239, dtype: int64-------------------- 当月网购类应用使用次数 --------------------不同值个数 = 8382 最大值 = 417536 , 最小值 = 00 159371 1284296148373688... 10844 16746 16385 12940 18785 1Name: 当月网购类应用使用次数, Length: 8382, dtype: int64-------------------- 当月视频播放类应用使用次数 --------------------不同值个数 = 16067 最大值 = 1382227 , 最小值 = 00 173551 15112 141838434828... 11365 160477 142036 119497 149528 1Name: 当月视频播放类应用使用次数, Length: 16067, dtype: int64-------------------- 当月通话交往圈人数 --------------------不同值个数 = 554 最大值 = 1906 , 最小值 = 1161762141747131737151718111711... 652 1486 1550 11318 11151 1Name: 当月通话交往圈人数, Length: 554, dtype: int64-------------------- 当月金融理财类应用使用总次数 --------------------不同值个数 = 7232 最大值 = 496238 , 最小值 = 00 183631 21582 16203 10804957... 9180 15082 16902 121394 120714 1Name: 当月金融理财类应用使用总次数, Length: 7232, dtype: int64-------------------- 当月飞机类应用使用次数 --------------------不同值个数 = 209 最大值 = 5856 , 最小值 = 00 986321 122796290889... 298 1150 11174 1233 1631Name: 当月飞机类应用使用次数, Length: 209, dtype: int64-------------------- 是否4G不健康客户 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 9113118869Name: 是否4G不健康客户, dtype: int64-------------------- 是否大学生客户 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 996381362Name: 是否大学生客户, dtype: int64-------------------- 是否经常逛商场的人 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 669281 33072Name: 是否经常逛商场的人, dtype: int64-------------------- 是否黑名单客户 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 9515014850Name: 是否黑名单客户, dtype: int64-------------------- 用户实名制是否通过核实 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 01 991240876Name: 用户实名制是否通过核实, dtype: int64-------------------- 用户年龄 --------------------不同值个数 = 88 最大值 = 111 , 最小值 = 0294255364227314168284062304021... 13 1111 1105 1100 191 1Name: 用户年龄, Length: 88, dtype: int64-------------------- 用户当月账户余额(元) --------------------不同值个数 = 316 最大值 = 109090 , 最小值 = 1050 800930 784740 777720 748060 6662... 5280 115270 13100 12140 14290 1Name: 用户当月账户余额(元), Length: 316, dtype: int64-------------------- 用户最近一次缴费距今时长(月) --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 01 701420 29858Name: 用户最近一次缴费距今时长(月), dtype: int64-------------------- 用户编码 --------------------不同值个数 = 100000 最大值 = ffffebe8f3a74834b51e122d76a9d41a , 最小值 = 00011b2d787242499b8683f0e72ec5a2cb1833d8de1641feb17c5d90cf6c83fb 1138dab4ccd2f48f9b1aae72b0c14d101 1ebc74c5d15b748f394dba5eca80e9ffb 1704d0c39c9ee48f88299f9c269b432a1 1c84346fc602a4913846d9ce29689be18 1..5a39734f0a61416b9661fa19123606ad 133e02edbfe2e49a79f7f00c0df69bf1a 1eab1e711168746e183f3870611cd66aa 1c54fb03a8dad497a884764a109164ba1 14cf641c938bd442994f554e9eb047ad4 1Name: 用户编码, Length: 100000, dtype: int64-------------------- 用户网龄(月) --------------------不同值个数 = 283 最大值 = 288 , 最小值 = 15128071141611208103110927... 3 3287 2284 2281 1280 1Name: 用户网龄(月), Length: 283, dtype: int64-------------------- 用户话费敏感度 --------------------不同值个数 = 6 最大值 = 5 , 最小值 = 04 298385 210112 206223 20578179130 38Name: 用户话费敏感度, dtype: int64-------------------- 用户账单当月总费用(元) --------------------不同值个数 = 16597 最大值 = 2117.01 , 最小值 = 0.018.00227438.00181678.00141858.00134298.001250... 96.35 1198.21 1166.79 1247.56 143.44 1Name: 用户账单当月总费用(元), Length: 16597, dtype: int64-------------------- 用户近6个月平均消费值(元) --------------------不同值个数 = 22520 最大值 = 1792.74 , 最小值 = 0.018.0041038.0019118.0115440.0014388.00120... 12.86 1251.781229.921211.331290.201Name: 用户近6个月平均消费值(元), Length: 22520, dtype: int64-------------------- 缴费用户当前是否欠费缴费 --------------------不同值个数 = 2 最大值 = 1 , 最小值 = 00 9481715183Name: 缴费用户当前是否欠费缴费, dtype: int64-------------------- 缴费用户最近一次缴费金额(元) --------------------不同值个数 = 532 最大值 = 1000.0 , 最小值 = 0.00.002935799.802228449.902106629.9411740199.605189... 60.14 133.49 128.17 1100.99 15.601Name: 缴费用户最近一次缴费金额(元), Length: 532, dtype: int64-------------------- 近三个月月均商场出现次数 --------------------不同值个数 = 93 最大值 = 92 , 最小值 = 0020755176072573592479134190... 5729658290562886528553285Name: 近三个月月均商场出现次数, Length: 93, dtype: int64

还好特征不多,不然这个就得慢慢看了,通过数据情况我们可以得到这些结论:

是否 相关的特征基本就只有 0 或 1,其他没有了

比如:当月是否景点游览、当月是否看电影、是否大学生客户是否大学生客户:大学生客户有 362个是否4G不健康客户 :是不健康的客户 8869个是否黑名单客户:黑名单用户有 4850个实名制通过 :876个未通过用户年龄:最大的是 111,最小的是0 , 0 用户应该是 脏数据用户话费敏感度 : 一共6个等级用户账单当月总费用:为 0 的数据也有,可能是脏数据,直方图来观看一下用户近6个月平均消费值(元):这个也同样有 0 的数据,也有可能是 脏数据

代码讲解(特征+算法)

上述是代码探索方面的内容,我们依旧先参考别人的代码来看下他们是如何思考的,然后我们再提出一些问题和我们的看法。

# 关键特征被fillna 0 了 这里还原回来data.loc[data['用户年龄'] == 0, '用户年龄'] = Nonedata.loc[data['用户年龄'] > 100, '用户年龄'] = Nonedata.loc[data['用户话费敏感度'] == 0, '用户话费敏感度'] = Nonedata.loc[data['用户近6个月平均消费值(元)'] == 0, '用户近6个月平均消费值(元)'] = None# 特征 名称 转换一下data.rename(columns={'用户编码': 'id', '信用分': 'score'}, inplace=True)origin_bool_feature = ['当月是否体育场馆消费', '当月是否景点游览', '当月是否看电影', '当月是否到过福州山姆会员店', '当月是否逛过福州仓山万达','缴费用户当前是否欠费缴费', '是否经常逛商场的人', '是否大学生客户', '是否4G不健康客户', '是否黑名单客户','用户最近一次缴费距今时长(月)', '用户实名制是否通过核实']origin_num_feature = ['用户话费敏感度', '用户年龄', '近三个月月均商场出现次数', '当月火车类应用使用次数', '当月飞机类应用使用次数','当月物流快递类应用使用次数', '用户当月账户余额(元)', '用户网龄(月)', '缴费用户最近一次缴费金额(元)','当月通话交往圈人数', '当月旅游资讯类应用使用次数', '当月金融理财类应用使用总次数', '当月网购类应用使用次数','当月视频播放类应用使用次数', '用户账单当月总费用(元)', '用户近6个月平均消费值(元)']count_feature_list = []## 重点看下这些特征,把特征值的count 新增为一列,简单的一个代码就搞定了,map作用还挺大的for i in ['用户近6个月平均消费值(元)', '用户账单当月总费用(元)', '缴费用户最近一次缴费金额(元)']:count_feature_list.append('count_' + i)data['count_' + i] = data[i].map(data[i].value_counts())# 业务特征 - 话费特征: # 1、5个月的话费 # 2、当月账单 - 平均账单 # 3、用户最近一次缴费/ 当月账单金额data['five_all'] = data['用户近6个月平均消费值(元)'] * data['用户网龄(月)'].apply(lambda x: min(x, 6)) - data['用户账单当月总费用(元)']data['fee_del_mean'] = data['用户账单当月总费用(元)'] - data['用户近6个月平均消费值(元)']data['fee_remain_now'] = data['缴费用户最近一次缴费金额(元)'] / data['用户账单当月总费用(元)']# 把一些统计次数的特征 收纳为一个特征,但是这里没有 '近三个月月均商场出现次数' 这个特征,可能是时间维度的问题data['次数'] = data[['当月网购类应用使用次数', '当月物流快递类应用使用次数', '当月金融理财类应用使用总次数','当月视频播放类应用使用次数', '当月飞机类应用使用次数', '当月火车类应用使用次数', '当月旅游资讯类应用使用次数']].sum(axis=1)## 算次数占比,有一些的特征的占比情况,for col in ['当月金融理财类应用使用总次数', '当月旅游资讯类应用使用次数']: # 这两个比较积极向上一点data[col + '_百分比'] = data[col] / data['次数']## 除以12 得到年限data['regist_month'] = data['用户网龄(月)'] % 12# 不知道这个是干嘛的 ,感觉好像是算出 一些 loss比较大的idlgb_model = lgb.LGBMRegressor(num_leaves=32, reg_alpha=0., reg_lambda=0.01, objective='mse', metric='mae',max_depth=-1, learning_rate=0.01, min_child_samples=50,n_estimators=15000, subsample=0.7, colsample_bytree=0.45, subsample_freq=5,)# ab_id 是去除的200个样本的id。是由5折预测出来的结果的loss最大的200个构成。也可以将这200个数据权重设置0.01(线下好像更好了。没机会试了)ab_id = []# 设置样本权重data['temp_label'] = data['score']# 这里设置为None 而不是删除该数据,因为删除的话,线下一定是提升的,对于线上而言,异常数据依旧存在,所以应该关注在训练集无异常,而测试集有异常下的处理效果data['sample_weight'] = data['temp_label'] + 200data['sample_weight'] = data['sample_weight'] / data['sample_weight'].mean()# 方案1 ,不训练data.loc[data.id.isin(ab_id), 'temp_label'] = None# 方案2,样本权重设置低一点data.loc[data.id.isin(ab_id), 'sample_weight'] = 0.01# 感谢大佬分享的参数ctb_params = {'n_estimators': 10000,'learning_rate': 0.02,'random_seed': 4590,'reg_lambda': 0.08,'subsample': 0.7,'bootstrap_type': 'Bernoulli','boosting_type': 'Plain','one_hot_max_size': 10,'rsm': 0.5,'leaf_estimation_iterations': 5,'use_best_model': True,'max_depth': 6,'verbose': -1,'thread_count': 4}ctb_model = ctb.CatBoostRegressor(**ctb_params)

上述代码有点多,帮大家总结一下:

将用户年龄 、用户话费敏感度、用户近6个月平均消费值(元) 一些脏数据置位None用户近6个月平均消费值(元)’, ‘用户账单当月总费用(元)’, '缴费用户最近一次缴费金额(元) :这些指标统计次数,并新增count特征新增话费特征: 1、5个月的话费 2、当月账单 - 平均账单 3、用户最近一次缴费/ 当月账单金额将一些次数相关的特征收拢为一个特征,所有次数相加作为这一个特征的特征值当月金融理财类应用使用总次数’, '当月旅游资讯类应用使用次数 :这两个特征的占比情况用户网龄(月) 除以 12 得到 年限设置了一个样本权重:用来表明样本的重要性,但是其实是对误差较大的样本较小的权重,其他的样本较大的权重,不是每一个样本一个权重。相当于将样本分两类,两个样本权重值。

这里我要改一下,使用lightgbm 来训练模型,评价指标值metrics=‘rmse’ ,代码如下:

# 把 测试数据集拿出来训练data_train = data.drop('id', 1)df_train = data_train.loc[data['type'] == 1]y_train = data.loc[data['type'] == 1]['score']print(df_train.shape)print(y_train.shape)params = {'boosting_type': 'gbdt', 'objective': 'regression', 'learning_rate': 0.005, 'num_leaves': 80, 'max_depth': 7,'min_data_in_leaf': 20,'subsample': 1, 'colsample_bytree': 0.7, }data_train = lgb.Dataset(df_train, y_train, silent=True)cv_results = lgb.cv(params, data_train, num_boost_round=10000, nfold=5, stratified=False, shuffle=True, metrics='rmse',early_stopping_rounds=50, verbose_eval=100, show_stdv=True)print('best n_estimators:', len(cv_results['rmse-mean']))print('best cv score:', cv_results['rmse-mean'][-1])

看下部分实验结果吧:

[100]cv_agg's rmse: 26.6712 + 0.10326[200]cv_agg's rmse: 17.0392 + 0.0632588[300]cv_agg's rmse: 11.1587 + 0.0420691[400]cv_agg's rmse: 7.5608 + 0.0307922[500]cv_agg's rmse: 5.26283 + 0.0275422[600]cv_agg's rmse: 3.84734 + 0.0265683[9000]cv_agg's rmse: 0.669732 + 0.0136983[9100]cv_agg's rmse: 0.669402 + 0.0136558[9200]cv_agg's rmse: 0.669015 + 0.0135673[9300]cv_agg's rmse: 0.668788 + 0.0136241[9400]cv_agg's rmse: 0.668525 + 0.0136477[9500]cv_agg's rmse: 0.668247 + 0.0136263[9600]cv_agg's rmse: 0.667934 + 0.0136192[9700]cv_agg's rmse: 0.667742 + 0.0135973[9800]cv_agg's rmse: 0.667451 + 0.0135567[9900]cv_agg's rmse: 0.667144 + 0.0135732[10000]cv_agg's rmse: 0.666852 + 0.0135611best n_estimators: 10000best cv score: 0.6668517639542803

我的问题

1、为什么要把脏数据、离散样本特征值置位None?

比如用户年龄,完全可以拆分 年龄段来做一个新特征。

2、置位None的特征是否合适?

意思就是换个模型,这样的值能不能被训练,估计不行吧,我个人认为还是都是数值化比较好,这样换模型比较好,

3、代码跟 参考博客里的PPT 对比起来差别还是挺大的,

可能代码精简了很多,只是一部分代码,但重点是思考问题的方式,根据对比赛、数据集的理解,加上实验,得到的一些结论。

参考博客

消费者人群画像-信用智能评分Top1

消费者人群画像—信用智能评分

如果觉得《消费者人群画像—信用智能评分 :信用分预测》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。