python数据分析实战之信用卡违约风险预测

python

文章目录

  • *       *         * 1、明确需求和目的 

    * 2、 数据收集

    * 3、数据预处理

    * * 3.1 数据整合

    * * 3.1.1 加载相关库和数据集

    * 3.1.2 主要数据集概览

    * 3.2 数据清洗

    * * 3.2.1 多余列的删除

    * 3.2.2 数据类型转换

    * 3.2.3 缺失值处理

    * 3.2.4 异常值处理

    * 3.2.5 重复值处理

    * 4、数据分析

    * * 4.1 相关系数分析

    * 5、模型训练

    * * 5.1 数据标准化

    * 5.2 使用逻辑回归训练

    * 5.3 简单优化

    * 5.4 使用随机森林训练

    * 6、总结

1、明确需求和目的

  • 现代社会,越来越多的人使用信用卡进行消费,大部分人使用信用卡之后会按时还款,但仍然有少部分人不能在约定时间进行还款,这大大的增加了银行或者金融机构的风险。
  • 本文以某金融机构的历史数据进行建模分析,对客户的还款能力进行评估,以预测新客户是否有信用卡的违约风险,从而决定是否贷款给新客户使用。
  • 本文使用AUC(ROC)作为模型的评估标准。

2、 数据收集

  • 本文使用的数据集来源于kaggle平台,主要有两份数据集。
  • application_train , application_test :训练集和测试集数据,包括每个贷款申请的信息。每笔贷款都有自己的行,并由特性SK_ID_CURR标识。训练集的TARGET 0:贷款已还清,1:贷款未还清。

3、数据预处理

3.1 数据整合

3.1.1 加载相关库和数据集

  • 使用的库主要有:pandas、numpy、matplotlib、seaborn
  • 使用的数据集:kaggle平台提供的数据集文件

    import numpy as np

import pandas as pd

import os

import matplotlib.pyplot as plt

import seaborn as sns

import warnings

