我們將初步了解一下在Kaggle上舉辦的Home Credit Default Risk機(jī)器學(xué)習(xí)競(jìng)賽。這項(xiàng)比賽的目的是利用歷史貸款申請(qǐng)數(shù)據(jù)來(lái)預(yù)測(cè)申請(qǐng)人是否有能力償還貸款。這是一個(gè)標(biāo)準(zhǔn)的二分類(lèi)任務(wù)。
數(shù)據(jù)介紹
這些數(shù)據(jù)由Home Credit提供漏麦,這是一項(xiàng)專(zhuān)門(mén)為無(wú)銀行賬戶(hù)人群提供信貸額度(貸款)的服務(wù)耸袜。預(yù)測(cè)客戶(hù)是否會(huì)償還貸款或遇到困難是一項(xiàng)關(guān)鍵的業(yè)務(wù)需求,Home Credit在Kaggle上舉辦了這場(chǎng)比賽攀隔,看看機(jī)器學(xué)習(xí)社區(qū)可以開(kāi)發(fā)什么樣的模型來(lái)幫助他們完成這項(xiàng)任務(wù)。
有7種不同的數(shù)據(jù)來(lái)源:
- application_train/application_test:train數(shù)據(jù)和test數(shù)據(jù)栖榨,包含關(guān)于每個(gè)家庭信貸貸款申請(qǐng)的信息昆汹。每個(gè)貸款都有自己的行,并由特性SK_ID_CURR標(biāo)識(shí)婴栽。application_train中的TARGET列:0:貸款已償還满粗;1:貸款未償還。
- bureau:客戶(hù)以前從其他金融機(jī)構(gòu)取得的信用數(shù)據(jù)愚争。每個(gè)先前的貸款在bureau中都有自己的行映皆,但是申請(qǐng)數(shù)據(jù)中的一個(gè)貸款可以有多個(gè)先前的貸款挤聘。
- bureau_balance:關(guān)于之前在bureau的信用記錄的每月數(shù)據(jù)。每一行是前一個(gè)信用記錄的一個(gè)月捅彻,一個(gè)前一個(gè)信用記錄可以有多個(gè)行组去,每個(gè)月的信用記錄長(zhǎng)度對(duì)應(yīng)一個(gè)行。
- bureau_balance:關(guān)于之前在bureau的信用記錄的每月數(shù)據(jù)步淹。每一行是前一個(gè)信用記錄的一個(gè)月从隆,一個(gè)前一個(gè)信用記錄可以有多個(gè)行,每個(gè)月的信用記錄長(zhǎng)度對(duì)應(yīng)一個(gè)行缭裆。
- POS_CASH_BALANCE:關(guān)于客戶(hù)以前的銷(xiāo)售點(diǎn)或家庭信貸的現(xiàn)金貸款的每月數(shù)據(jù)键闺。每一行是前一個(gè)銷(xiāo)售點(diǎn)或現(xiàn)金貸款的一個(gè)月,而前一個(gè)貸款可以有許多行澈驼。
- credit_card_balance:關(guān)于以前的信用卡客戶(hù)使用家庭信用卡的每月數(shù)據(jù)艾杏。每一行是信用卡余額的一個(gè)月,一張信用卡可以有很多行盅藻。
- installments_payment: 以前在國(guó)內(nèi)貸款的付款歷史购桑。每一次付款都有一行,每一次未付款也有一行氏淑。
這張圖顯示了所有的數(shù)據(jù)是如何關(guān)聯(lián)的:
庫(kù)
導(dǎo)入我們接下來(lái)需要用到的庫(kù)
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
import warnings
warnings.filterwarnings('ignore')
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import MinMaxScaler, Imputer
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
讀入數(shù)據(jù)
app_train = pd.read_csv('application_train.csv')
app_test = pd.read_csv('application_test.csv')
print(app_train.shape)
print(app_test.shape)
# print(app_train.head(10)) # 查看前10行數(shù)據(jù)
輸出:
(307511, 122)
(48744, 121)
可以看出訓(xùn)練集有307511個(gè)觀(guān)察值(每個(gè)單獨(dú)的貸款)和122個(gè)特征(變量)勃蜘。
測(cè)試集要小得多,并且缺少TARGET列假残。
檢查T(mén)ARGET列的分布
TARGET是我們要預(yù)測(cè)的:0表示貸款按時(shí)償還缭贡,1表示貸款未按時(shí)償還。我們先檢查每一類(lèi)貸款的數(shù)量辉懒。
print(app_train['TARGET'].value_counts())
0 282686
1 24825
Name: TARGET, dtype: int64
app_train['TARGET'].astype(int).plot.hist()
plt.show()
這是一個(gè)類(lèi)別不平衡的問(wèn)題阳惹,我們可以很明顯的看出按時(shí)償還貸款的遠(yuǎn)遠(yuǎn)比未按時(shí)償還貸款的多。
解決方法
檢查缺失值
接下來(lái)眶俩,我們可以查看每一列中缺失值的數(shù)量和百分比莹汤。
# 按列計(jì)算缺失值
def missing_values_table(df):
# 總?cè)笔е? mis_val = df.isnull().sum()
# 缺失值百分比
mis_val_parent = 100*df.isnull().sum()/len(df)
# 用結(jié)果做一個(gè)表格
mis_val_table = pd.concat([mis_val, mis_val_parent], axis=1)
# 重命名列
mis_val_table_ren_columns = mis_val_table.rename(
columns={0: 'Missing Values', 1: '% of Total Values'}
)
# 按丟失降序排列的百分比對(duì)表進(jìn)行排序
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('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 mis_val_table_ren_columns
# 缺失值統(tǒng)計(jì)
miss_values = missing_values_table(app_train)
print(miss_values.head(11))
Your selected dataframe has 122 columns.
There are 67 columns that have missing values.
Missing Values % of Total Values
COMMONAREA_MEDI 214865 69.9
COMMONAREA_AVG 214865 69.9
COMMONAREA_MODE 214865 69.9
NONLIVINGAPARTMENTS_MEDI 213514 69.4
NONLIVINGAPARTMENTS_MODE 213514 69.4
NONLIVINGAPARTMENTS_AVG 213514 69.4
FONDKAPREMONT_MODE 210295 68.4
LIVINGAPARTMENTS_MODE 210199 68.4
LIVINGAPARTMENTS_MEDI 210199 68.4
LIVINGAPARTMENTS_AVG 210199 68.4
FLOORSMIN_MODE 208642 67.8
當(dāng)構(gòu)建機(jī)器學(xué)習(xí)模型時(shí),我們必須填充這些缺失的值颠印。又或者我們使用XGBoost之類(lèi)的模型纲岭,這些模型可以處理缺失的值。另一種選擇是刪除具有高丟失值百分比的列线罕。我們現(xiàn)在保留所有的列止潮。
列類(lèi)型
查看每種數(shù)據(jù)類(lèi)型的列數(shù)
# 每種類(lèi)型列的數(shù)目
print(app_train.dtypes.value_counts())
float64 65
int64 41
object 16
dtype: int64
我們可以看出有16列是object類(lèi)型的,我們要把這些轉(zhuǎn)為機(jī)器學(xué)習(xí)可以處理的數(shù)值型钞楼。
# 每個(gè)object列中,不重復(fù)值的數(shù)目
print(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
FONDKAPREMONT_MODE 4
HOUSETYPE_MODE 3
WALLSMATERIAL_MODE 7
EMERGENCYSTATE_MODE 2
dtype: int64
標(biāo)簽編碼(Label Encoding)和獨(dú)熱編碼(One-Hot Encoding)
標(biāo)簽編碼:它給類(lèi)別一個(gè)任意的順序喇闸。分配給每個(gè)類(lèi)別的值是隨機(jī)的,不反映類(lèi)別的任何固有方面。所以我們?cè)谥挥袃蓚€(gè)類(lèi)別的時(shí)候使用標(biāo)簽編碼燃乍。例如上面的‘NAME_CONTRACT_TYPE’等唆樊,我們就可以使用標(biāo)簽編碼。
獨(dú)熱編碼:為分類(lèi)變量中的每個(gè)類(lèi)別創(chuàng)建一個(gè)新列橘沥。當(dāng)類(lèi)別>2的時(shí)候窗轩,我們將使用獨(dú)熱編碼夯秃。例如上面的‘CODE_GENDER’等座咆。當(dāng)然獨(dú)熱編碼的缺點(diǎn)也很明顯,就是特征可能會(huì)暴增仓洼,但我們可以使用PCA或其他降維方法來(lái)減少維數(shù)介陶。
# 創(chuàng)建一個(gè)LabelEncoder對(duì)象
le = LabelEncoder()
le_count = 0
# 標(biāo)簽編碼
for col in app_train:
if app_train[col].dtype == 'object':
if len(app_train[col].unique()) <= 2:
le.fit(app_train[col])
app_train[col] = le.transform(app_train[col])
app_test[col] = le.transform(app_test[col])
le_count += 1
print('%d columns were label encoded.' % le_count)
3 columns were label encoded.
train = pd.get_dummies(app_train)
test = pd.get_dummies(app_test)
print('Training Features shape: ', train.shape)
print('Testing Features shape: ', test.shape)
Training Features shape: (307511, 243)
Testing Features shape: (48744, 239)
調(diào)整訓(xùn)練集和測(cè)試集
在訓(xùn)練集和測(cè)試集中需要有相同的特征(列)。獨(dú)熱編碼在訓(xùn)練集中創(chuàng)建了更多的列色建,因?yàn)橛?xùn)練集中有TARGET列哺呜,而測(cè)試集中沒(méi)有。
train_labels = train['TARGET']
app_train, app_test = train.align(test, join = 'inner', axis = 1)
app_train['TARGET'] = train_labels
print('Training Features shape: ', app_train.shape)
print('Testing Features shape: ', app_test.shape)
Training Features shape: (307511, 240)
Testing Features shape: (48744, 239)
EDA
檢查異常值
print((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
看上去很正常沒(méi)有異常值
print(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天箕戳,也就是1000年某残,這明顯不對(duì),是異常值陵吸。
出于好奇玻墅,讓我們對(duì)異常客戶(hù)進(jìn)行分析壮虫,看看他們的違約率比其他客戶(hù)高還是低澳厢。
anom = train[train['DAYS_EMPLOYED'] == 365243]
non_anom = train[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
事實(shí)證明,這些異城羲疲現(xiàn)象的違約率較低剩拢。
處理異常取決于具體情況,沒(méi)有固定的規(guī)則饶唤。最安全的方法之一就是將異常設(shè)置為一個(gè)缺失的值徐伐,然后在使用算法之前填充它們。在這種情況下募狂,由于所有的異常值都是相同的呵晨,所以我們希望用相同的值來(lái)填充它們,以防所有這些貸款都有一個(gè)共同點(diǎn)熬尺。異常值似乎有一定的重要性摸屠。作為一種解決方案,我們將用非數(shù)字(np.nan)填充異常值粱哼,然后創(chuàng)建一個(gè)新的布爾列季二,指示該值是否異常。
# 創(chuàng)建一個(gè)異常標(biāo)志列
train['DAYS_EMPLOYED_ANOM'] = train['DAYS_EMPLOYED'] == 365243
# 用nan代替異常值
train['DAYS_EMPLOYED'].replace({365243: np.nan}, inplace=True)
test['DAYS_EMPLOYED_ANOM'] = test['DAYS_EMPLOYED'] == 365243
test['DAYS_EMPLOYED'].replace({365243: np.nan}, inplace=True)
print('There are %d anomalies in the test data out of %d entries' % (test["DAYS_EMPLOYED_ANOM"].sum(), len(test)))
There are 9274 anomalies in the test data out of 48744 entries
相關(guān)性
現(xiàn)在我們已經(jīng)處理了分類(lèi)變量和異常值,讓我們繼續(xù)EDA胯舷。一種嘗試和理解數(shù)據(jù)的方法是尋找特征和目標(biāo)之間的關(guān)聯(lián)刻蚯。我們可以使用.corr方法計(jì)算每個(gè)變量與目標(biāo)之間的Pearson相關(guān)系數(shù)。
相關(guān)系數(shù)并不是表示特征“相關(guān)性”的最佳方法桑嘶,但它確實(shí)讓我們了解了數(shù)據(jù)中可能存在的關(guān)系炊汹。對(duì)相關(guān)系數(shù)絕對(duì)值的一般解釋是:
- .00-.19 “very weak”
- .20-.39 “weak”
- .40-.59 “moderate”
- .60-.79 “strong”
- .80-1.0 “very strong”
# 查看與TARGET的相關(guān)系數(shù)并排序
correlations = train.corr()['TARGET'].sort_values()
# 顯示相關(guān)系數(shù)
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.074958
DAYS_BIRTH 0.078239
TARGET 1.000000
Name: TARGET, dtype: float64
Most Negative Correlations:
EXT_SOURCE_3 -0.178919
EXT_SOURCE_2 -0.160472
EXT_SOURCE_1 -0.155317
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
FLOORSMAX_AVG -0.044003
FLOORSMAX_MEDI -0.043768
FLOORSMAX_MODE -0.043226
EMERGENCYSTATE_MODE_No -0.042201
HOUSETYPE_MODE_block of flats -0.040594
AMT_GOODS_PRICE -0.039645
REGION_POPULATION_RELATIVE -0.037227
Name: TARGET, dtype: float64
年齡對(duì)還款的影響
# 找出DAYS_BIRTH和TARGET之間的相關(guān)系數(shù)
app_train['DAYS_BIRTH'] = abs(app_train['DAYS_BIRTH'])
print(app_train['DAYS_BIRTH'].corr(app_train['TARGET']))
-0.07823930830982694
隨著客戶(hù)年齡的增長(zhǎng),與目標(biāo)存在負(fù)線(xiàn)性關(guān)系逃顶,這意味著隨著客戶(hù)年齡的增長(zhǎng)讨便,他們往往會(huì)更經(jīng)常地按時(shí)償還貸款。
plt.figure(figsize=(10, 8))
# KDE圖中按時(shí)償還的貸款
sns.kdeplot(app_train.loc[app_train['TARGET'] == 0, 'DAYS_BIRTH'] / -365, label = 'target == 0')
# KDE圖中未按時(shí)償還的貸款
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()
target == 1曲線(xiàn)向范圍的較年輕端傾斜以政。雖然這不是一個(gè)顯著的相關(guān)性(-0.07相關(guān)系數(shù))霸褒,但這個(gè)變量很可能在機(jī)器學(xué)習(xí)模型中有用,因?yàn)樗_實(shí)會(huì)影響目標(biāo)盈蛮。
外部來(lái)源
與目標(biāo)負(fù)相關(guān)性最強(qiáng)的三個(gè)變量是EXT_SOURCE_1废菱、EXT_SOURCE_2和EXT_SOURCE_3。根據(jù)文檔抖誉,這些特征表示“來(lái)自外部數(shù)據(jù)源的標(biāo)準(zhǔn)化得分”殊轴。
首先,我們可以顯示EXT_SOURCE特性與目標(biāo)以及彼此之間的關(guān)聯(lián)袒炉。
# 提取EXT_SOURCE變量并顯示相關(guān)性
ext_data = app_train[['TARGET', 'EXT_SOURCE_1', 'EXT_SOURCE_2', 'EXT_SOURCE_3', 'DAYS_BIRTH']]
ext_data_corrs = ext_data.corr()
print(ext_data_corrs)
TARGET EXT_SOURCE_1 EXT_SOURCE_2 EXT_SOURCE_3 DAYS_BIRTH
TARGET 1.000000 -0.155317 -0.160472 -0.178919 0.078239
EXT_SOURCE_1 -0.155317 1.000000 0.213982 0.186846 -0.600610
EXT_SOURCE_2 -0.160472 0.213982 1.000000 0.109167 -0.091996
EXT_SOURCE_3 -0.178919 0.186846 0.109167 1.000000 -0.205478
DAYS_BIRTH 0.078239 -0.600610 -0.091996 -0.205478 1.000000
這三個(gè)EXT_SOURCE特性都與目標(biāo)負(fù)相關(guān)旁理,這表明隨著EXT_SOURCE值的增加,客戶(hù)端更有可能償還貸款梳杏。我們還可以看到DAYS_BIRTH與EXT_SOURCE_1呈正相關(guān)韧拒,這表明這個(gè)評(píng)分中的一個(gè)因素可能是客戶(hù)端年齡。
特征工程
多項(xiàng)式特征
關(guān)于多項(xiàng)式特征可以看這篇文章
# 為多項(xiàng)式特征創(chuàng)建一個(gè)新的dataframe
poly_features = app_train[['EXT_SOURCE_1', 'EXT_SOURCE_2', 'EXT_SOURCE_3', 'DAYS_BIRTH', 'TARGET']]
poly_features_test = app_test[['EXT_SOURCE_1', 'EXT_SOURCE_2', 'EXT_SOURCE_3', 'DAYS_BIRTH']]
imputer = Imputer(strategy='median')
poly_target = poly_features['TARGET']
poly_features = poly_features.drop(columns=['TARGET'])
poly_features = imputer.fit_transform(poly_features)
poly_features_test = imputer.transform(poly_features_test)
poly_transformer = PolynomialFeatures(degree=3)
poly_transformer.fit(poly_features)
poly_features = poly_transformer.transform(poly_features)
poly_features_test = poly_transformer.transform(poly_features_test)
print('Polynomial Features shape: ', poly_features.shape)
print(poly_transformer.get_feature_names(input_features=['EXT_SOURCE_1', 'EXT_SOURCE_2', 'EXT_SOURCE_3', 'DAYS_BIRTH'])
[:15])
Polynomial Features shape: (307511, 35)
['1',
'EXT_SOURCE_1',
'EXT_SOURCE_2',
'EXT_SOURCE_3',
'DAYS_BIRTH',
'EXT_SOURCE_1^2',
'EXT_SOURCE_1 EXT_SOURCE_2',
'EXT_SOURCE_1 EXT_SOURCE_3',
'EXT_SOURCE_1 DAYS_BIRTH',
'EXT_SOURCE_2^2',
'EXT_SOURCE_2 EXT_SOURCE_3',
'EXT_SOURCE_2 DAYS_BIRTH',
'EXT_SOURCE_3^2',
'EXT_SOURCE_3 DAYS_BIRTH',
'DAYS_BIRTH^2']
共有35個(gè)特征十性,每個(gè)特征的冪次可達(dá)3次叛溢,并有交互項(xiàng)。現(xiàn)在劲适,我們可以看到這些新特征與目標(biāo)的相關(guān)系數(shù)楷掉。
poly_features = pd.DataFrame(poly_features,
columns = poly_transformer.get_feature_names(['EXT_SOURCE_1', 'EXT_SOURCE_2',
'EXT_SOURCE_3', 'DAYS_BIRTH']))
poly_features['TARGET'] = poly_target
# 找出與target的相關(guān)性
poly_corrs = poly_features.corr()['TARGET'].sort_values()
# 顯示最消極和最積極的一面
print(poly_corrs.head(10))
print(poly_corrs.tail(5))
EXT_SOURCE_2 EXT_SOURCE_3 -0.193939
EXT_SOURCE_1 EXT_SOURCE_2 EXT_SOURCE_3 -0.189605
EXT_SOURCE_2^2 EXT_SOURCE_3 -0.176428
EXT_SOURCE_2 EXT_SOURCE_3^2 -0.172282
EXT_SOURCE_1 EXT_SOURCE_2 -0.166625
EXT_SOURCE_1 EXT_SOURCE_3 -0.164065
EXT_SOURCE_2 -0.160295
EXT_SOURCE_1 EXT_SOURCE_2^2 -0.156867
EXT_SOURCE_3 -0.155892
EXT_SOURCE_1 EXT_SOURCE_3^2 -0.150822
Name: TARGET, dtype: float64
EXT_SOURCE_1 EXT_SOURCE_2 DAYS_BIRTH 0.155891
EXT_SOURCE_2 DAYS_BIRTH 0.156873
EXT_SOURCE_2 EXT_SOURCE_3 DAYS_BIRTH 0.181283
TARGET 1.000000
1 NaN
幾個(gè)新變量與目標(biāo)的相關(guān)性(就絕對(duì)值而言)比原來(lái)的特征更大。當(dāng)我們構(gòu)建機(jī)器學(xué)習(xí)模型時(shí)霞势,我們可以嘗試使用或不使用這些特性來(lái)確定它們是否真的有助于模型的學(xué)習(xí)烹植。
我們將把這些特性添加到訓(xùn)練集和測(cè)試集中,然后評(píng)估具有和不具有這些特性的模型愕贡。在機(jī)器學(xué)習(xí)中草雕,很多時(shí)候,知道一種方法是否有效的唯一方法就是嘗試它!
poly_features_test = pd.DataFrame(poly_features_test,
columns = poly_transformer.get_feature_names(['EXT_SOURCE_1', 'EXT_SOURCE_2',
'EXT_SOURCE_3', 'DAYS_BIRTH']))
poly_features['SK_ID_CURR'] = app_train['SK_ID_CURR']
app_train_poly = app_train.merge(poly_features, on = 'SK_ID_CURR', how = 'left')
poly_features_test['SK_ID_CURR'] = app_test['SK_ID_CURR']
app_test_poly = app_test.merge(poly_features_test, on = 'SK_ID_CURR', how = 'left')
app_train_poly, app_test_poly = app_train_poly.align(app_test_poly, join = 'inner', axis = 1)
print('Training data with polynomial features shape: ', app_train_poly.shape)
print('Testing data with polynomial features shape: ', app_test_poly.shape)
Training data with polynomial features shape: (307511, 274)
Testing data with polynomial features shape: (48744, 274)
領(lǐng)域知識(shí)特征
我們可以創(chuàng)建幾個(gè)特性固以,試圖捕捉我們認(rèn)為對(duì)于判斷客戶(hù)是否會(huì)拖欠貸款可能很重要的信息墩虹。
- CREDIT_INCOME_PERCENT: 信貸金額占客戶(hù)收入的百分比
- ANNUITY_INCOME_PERCENT: 貸款年金占客戶(hù)收入的百分比
- CREDIT_TERM: 以月為單位支付的期限(因?yàn)槟杲鹗敲吭碌狡诘慕痤~)
- DAYS_EMPLOYED_PERCENT: 就職天數(shù)占客戶(hù)年齡的百分比
app_train_domain = app_train.copy()
app_test_domain = app_test.copy()
app_train_domain['CREDIT_INCOME_PERCENT'] = app_train_domain['AMT_CREDIT'] / app_train_domain['AMT_INCOME_TOTAL']
app_train_domain['ANNUITY_INCOME_PERCENT'] = app_train_domain['AMT_ANNUITY'] / app_train_domain['AMT_INCOME_TOTAL']
app_train_domain['CREDIT_TERM'] = app_train_domain['AMT_ANNUITY'] / app_train_domain['AMT_CREDIT']
app_train_domain['DAYS_EMPLOYED_PERCENT'] = app_train_domain['DAYS_EMPLOYED'] / app_train_domain['DAYS_BIRTH']
app_test_domain['CREDIT_INCOME_PERCENT'] = app_test_domain['AMT_CREDIT'] / app_test_domain['AMT_INCOME_TOTAL']
app_test_domain['ANNUITY_INCOME_PERCENT'] = app_test_domain['AMT_ANNUITY'] / app_test_domain['AMT_INCOME_TOTAL']
app_test_domain['CREDIT_TERM'] = app_test_domain['AMT_ANNUITY'] / app_test_domain['AMT_CREDIT']
app_test_domain['DAYS_EMPLOYED_PERCENT'] = app_test_domain['DAYS_EMPLOYED'] / app_test_domain['DAYS_BIRTH']
模型
Logistic Regression
# 邏輯回歸
# 從訓(xùn)練集中刪除TARGET列
if 'TARGET' in app_train:
train = app_train.drop(columns = ['TARGET'])
else:
train = app_train.copy()
features = list(train.columns)
test = app_test.copy()
# 缺失值的中值估計(jì)
imputer = Imputer(strategy='median')
# 將每個(gè)特性縮放到0-1
scaler = MinMaxScaler(feature_range=(0, 1))
imputer.fit(train)
train = imputer.transform(train)
test = imputer.transform(app_test)
scaler.fit(train)
train = scaler.transform(train)
test = scaler.transform(test)
print('Training data shape: ', train.shape)
print('Testing data shape: ', test.shape)
Training data shape: (307511, 278)
Testing data shape: (48744, 278)
現(xiàn)在這個(gè)模型已經(jīng)經(jīng)過(guò)訓(xùn)練嘱巾,我們可以用它來(lái)做預(yù)測(cè)。我們想預(yù)測(cè)不償還貸款的概率诫钓,所以我們使用predict.proba()
log_reg = LogisticRegression(C = 0.0001)
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
# 將提交文件保存到csv文件中
submit.to_csv('log_reg_baseline.csv', index=False)
提交后旬昭,分?jǐn)?shù)為0.671
Random Forest
# 隨機(jī)森林
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.csv', index = False)
提交后,分?jǐn)?shù)為0.678
總結(jié)
我們首先了解數(shù)據(jù)菌湃。然后问拘,我們執(zhí)行了一個(gè)相當(dāng)簡(jiǎn)單的EDA,試圖識(shí)別可能有助于建模的關(guān)系惧所、趨勢(shì)或異常骤坐。在此過(guò)程中,我們執(zhí)行了必要的預(yù)處理步驟纯路,比如對(duì)分類(lèi)變量進(jìn)行編碼或油、輸入缺失的值以及將特性縮放到一個(gè)范圍寞忿。然后驰唬,我們從現(xiàn)有的數(shù)據(jù)構(gòu)建新特性。最后腔彰,我們跑了兩個(gè)模型叫编。
參考文章