任务:信用风险用户识别
赛题分析:监督二分类任务
比赛链接:DC竞赛-大数据竞赛平台
数据:
数据集共分为训练数据集、初赛测试数据集。
训练数据集中的文件包含:
黑白样本标签(0/1):train_label.csv,共47782条数据。
脱敏后的用户基础信息:train_base.csv,共47782条数据。
脱敏后的用户操作信息:train_op.csv,共2774988条数据。
脱敏后的用户交易信息:train_trans.csv,共591266条数据。
初赛测试数据集包含:
脱敏后的用户基础信息:test_a_base.csv,共24315条数据。
脱敏后的用户操作信息:test_a_op.csv,共1109432条数据。
脱敏后的用户交易信息:test_a_trans.csv,共147870条数据
评分标准:
本次比赛采用auc对结果进行评分,评分代码示例:
from sklearn.metrics import roc_auc_score
y_true = [1, 0, 1, 1]
y_pred = [1,0, 1, 0]
score = roc_auc_score(y_true, y_pred)
代码
给了3个表,但我只用上了train_base这个表来做。
用机器学习实现
载入数据:
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
train_label= pd.read_csv(r"E:\tianchi\翼支付金融选手下载的文件\训练集\train_label.csv")
train_base= pd.read_csv(r"E:\tianchi\翼支付金融选手下载的文件\训练集\train_base.csv")
test_a_base = pd.read_csv(r"E:\tianchi\翼支付金融选手下载的文件\初赛测试集\test_a_base.csv")
将训练集和测试集的数据合起来一起处理特征
all_df=pd.concat([train_base,test_a_base],axis=0)
数据特征的处理
数据经过脱敏处理之后,发现数值型的特征,如:年龄,处理后仅保留大小关系,为某一区间的整数。按照区间分段了,所以要按照类别特征处理。
先将数值型特征转换成为类别型特征,然后再一起进行label编码。(没做one_hot编码,是因为数object特征太多了,one_hot之后应该会维度爆炸,不敢做,怕崩。)
category=[ 'sex','provider', 'level', 'verified', 'regist_type', 'agreement1', 'agreement2', 'agreement3', 'agreement4', 'province', 'city',
'balance', 'balance_avg', 'balance1', 'balance1_avg', 'balance2', 'balance2_avg', 'service3', 'service3_level', 'product1_amount',
'product2_amount', 'product3_amount', 'product4_amount', 'product5_amount', 'product6_amount']#类别特征,由于类别特征是通过文字给定的,将其进行再编码。
number=['age','using_time','card_a_cnt','card_b_cnt','card_c_cnt','card_b_cnt','op1_cnt','op2_cnt','service1_cnt','service1_amt','service2_cnt',
'agreement_total','acc_count','login_cnt_period1','login_cnt_period2','ip_cnt','login_cnt_avg','login_days_cnt','product7_cnt',
'product7_fail_cnt']
for col in number:
all_df[col] = all_df[col].astype(str)
s = category+number
from sklearn.preprocessing import LabelEncoder
for col in s:
label= LabelEncoder()
all_df[col]=label.fit_transform(all_df[col].astype(str))#将训练集测试集放一起,一起编码
test_a_base[col]=label.transform(test_a_base[col].astype(str))
分割数据
训练集和测试集合在一起特征处理之后就分割开来。至于为什么是47782,可以前面在把数据合起来之前查看原本训练集、测试集的大小:train_base.shape,test_a_base.shape.
dummy_train_df = all_df.iloc[:47782]#训练集
dummy_test_df = all_df.iloc[47782:]#测试集
这个数据集的目标标签和数据特征是分开存储的,而且user的顺序不一样,所以可以通过merge函数使得训练集的label与训练集的特征对应上。
dummy_train_df= pd.merge(train_label,dummy_train_df, on='user')
#由于训练集的label与训练集特征不对应,通过该函数将其对应上
将训练集取一部当作验证集。而且,把user特征列丢弃。
from sklearn.model_selection import train_test_split
s=dummy_train_df.columns
train_set,val_set,y_train,y_val=train_test_split(dummy_train_df[s[2:]],dummy_train_df[s[1]],test_size=0.2,random_state = 42)#划分验证集
准备训练模型
from sklearn import metrics
# 结果衡量
def print_metrics(true_values, predicted_values):
print ("Accuracy: ", metrics.accuracy_score(true_values, predicted_values))
print ("AUC: ", metrics.roc_auc_score(true_values, predicted_values))
print ("Confusion Matrix: ", + metrics.confusion_matrix(true_values, predicted_values))
print (metrics.classification_report(true_values, predicted_values))
# 拟合分类器
def classify(classifier_class, train_input, train_targets):
classifier_object = classifier_class()
classifier_object.fit(train_input, train_targets)
return classifier_object
选择随机森林分类器:
from sklearn.ensemble import RandomForestClassifier
classifier = classify(RandomForestClassifier, train_set, y_train)
predictions = classifier.predict(val_set)
print_metrics(y_val, predictions)
得到结果:
可见AUC:0.52246
预测
predictions = classifier.predict(test_set)
将结果按照指定形式存储:
import numpy as np
result = pd.DataFrame({'user':test_user, 'prob':predictions.astype(np.int32)})
submit=result.sort_values("user")
submit.to_csv("submit_ML.csv", index=False)
用深度学习实现
载入需要的库
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import sklearn
import pandas as pd
import os
import sys
import time
import tensorflow as tf
from tensorflow import keras
print(tf.__version__)
for model in mpl, np, pd, sklearn, tf.keras:
print(model.__name__,model.__version__)
数据处理的地方与前面机器学习的一样:
train_label= pd.read_csv(r"E:\tianchi\翼支付金融选手下载的文件\训练集\train_label.csv")
train_base= pd.read_csv(r"E:\tianchi\翼支付金融选手下载的文件\训练集\train_base.csv")
test_a_base = pd.read_csv(r"E:\tianchi\翼支付金融选手下载的文件\初赛测试集\test_a_base.csv")
all_df=pd.concat([train_base,test_a_base],axis=0)
category=[ 'sex','provider', 'level', 'verified', 'regist_type', 'agreement1', 'agreement2', 'agreement3', 'agreement4', 'province', 'city',
'balance', 'balance_avg', 'balance1', 'balance1_avg', 'balance2', 'balance2_avg', 'service3', 'service3_level', 'product1_amount',
'product2_amount', 'product3_amount', 'product4_amount', 'product5_amount', 'product6_amount']#类别特征,由于类别特征是通过文字给定的,将其进行再编码,这是这个baseline做的其中一个工作。
number=['age','using_time','card_a_cnt','card_b_cnt','card_c_cnt','card_b_cnt','op1_cnt','op2_cnt','service1_cnt','service1_amt','service2_cnt',
'agreement_total','acc_count','login_cnt_period1','login_cnt_period2','ip_cnt','login_cnt_avg','login_days_cnt','product7_cnt',
'product7_fail_cnt']
for col in number:
all_df[col] = all_df[col].astype(str)
s = category+number
from sklearn.preprocessing import LabelEncoder
for col in s:
label= LabelEncoder()
all_df[col]=label.fit_transform(all_df[col].astype(str))#将训练集测试集放一起,一起编码
test_a_base[col]=label.transform(test_a_base[col].astype(str))
dummy_train_df = all_df.iloc[:47782]#训练集
dummy_test_df = all_df.iloc[47782:]#测试集
dummy_train_df= pd.merge(train_label,dummy_train_df, on='user')#由于训练集的label与训练集特征不对应,通过该函数将其对应上
from sklearn.model_selection import train_test_split
s=dummy_train_df.columns
train_set,val_set,y_train,y_val=train_test_split(dummy_train_df[s[2:]],dummy_train_df[s[1]],test_size=0.2,random_state = 42)#划分验证集
标准化训练集和验证集
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
train_set = scaler.fit_transform(train_set)
val_set = scaler.transform(val_set)
搭建模型:
input_shape的值通过train_set.shape查看。
model = keras.models.Sequential([
keras.layers.Dense(50, activation="relu", input_shape=(45,)),
keras.layers.BatchNormalization(),
keras.layers.Dense(25, activation="relu", kernel_initializer="he_normal"),
keras.layers.BatchNormalization(),
keras.layers.Dense(2,activation="softmax")
])
编译模型
model.compile(loss="sparse_categorical_crossentropy",
optimizer="adam",
metrics=["accuracy"])
将标签转为numpy类型
y_train=y_train.values
y_val = y_val.values
训练模型
history = model.fit(train_set, y_train, epochs=30,
validation_data=(val_set, y_val))
用验证集来预测:
y_pred = model.predict_classes(val_set)
衡量模型的函数
from sklearn import metrics
# 结果衡量
def print_metrics(true_values, predicted_values):
print ("Accuracy: ", metrics.accuracy_score(true_values, predicted_values))
print ("AUC: ", metrics.roc_auc_score(true_values, predicted_values))
print ("Confusion Matrix: ", + metrics.confusion_matrix(true_values, predicted_values))
print (metrics.classification_report(true_values, predicted_values))
得到结果:
print_metrics(y_val, y_pred)
可见AUC比前面得到的要高那么一丁点。
测试集处理
test_user = test_a_base['user']
test_set=test_a_base.drop('user',axis=1)
test_set = scaler.transform(test_set)
预测得到分类
y_pred = model.predict_classes(test_set)
如果想得到概率:
y_proba = model.predict(test_set)
将结果按照指定形式存储:
import numpy as np
result = pd.DataFrame({'user':test_user, 'prob':y_pred.astype(np.int32)})
submit=result.sort_values("user")
submit.to_csv("submit_dp.csv", index=False)
总结
当然,这个结果是不满意的,auc的值太低了要想办法改进
1、机器学习方法可以尝试其他更多的模型。
2、可以采用集成的方法,进行模型融合。
3、可以用网格搜索找到模型的最优参数,这里直接喂数据,没有进行调参
4、深度学习的层级结构可以尝试多搭建,改变来训练。
5、我认为分数上不去最重要的原因是,数据特征没好好冲洗提取,只是简单的编码了而已。
6、可以结合使用所提供的另外两个表中的特征。
说了那么多,其实我都试过了,能力不足,还是上不了分。哭唧唧。
最后的最后小白陪跑真快乐。
更新
想尝试一下别人的baseline的。要用到xgb。我硬是装了几天都装不好xgboost。装到崩溃,放弃了。
后来无意中发现可以用天池实验室来做,里面有xgb。
import xgboost as xgb
params = { 'booster': 'gbtree', 'objective': 'binary:logistic', 'eval_metric': 'auc', 'min_child_weight':18, 'max_depth': 8, 'subsample': 0.75,'colsample_bytree': 0.75,
'eta': 0.001,'seed': 2020,'nthread': 36,'silent': True, }#xgboost的参数设置
train_matrix = xgb.DMatrix(train_set,y_train)
valid_matrix = xgb.DMatrix(val_set,y_val)
watchlist = [(train_matrix, 'train'),(valid_matrix, 'eval')]
model= xgb.train(params, train_matrix, num_boost_round=24000, evals=watchlist, verbose_eval=500, early_stopping_rounds=1000)#模型训练
test_user = test_a_base['user']
test_set=test_a_base.drop('user',axis=1)
testx1 = xgb.DMatrix(test_set)
out2=model.predict(testx1,ntree_limit=model.best_ntree_limit)
import numpy as np
result = pd.DataFrame({'user':test_user, 'prob':out2})
submit=result.sort_values("user")
submit.to_csv('/home/tianchi/myspace/z1.csv', index=False)
关于xgb的默认参数
xgb基本使用方法
果然分数一下子就提升了。果然比不上别人的baseline。