用户贷款逾期预测(The Predict of User's loan Overdue)

Contents

一、背景

这是一份关于用户借还贷款数据,以用户是否逾期为目标,先进行简单的预测。

二、任务分析

  • 首先,由于数据中存在缺失值,因此需要对缺失值数据进行预处理。
  • 其次,对明显与模型无关的特征进行删除。
  • 然后,采用逻辑回归模型进行模型训练。
  • 之后准备好尝试更多不同的机器学习模型,在这里不调参。

三 原始数据

数据:金融贷款数据。
任务:我们要做的是预测贷款用户是否会逾期,
标签说明:表格中,status 是标签:0 表示未逾期,1 表示逾期。

四、数据预处理

一共 4754 行,89 列(除去首行、首列),属于低样本,需要注意过拟合。

  1. 直接删除,对模型影响不大的数据及特征,比如固定的个人信息
    • 列:custid、trade_no、bank_card_no、id_name、source
    • 行:删除很多项特征缺失的用户信息
  2. 特征转换:特征student_feature列缺失值太多,基本占据一半,经分析,其包含 1、NA、2 三个参数,NA占据缺失NA转为0,2 转为 0(2 只有 2 个)
  3. 几个需考虑的因素
    城市:境外0,一线 1,二线 2,三线 3,四线 4,NA及其他
  4. 现阶段不进行处理而直接删除的列:
    比如时间 first_transaction_time,latest_query_time,loans_latest_time

五、代码实现

1、调包、导入数据以及数据替换

# coding=utf-8

"""1. 导包"""
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import f1_score,r2_score

"""2. 读取数据"""
dataset = pd.read_csv('./data/data.csv',encoding='gbk')

"""3. 数据处理"""
# 删除固定信息列
dataset = dataset.drop(["custid","trade_no","bank_card_no","id_name","first_transaction_time","latest_query_time","loans_latest_time","source"],axis=1)
# 对于sstudent_feature列,我们进行NAN转成0,2转为0
# 缺失值填充
dataset["student_feature"] = dataset["student_feature"].fillna(0)
# 2替换为0
dataset["student_feature"] = dataset["student_feature"].replace([2],[0])

# 针对城市列'reg_preference_for_trad',进行数据替换
dataset["reg_preference_for_trad"] = dataset["reg_preference_for_trad"].replace("一线城市", "1")
dataset["reg_preference_for_trad"] = dataset["reg_preference_for_trad"].replace("二线城市", "2")
dataset["reg_preference_for_trad"] = dataset["reg_preference_for_trad"].replace("三线城市", "3")
dataset["reg_preference_for_trad"] = dataset["reg_preference_for_trad"].replace("其他城市", "4")
dataset["reg_preference_for_trad"] = dataset["reg_preference_for_trad"].replace("境外", "0")

# 将object类型转成folat
dataset = dataset.convert_objects(convert_numeric=True)

2、填充缺失值

# 填充其他空值
# 使用均值进行填充
# dataset.fillna(dataset.mean(), inplace=True)
# 使用众数进行填充
dataset = dataset.fillna(0) # 使用 0 替换所有 NaN 的值
col = dataset.columns.tolist()[1:]

def missing(df, columns):
    """
    使用众数填充缺失值
    df[i].mode()[0] 获取众数第一个值
    """
    col = columns
    for i in col:
        df[i].fillna(df[i].mode()[0], inplace=True)
        df[i] = df[i].astype('float')


missing(dataset, col)

3、数据划分

X = dataset.drop(["status"],axis=1)
Y = dataset["status"]

# 数据按正常的2、8划分
X_train, X_test, y_train, y_test = train_test_split(X, Y,test_size=0.2, random_state=666)
# not enough values to unpack (expected 4, got 2)

4、数据归一化

from sklearn.preprocessing import minmax_scale
# minmax_scale归一化,缩放到0-1
X_train = minmax_scale(X_train)
X_test =  minmax_scale(X_test)
# Input contains NaN, infinity or a value too large for dtype('float64').

5、逻辑回归模型训练

log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
y_predict = log_reg.predict(X_test)

6、输出结果

print("predict:",log_reg.score(X_test, y_test))
print("f1_score:",f1_score(y_test, y_predict))
predict: 0.772870662461
f1_score: 0.341463414634

7、模型选择

from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import LinearSVC
from sklearn import svm
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import cross_val_score

models = [
    RandomForestClassifier(n_estimators=200, max_depth=3, random_state=0),
    LinearSVC(),
    svm.SVC(),
    MultinomialNB(),
    LogisticRegression(random_state=0),
]
CV = 5
cv_df = pd.DataFrame(index=range(CV * len(models)))
entries = []
for model in models:
  model_name = model.__class__.__name__
  accuracies = cross_val_score(model, X_train, y_train, scoring='accuracy', cv=CV)
  for fold_idx, accuracy in enumerate(accuracies):
    entries.append((model_name, fold_idx, accuracy))
cv_df = pd.DataFrame(entries, columns=['model_name', 'fold_idx', 'accuracy'])
cv_df.groupby('model_name').accuracy.mean()
model_name
LinearSVC                 0.791998   
LogisticRegression        0.794891   
MultinomialNB             0.764133  
RandomForestClassifier    0.776754  
SVC                       0.752827  
Name: accuracy, dtype: float64  

六、遇到的问题

1、对特征工程的分析不够深入,在特征选择上还可以更详细更优化。
2、在用均值填充NAN时,进行归一化出现了 Input contains NaN, infinity or a value too large for dtype(‘float64’),是因为填充时未考虑数据类型,有部分空值未被填充。

  1. 仅进行简单的模型选择,未进行调参

七、小结

这个做得比较浅,对特征的分析很基础,并且不是特别清楚业务,模型训练也很简单,算是一个入门教程吧!


转载请注明:yezuolin的博客 » 点击阅读原文