warnings.filterwarnings(\'ignore\')

print(os.listdir("../input/")) # List files available

-------------------------------------------------

[\'sample_submission.csv\', \'credit_card_balance.csv\', \'installments_payments.csv\', \'HomeCredit_columns_description.csv\', \'previous_application.csv\', \'POS_CASH_balance.csv\', \'bureau_balance.csv\', \'application_test.csv\', \'bureau.csv\', \'application_train.csv\']

3.1.2 主要数据集概览

首先看一下训练集数据:

    # Training data

app_train = pd.read_csv(\'../input/application_train.csv\')

print(\'Training data shape: \', app_train.shape)

--------------------------------------

Training data shape: (307511, 122)

app_train.head()

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200507235136393.png?x-oss-

process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjM4NDc4NA==,size_16,color_FFFFFF,t_70#pic_center)

从上面可以看出,训练集数据有122个特征,307511条数据。

再来看一下测试集数据:

    # Testing data 

app_test = pd.read_csv(\'../input/application_test.csv\')

print(\'Testing data shape: \', app_test.shape)

---------------------------------------------

Testing data shape: (48744, 121)

app_test.head()

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200507235148946.png?x-oss-

process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjM4NDc4NA==,size_16,color_FFFFFF,t_70#pic_center)

从上面可以看出,测试集数据有121个特征,48744条数据,相比训练集,少了一个特征

TARGET,即我们需要预测的目标值(0表示贷款按时偿还,1表示贷款未按时偿还。)。

检查一下TARGET列的分布,看看每一类贷款的数量:

    app_train[\'TARGET\'].value_counts()

----------------------------------------

0 282686

1 24825

Name: TARGET, dtype: int64

可以看出按时还款的类别明显要比未按时还款的类别多, 属于样本不均衡的问题,后续可以考虑使用权重法或采样法等办法来进行解决。

转化成图形更直观的对比一下:

    app_train[\'TARGET\'].astype(int).plot.hist()

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200507235203694.png?x-oss-

process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjM4NDc4NA==,size_16,color_FFFFFF,t_70#pic_center)

3.2 数据清洗

3.2.1 多余列的删除

首先删除空白值超过一半的列 :

    app_train = app_train.dropna(thresh=len(app_train) / 2 , axis=1) 

定义一个函数,看一下剩余数据的缺失值情况:

    # Function to calculate missing values by column# Funct 

def missing_values_table(df):

# Total missing values

mis_val = df.isnull().sum()

# Percentage of missing values

mis_val_percent = 100 * df.isnull().sum() / len(df)

# Make a table with the results

mis_val_table = pd.concat([mis_val, mis_val_percent], axis=1)

# Rename the columns

mis_val_table_ren_columns = mis_val_table.rename(

columns = {0 : \'Missing Values\', 1 : \'% of Total Values\'})

# Sort the table by percentage of missing descending

mis_val_table_ren_columns = mis_val_table_ren_columns[

mis_val_table_ren_columns.iloc[:,1] != 0].sort_values(

\'% of Total Values\', ascending=False).round(1)

# Print some summary information

print ("Your selected dataframe has " + str(df.shape[1]) + " columns.\n"

"There are " + str(mis_val_table_ren_columns.shape[0]) +

" columns that have missing values.")

# Return the dataframe with missing information

return mis_val_table_ren_columns

    # Missing values statistics

missing_values = missing_values_table(app_train)

---------------------------------------------------

Your selected dataframe has 81 columns.

There are 26 columns that have missing values.

missing_values.head(10)

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200507235220671.png?x-oss-

process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjM4NDc4NA==,size_16,color_FFFFFF,t_70#pic_center)

从上面可以看出,还有好几列的值缺失将近50%,缺失比例较高,我们一并将这些列进行删除。当然,也可以选择进行缺失值填充,这里选择删除。

    drop_columns = ["FLOORSMAX_AVG","FLOORSMAX_MODE","FLOORSMAX_MEDI","YEARS_BEGINEXPLUATATION_AVG","YEARS_BEGINEXPLUATATION_MODE",

"YEARS_BEGINEXPLUATATION_MEDI","TOTALAREA_MODE","EMERGENCYSTATE_MODE"]

app_train = app_train.drop(drop_columns, axis=1)

删除了缺失值较多的列之后,还有其它列的缺失值需要处理,我们可以先进行数据类型转换,后面再统一采用填充的方式进行处理。

3.2.2 数据类型转换

先来看一下各个类型的数据有多少:

    # Number of each type of column

app_train.dtypes.value_counts()

----------------------------------

int64 41

float64 20

object 12

dtype: int64

object类型的有12个,需要将其转换成数值类型,我们先看一下它们各自的特征类别有多少:

注意 nunique 不考虑空值。

    # Number of unique classes in each object column

app_train.select_dtypes(\'object\').apply(pd.Series.nunique, axis = 0)

-------------------------------------

NAME_CONTRACT_TYPE 2

CODE_GENDER 3

FLAG_OWN_CAR 2

FLAG_OWN_REALTY 2

NAME_TYPE_SUITE 7

NAME_INCOME_TYPE 8

NAME_EDUCATION_TYPE 5

NAME_FAMILY_STATUS 6

NAME_HOUSING_TYPE 6

OCCUPATION_TYPE 18

WEEKDAY_APPR_PROCESS_START 7

ORGANIZATION_TYPE 58

dtype: int64

  • 标签编码 ( Label Encoding):它给类别一个任意的顺序。分配给每个类别的值是随机的,不反映类别的任何固有方面。所以我们在只有两个类别的时候使用标签编码。例如上面的‘NAME_CONTRACT_TYPE’等,我们就可以使用标签编码。
  • 独热编码 (One-Hot Encoding):为分类变量中的每个类别创建一个新列。当类别>2的时候,我们将使用独热编码。例如上面的‘CODE_GENDER’等。当然独热编码的缺点也很明显,就是特征可能会暴增,但我们可以使用PCA或其他降维方法来减少维数。

对于类别只有2个的特征,我们使用 Label Encoding 进行数据的转换(注意测试集也同样需要进行转换):

    from sklearn.preprocessing import LabelEncoder

# Create a label encoder object

le = LabelEncoder()

le_count = 0

# Iterate through the columns

for col in app_train:

if app_train[col].dtype == \'object\':

# If 2 or fewer unique categories

if len(list(app_train[col].unique())) <= 2:

# Train on the training data

le.fit(app_train[col])

# Transform both training and testing data

app_train[col] = le.transform(app_train[col])

app_test[col] = le.transform(app_test[col])

# Keep track of how many columns were label encoded

le_count += 1

print(\'%d columns were label encoded.\' % le_count)

-------------------------------------------------

3 columns were label encoded.

从上面可以看出3个类别全部完成了转换,接下来使用 One-Hot Encoding

进行剩余数据的转换,此处选择使用pandas的get_dummies()函数,直接映射为数值型(测试集一并进行转换):

    # one-hot encoding of categorical variables

app_train = pd.get_dummies(app_train)

app_test = pd.get_dummies(app_test)

print(\'Training Features shape: \', app_train.shape)

print(\'Testing Features shape: \', app_test.shape)

----------------------------------------------------

Training Features shape: (307511, 182)

Testing Features shape: (48744, 239)

从上面可以看出,此时测试集列数多于训练集,因为训练集删除了一些多余的列,我们对两份数据取并集,只需要处理共同拥有的列即可:

    train_labels = app_train[\'TARGET\']

# Align the training and testing data, keep only columns present in both dataframes

app_train, app_test = app_train.align(app_test, join = \'inner\', axis = 1)

# Add the target back in

app_train[\'TARGET\'] = train_labels

print(\'Training Features shape: \', app_train.shape)

print(\'Testing Features shape: \', app_test.shape)

------------------------------------------------

Training Features shape: (307511, 179)

Testing Features shape: (48744, 178)

3.2.3 缺失值处理

数据类型转换完成,我们就可以统一进行缺失值处理,可以采用中位数进行填充:

    from sklearn.preprocessing import Imputer

imputer = Imputer(strategy = \'median\')

train = app_train.drop(columns = [\'TARGET\'])

column_list = train.columns.tolist()

# fit with Training_data, fill both Training_data and Testing_data

imputer.fit(train)

train = imputer.transform(train)

test = imputer.transform(app_test)

train = pd.DataFrame(train, columns = column_list)

app_train = pd.concat([train, app_train[\'TARGET\']], axis=1)

app_test = pd.DataFrame(test, columns = column_list)

print(\'Training data shape: \', app_train.shape)

print(\'Testing data shape: \', app_test.shape)

--------------------------------------------------

Training data shape: (307511, 179)

Testing data shape: (48744, 178)

检查是否还有缺失值:

    print(app_train.isnull().sum())

print(app_test.isnull().sum())

需要注意的是,此处"SK_ID_CURR" 经过处理之后变成float类型,需要重新转换成 int类型:

    app_train["SK_ID_CURR"] = app_train["SK_ID_CURR"].astype(int)

app_test["SK_ID_CURR"] = app_test["SK_ID_CURR"].astype(int)

3.2.4 异常值处理

对年龄进行异常值检查(原始数据为天,需要除以365,并且取负数):

    (app_train[\'DAYS_BIRTH\'] / -365).describe()

-----------------------------------------------

count 307511.000000

mean 43.936973

std 11.956133

min 20.517808

25% 34.008219

50% 43.150685

75% 53.923288

max 69.120548

Name: DAYS_BIRTH, dtype: float64

看起来很正常,无异常,再看一下在职天数:

    app_train[\'DAYS_EMPLOYED\'].describe()

-----------------------------------------

count 307511.000000

mean 63815.045904

std 141275.766519

min -17912.000000

25% -2760.000000

50% -1213.000000

75% -289.000000

max 365243.000000

Name: DAYS_EMPLOYED, dtype: float64

最大值为365243天,换算成年即100年,明显不合理,属于异常值。

出于好奇,对异常客户进行分析,看看他们的违约率比其他客户高还是低。

    anom = app_train[app_train[\'DAYS_EMPLOYED\'] == 365243]

non_anom = app_train[app_train[\'DAYS_EMPLOYED\'] != 365243]

print(\'The non-anomalies default on %0.2f%% of loans\' % (100 * non_anom[\'TARGET\'].mean()))

print(\'The anomalies default on %0.2f%% of loans\' % (100 * anom[\'TARGET\'].mean()))

print(\'There are %d anomalous days of employment\' % len(anom))

-------------------------------------------------------------

The non-anomalies default on 8.66% of loans

The anomalies default on 5.40% of loans

There are 55374 anomalous days of employment

可以看到,这些异常值的客户违约率比其他客户还要低,且数量还不少。

我们需要对异常值进行处理,处理异常值取决于具体情况,没有固定的规则。最安全的方法之一就是将异常值视为缺失值处理,然后在使用算法之前填充它们。这里我们将用(np.nan)填充异常值,然后创建一个新的布尔列,指示该值是否异常。

    # Create an anomalous flag column

app_train[\'DAYS_EMPLOYED_ANOM\'] = app_train["DAYS_EMPLOYED"] == 365243

# Replace the anomalous values with nan

app_train[\'DAYS_EMPLOYED\'].replace({365243: np.nan}, inplace = True)

同样对测试集进行异常值处理:

    app_test[\'DAYS_EMPLOYED_ANOM\'] = app_test["DAYS_EMPLOYED"] == 365243

app_test["DAYS_EMPLOYED"].replace({365243: np.nan}, inplace = True)

print(\'There are %d anomalies in the test data out of %d entries\' % (app_test["DAYS_EMPLOYED_ANOM"].sum(), len(app_test)))

---------------------------------------------------

There are 9274 anomalies in the test data out of 48744 entries

使用中位数对异常值转换后的缺失值进行填充:

    from sklearn.preprocessing import Imputer

imputer = Imputer(strategy = \'median\')

train = app_train[\'DAYS_EMPLOYED\'].values.reshape(-1, 1)

imputer.fit(train)

train = imputer.transform(app_train[\'DAYS_EMPLOYED\'].values.reshape(-1, 1))

test = imputer.transform(app_test[\'DAYS_EMPLOYED\'].values.reshape(-1, 1))

app_train[\'DAYS_EMPLOYED\'] = train

app_test[\'DAYS_EMPLOYED\'] = test

print(app_train[\'DAYS_EMPLOYED\'].describe())

print(app_test[\'DAYS_EMPLOYED\'].describe())

---------------------------------------------

count 307511.000000

mean -2251.606131

std 2136.193492

min -17912.000000

25% -2760.000000

50% -1648.000000

75% -933.000000

max 0.000000

Name: DAYS_EMPLOYED, dtype: float64

count 48744.000000

mean -2319.063639

std 2102.150130

min -17463.000000

25% -2910.000000

50% -1648.000000

75% -1048.000000

max -1.000000

Name: DAYS_EMPLOYED, dtype: float64

从上面可以看出,已经没有异常值了。

3.2.5 重复值处理

看一下有没有重复值,有则直接删除:

    print(app_train.duplicated().sum())    # 查看重复值的数量

------------------------------------------

0

没有重复值,不需要进行处理。

4、数据分析

4.1 相关系数分析

使用.corr方法计算每个变量与目标之间的相关系数。

相关系数并不是表示特征“相关性”的最佳方法,但它确实让我们了解了数据中可能存在的关系。

    # Find correlations with the target and sort

correlations = app_train.corr()[\'TARGET\'].sort_values()

# Display correlations

print(\'Most Positive Correlations:\n\', correlations.tail(15))

print(\'\nMost Negative Correlations:\n\', correlations.head(15))

---------------------------------------------------------------

Most Positive Correlations:

OCCUPATION_TYPE_Laborers 0.043019

FLAG_DOCUMENT_3 0.044346

REG_CITY_NOT_LIVE_CITY 0.044395

FLAG_EMP_PHONE 0.045982

NAME_EDUCATION_TYPE_Secondary / secondary special 0.049824

REG_CITY_NOT_WORK_CITY 0.050994

DAYS_ID_PUBLISH 0.051457

CODE_GENDER_M 0.054713

DAYS_LAST_PHONE_CHANGE 0.055218

NAME_INCOME_TYPE_Working 0.057481

REGION_RATING_CLIENT 0.058899

REGION_RATING_CLIENT_W_CITY 0.060893

DAYS_EMPLOYED 0.063368

DAYS_BIRTH 0.078239

TARGET 1.000000

Name: TARGET, dtype: float64

Most Negative Correlations:

EXT_SOURCE_2 -0.160295

EXT_SOURCE_3 -0.155892

NAME_EDUCATION_TYPE_Higher education -0.056593

CODE_GENDER_F -0.054704

NAME_INCOME_TYPE_Pensioner -0.046209

DAYS_EMPLOYED_ANOM -0.045987

ORGANIZATION_TYPE_XNA -0.045987

AMT_GOODS_PRICE -0.039623

REGION_POPULATION_RELATIVE -0.037227

NAME_CONTRACT_TYPE -0.030896

AMT_CREDIT -0.030369

FLAG_DOCUMENT_6 -0.028602

NAME_HOUSING_TYPE_House / apartment -0.028555

NAME_FAMILY_STATUS_Married -0.025043

HOUR_APPR_PROCESS_START -0.024166

Name: TARGET, dtype: float64

从上面看出,和目标值有较大正相关性的有 DAYS_BIRTH 这个特征,有较大负相关性的有 EXT_SOURCE_2 和 EXT_SOURCE_3

这两个特征,可以进一步进行分析:

    plt.figure(figsize=(10, 8))

# KDE图中按时偿还的贷款

sns.kdeplot(app_train.loc[app_train[\'TARGET\'] == 0, \'DAYS_BIRTH\'] / -365, label = \'target == 0\')

# KDE图中未按时偿还的贷款

sns.kdeplot(app_train.loc[app_train[\'TARGET\'] == 1, \'DAYS_BIRTH\'] / -365, label = \'target == 1\')

plt.xlabel(\'Age (years)\')

plt.ylabel(\'Density\')

plt.title(\'Distribution of Ages\')

plt.show()

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200507235247598.png?x-oss-

process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjM4NDc4NA==,size_16,color_FFFFFF,t_70#pic_center)

target ==

1曲线向范围的较年轻端倾斜,说明随着客户年龄的增长,他们往往会更经常地按时偿还贷款。虽然这不是一个显著的相关性(-0.07相关系数),但这个变量很可能在机器学习模型中有用,因为它确实会影响目标。

对于其余两个特征,也可以进行相应的分析,并可以利用这几个特征进行特征工程的选择。(本文为简单起见,未进行特征工程)

5、模型训练

5.1 数据标准化

  • 在使用算法之前,进行 数据标准化处理,将数据集中的特征转换成相同的量纲,从而消除不同量纲对算法造成的负面影响。

    from sklearn.preprocessing import Imputer, MinMaxScaler

imputer = Imputer(strategy = \'median\')

scaler = MinMaxScaler(feature_range = [0,1])

train = app_train.drop(columns = [\'TARGET\'])

scaler.fit(train)

train = scaler.transform(train)

test = scaler.transform(app_test)

print(\'Training data shape: \', train.shape)

print(\'Testing data shape: \', test.shape)

--------------------------------------------

Training data shape: (307511, 183)

Testing data shape: (48744, 183)

5.2 使用逻辑回归训练

  • 直接使用简单的逻辑回归

    from sklearn.linear_model import LogisticRegression

log_reg = LogisticRegression()

log_reg.fit(train, train_labels)

log_reg_pred = log_reg.predict_proba(test)[:, 1]

submit = app_test[[\'SK_ID_CURR\']]

submit[\'TARGET\'] = log_reg_pred

submit.head()

submit.to_csv(\'log_reg_baseline.csv\', index = False)

提交之后,分数如下:

    Private Score:0.72683, Public Score:0.73322

  • 使用网格交叉验证计算出最佳参数的逻辑回归:

    from sklearn.linear_model import LogisticRegression

from sklearn.model_selection import GridSearchCV

param_grid = {\'C\' : [0.01,0.1,1,10,100],

\'penalty\' : [\'l1\',\'l2\']}

log_reg = LogisticRegression()

grid_search = GridSearchCV(log_reg, param_grid, scoring = \'roc_auc\', cv = 5)

grid_search.fit(train, train_labels)

# Train on the training data

log_reg_best = grid_search.best_estimator_

log_reg_pred = log_reg_best.predict_proba(test)[:, 1]

submit = app_test[[\'SK_ID_CURR\']]

submit[\'TARGET\'] = log_reg_pred

submit.head()

submit.to_csv(\'log_reg_baseline_gridsearch2.csv\', index = False)

使用交叉验证,效果有一点提升,分数如下:

    Private Score:0.72770, Public Score:0.73452

5.3 简单优化

增加领域知识特征,我们可以创建几个特性,试图捕捉我们认为对于判断客户是否会拖欠贷款可能很重要的信息。

  • CREDIT_INCOME_PERCENT: 信贷金额占客户收入的百分比
  • ANNUITY_INCOME_PERCENT: 贷款年金占客户收入的百分比
  • CREDIT_TERM: 以月为单位支付的期限(因为年金是每月到期的金额)
  • DAYS_EMPLOYED_PERCENT: 就职天数占客户年龄的百分比

    app_train_domain = app_train.copy()

app_train[\'CREDIT_INCOME_PERCENT\'] = app_train_domain[\'AMT_CREDIT\'] / app_train_domain[\'AMT_INCOME_TOTAL\']

app_train[\'ANNUITY_INCOME_PERCENT\'] = app_train_domain[\'AMT_ANNUITY\'] / app_train_domain[\'AMT_INCOME_TOTAL\']

app_train[\'CREDIT_TERM\'] = app_train_domain[\'AMT_ANNUITY\'] / app_train_domain[\'AMT_CREDIT\']

app_train[\'DAYS_EMPLOYED_PERCENT\'] = app_train_domain[\'DAYS_EMPLOYED\'] / app_train_domain[\'DAYS_BIRTH\']

测试集进行同样处理:

    app_test_domain = app_test.copy()

app_test[\'CREDIT_INCOME_PERCENT\'] = app_test_domain[\'AMT_CREDIT\'] / app_test_domain[\'AMT_INCOME_TOTAL\']

app_test[\'ANNUITY_INCOME_PERCENT\'] = app_test_domain[\'AMT_ANNUITY\'] / app_test_domain[\'AMT_INCOME_TOTAL\']

app_test[\'CREDIT_TERM\'] = app_test_domain[\'AMT_ANNUITY\'] / app_test_domain[\'AMT_CREDIT\']

app_test[\'DAYS_EMPLOYED_PERCENT\'] = app_test_domain[\'DAYS_EMPLOYED\'] / app_test_domain[\'DAYS_BIRTH\']

增加领域特征之后,再次使用简单的逻辑回归进行训练(交叉验证太耗时间,用简单的比较看看效果):

    from sklearn.linear_model import LogisticRegression

log_reg = LogisticRegression()

log_reg.fit(train, train_labels)

log_reg_pred = log_reg.predict_proba(test)[:, 1]

submit = app_test[[\'SK_ID_CURR\']]

submit[\'TARGET\'] = log_reg_pred

submit.head()

submit.to_csv(\'log_reg_baseline_domain.csv\', index = False)

增加领域特征之后,效果有一点提升,分数如下:

    Private Score:0.72805, Public Score:0.73434

5.4 使用随机森林训练

  • 增加领域特征之后,使用随机森林训练,看看效果怎么样

    from sklearn.ensemble import RandomForestClassifier

# 随机森林

random_forest = RandomForestClassifier(n_estimators = 100, random_state = 50, verbose = 1, n_jobs = -1)

random_forest.fit(train, train_labels)

predictions = random_forest.predict_proba(test)[:, 1]

submit = app_test[[\'SK_ID_CURR\']]

submit[\'TARGET\'] = predictions

submit.to_csv(\'random_forest_baseline_domain.csv\', index = False)

使用随机森林,效果比逻辑回归还要差一些:

    Private Score:0.70975, Public Score:0.70120 

6、总结

  • 本文仅仅使用一个数据集进行模型训练,并使用逻辑回归和随机森林分别预测,并通过简单优化提升了模型效果。
  • 如果进一步进行特征分析,并且使用其它数据集进行训练的话,应该会得到更好的训练模型。

以上是 python数据分析实战之信用卡违约风险预测 的全部内容, 来源链接: utcz.com/z/387611.html

回到顶部