最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

《Lending Club—構(gòu)建貸款違約預(yù)測模型》點評

2020-07-19 15:05 作者:python風(fēng)控模型  | 我要投稿

python金融風(fēng)控評分卡模型和數(shù)據(jù)分析微專業(yè)課:http://dwz.date/b9vv

up主金融微專業(yè)課

博主介紹: 持牌照消費金融模型專家,和中科院,中科大教授保持長期項目合作;和同盾,聚信立等外部數(shù)據(jù)源公司有項目對接。熟悉消費金融場景業(yè)務(wù),線上線下業(yè)務(wù),包括現(xiàn)金貸,商品貸,醫(yī)美,反欺詐,汽車金融等等。模型項目200+,擅長Python機(jī)器學(xué)習(xí)建模,對于變量篩選,衍生變量構(gòu)造,變量缺失率高,正負(fù)樣本不平衡,共線性高,多算法比較,調(diào)參等疑難問題有良好解決方法。

之前看到一篇不錯文章《lendingclub-構(gòu)建貸款違約預(yù)測模型》,分享給各位同學(xué)。原文鏈接如下https://blog.csdn.net/arsenal0435/article/details/80446829。此文章總結(jié)整體構(gòu)建思路不錯,但每個環(huán)節(jié)都還有改善地方。例如特征篩選時,是否使用標(biāo)準(zhǔn)化方法縮放數(shù)據(jù)要看算法和最終驗證結(jié)果。熱編碼方法hot-coding是一種分類數(shù)據(jù)預(yù)處理方法,但并非最優(yōu),且熱編碼后數(shù)據(jù)擴(kuò)張多個維度,極大占用內(nèi)存。

算法方面,邏輯回歸在數(shù)據(jù)預(yù)處理,特別是woe分箱需要耗費大量時間和精力。目前woe分箱方法有卡方分箱,kmean分箱,樹分箱,但沒有統(tǒng)一標(biāo)準(zhǔn)方法。一般腳本自動分箱后,最好人為檢查一下,再做做粗分箱微調(diào)。

模型驗證結(jié)果來看,auc=0.66,效果也很一般,模型還有提升空間?;煜仃嘑1分?jǐn)?shù),sensitivity,precision等結(jié)果很奇怪,都是0.66。仔細(xì)觀察,是博主用了smote方法處理非平衡數(shù)據(jù),把正負(fù)樣本5:5開。

SMOTE方法來對正負(fù)樣本比例設(shè)定不是5:5這么簡單,5:5只是一個純理想化模型訓(xùn)練狀態(tài),但實際模型表現(xiàn)不一定最好。

另外grid_search網(wǎng)格調(diào)參方法對于lendingclub數(shù)據(jù)來說,速度太慢。lendingclub超過12萬數(shù)據(jù),grid_search網(wǎng)格調(diào)參會消耗大量時間。

缺失數(shù)據(jù)處理方面,woe分箱會把缺失數(shù)據(jù)分為一箱,不用再單獨用平均數(shù),中位數(shù),或眾數(shù)來填充缺失數(shù)據(jù),這顯得畫蛇添足。很有很多細(xì)節(jié)就不一一點評了。

總之文章整體結(jié)構(gòu)還是不錯,只是機(jī)器學(xué)習(xí)是一門非常專業(yè)學(xué)科,細(xì)分很多領(lǐng)域。歡迎各位同學(xué)訪問我的教學(xué)主頁學(xué)習(xí):http://dwz.date/bwes


文章具體內(nèi)容如下:

1.本項目需解決的問題

????本項目通過利用P2P平臺Lending Club的貸款數(shù)據(jù),進(jìn)行機(jī)器學(xué)習(xí),構(gòu)建貸款違約預(yù)測模型,對新增貸款申請人進(jìn)行預(yù)測是否會違約,從而決定是否放款。


2.建模思路

????以下為本次項目的工作流程。


3.場景解析

? ? 貸款申請人向Lending Club平臺申請貸款時,Lending Club平臺通過線上或線下讓客戶填寫貸款申請表,收集客戶的基本信息,這里包括申請人的年齡、性別、婚姻狀況、學(xué)歷、貸款金額、申請人財產(chǎn)情況等信息,通常來說還會借助第三方平臺如征信機(jī)構(gòu)或FICO等機(jī)構(gòu)的信息。通過這些信息屬性來做線性回歸 ,生成預(yù)測模型,Lending Club平臺可以通過預(yù)測判斷貸款申請是否會違約,從而決定是否向申請人發(fā)放貸款。


1)首先,我們的場景是通過用戶的歷史行為(如歷史數(shù)據(jù)的多維特征和貸款狀態(tài)是否違約)來訓(xùn)練模型,通過這個模型對新增的貸款人“是否具有償還能力,是否具有償債意愿”進(jìn)行分析,預(yù)測貸款申請人是否會發(fā)生違約貸款。這是一個監(jiān)督學(xué)習(xí)的場景,因為已知了特征以及貸款狀態(tài)是否違約(目標(biāo)列),我們判定貸款申請人是否違約是一個二元分類問題,可以通過一個分類算法來處理,這里選用邏輯斯蒂回歸(Logistic Regression)。


2)觀察數(shù)據(jù)集發(fā)現(xiàn)部分?jǐn)?shù)據(jù)是半結(jié)構(gòu)化數(shù)據(jù),需要進(jìn)行特征抽象。

? ? 現(xiàn)對該業(yè)務(wù)場景進(jìn)行總結(jié)如下:

? ? 根據(jù)歷史記錄數(shù)據(jù)學(xué)習(xí)并對貸款是否違約進(jìn)行預(yù)測,監(jiān)督學(xué)習(xí)場景,選擇邏輯斯蒂回歸(Logistic Regression)算法。

數(shù)據(jù)為半結(jié)構(gòu)化數(shù)據(jù),需要進(jìn)行特征抽象。


4.數(shù)據(jù)預(yù)處理(Pre-Processing Data)

? ? ?本次項目數(shù)據(jù)集來源于Lending Club Statistics,具體為2018年第一季Lending Club平臺發(fā)生借貸的業(yè)務(wù)數(shù)據(jù)。

?數(shù)據(jù)預(yù)覽


查看每列屬性缺失值的比例

check_null = data.isnull().sum().sort_values(ascending=False)/float(len(data))?

print(check_null[check_null > 0.2]) # 查看缺失比例大于20%的屬性。


? ? 從上面信息可以發(fā)現(xiàn),本次數(shù)據(jù)集缺失值較多的屬性對我們模型預(yù)測意義不大,例如id和member_id以及url等。因此,我們直接刪除這些沒有意義且缺失值較多的屬性。此外,如果缺失值對屬性來說是有意義的,還得細(xì)分缺失值對應(yīng)的屬性是數(shù)值型變量或是分類類型變量。

thresh_count = len(data)*0.4 # 設(shè)定閥值

data = data.dropna(thresh=thresh_count, axis=1) #若某一列數(shù)據(jù)缺失的數(shù)量超過閥值就會被刪除

再將處理后的數(shù)據(jù)轉(zhuǎn)化為csv

data.to_csv('loans_2018q1_ml.csv', index = False)

loans = pd.read_csv('loans_2018q1_ml.csv')?

loans.dtypes.value_counts() # 分類統(tǒng)計數(shù)據(jù)類型


loans.shape

(107866, 103)

同值化處理???

????如果一個變量大部分的觀測都是相同的特征,那么這個特征或者輸入變量就是無法用來區(qū)分目標(biāo)時間。

loans = loans.loc[:,loans.apply(pd.Series.nunique) != 1]

loans.shape

(107866, 96)

缺失值處理——分類變量? ?

objectColumns = loans.select_dtypes(include=["object"]).columns

loans[objectColumns].isnull().sum().sort_values(ascending=False)



loans[objectColumns]

loans['int_rate'] = loans['int_rate'].str.rstrip('%').astype('float')

loans['revol_util'] = loans['revol_util'].str.rstrip('%').astype('float')

objectColumns = loans.select_dtypes(include=["object"]).columns

? 我們可以調(diào)用missingno庫來快速評估數(shù)據(jù)缺失的情況。

msno.matrix(loans[objectColumns]) ?# 缺失值可視化


?從圖中可以直觀看出變量“l(fā)ast_pymnt_d”、“emp_title”、“emp_length”缺失值較多。

????這里我們先用‘unknown’來填充。

objectColumns = loans.select_dtypes(include=["object"]).columns

loans[objectColumns] = loans[objectColumns].fillna("Unknown")

缺失值處理——數(shù)值變量

numColumns = loans.select_dtypes(include=[np.number]).columns

pd.set_option('display.max_columns', len(numColumns))

loans[numColumns].tail()


loans.drop([107864, 107865], inplace =True)

這里使用可sklearn的Preprocessing模塊,參數(shù)strategy選用most_frequent,采用眾數(shù)插補(bǔ)的方法填充缺失值


imr = Imputer(missing_values='NaN', strategy='most_frequent', axis=0)? #? axis=0? 針對列來處理

imr = imr.fit(loans[numColumns])

loans[numColumns] = imr.transform(loans[numColumns])

?這樣缺失值就已經(jīng)處理完。



數(shù)據(jù)過濾

print(objectColumns)


????將以上重復(fù)或?qū)?gòu)建預(yù)測模型沒有意義的屬性進(jìn)行刪除。

drop_list = ['sub_grade', 'emp_title', 'issue_d', 'title', 'zip_code', 'addr_state', 'earliest_cr_line',

? ? ? ?'initial_list_status', 'last_pymnt_d', 'next_pymnt_d', 'last_credit_pull_d', 'disbursement_method']

loans.drop(drop_list, axis=1, inplace=True)

loans.select_dtypes(include = ['object']).shape

(107866, 8)


5.特征工程(Feature Engineering)

特征衍生

? ? Lending Club平臺中,"installment"代表貸款每月分期的金額,我們將'annual_inc'除以12個月獲得貸款申請人的月收入金額,然后再把"installment"(月負(fù)債)與('annual_inc'/12)(月收入)相除生成新的特征'installment_feat',新特征'installment_feat'代表客戶每月還款支出占月收入的比,'installment_feat'的值越大,意味著貸款人的償債壓力越大,違約的可能性越大。

loans['installment_feat'] = loans['installment'] / ((loans['annual_inc']+1) / 12)


特征抽象(Feature Abstraction)

def coding(col, codeDict):

? ? colCoded = pd.Series(col, copy=True)

? ? for key, value in codeDict.items():

? ? ? ? colCoded.replace(key, value, inplace=True)

? ? return colCoded

#把貸款狀態(tài)LoanStatus編碼為違約=1, 正常=0:

loans["loan_status"] = coding(loans["loan_status"], {'Current':0,'Issued':0,'Fully Paid':0,'In Grace Period':1,'Late (31-120 days)':1,'Late (16-30 days)':1,'Charged Off':1})

print( '\nAfter Coding:')

pd.value_counts(loans["loan_status"])


貸款狀態(tài)可視化

loans.select_dtypes(include=["object"]).head()


?首先,我們對變量“emp_length”、"grade"進(jìn)行特征抽象化。

# 有序特征的映射

mapping_dict = {

? ? "emp_length": {

? ? ? ? "10+ years": 10,

? ? ? ? "9 years": 9,

? ? ? ? "8 years": 8,

? ? ? ? "7 years": 7,

? ? ? ? "6 years": 6,

? ? ? ? "5 years": 5,

? ? ? ? "4 years": 4,

? ? ? ? "3 years": 3,

? ? ? ? "2 years": 2,

? ? ? ? "1 year": 1,

? ? ? ? "< 1 year": 0,

? ? ? ? "Unknown": 0

? ? },

? ? "grade":{

? ? ? ? "A": 1,

? ? ? ? "B": 2,

? ? ? ? "C": 3,

? ? ? ? "D": 4,

? ? ? ? "E": 5,

? ? ? ? "F": 6,

? ? ? ? "G": 7

? ? }

}

loans = loans.replace(mapping_dict)?

loans[['emp_length','grade']].head()?


?再對剩余特征進(jìn)行One-hot編碼。

n_columns = ["home_ownership", "verification_status", "application_type","purpose", "term"]?

dummy_df = pd.get_dummies(loans[n_columns]) # 用get_dummies進(jìn)行one hot編碼

loans = pd.concat([loans, dummy_df], axis=1) #當(dāng)axis = 1的時候,concat就是行對齊,然后將不同列名稱的兩張表合并

?再清除掉原來的屬性。

loans = loans.drop(n_columns, axis=1)

loans.info()


? ? 這樣,就已經(jīng)將所有類型為object的變量作了轉(zhuǎn)化。

col = loans.select_dtypes(include=['int64','float64']).columns

col = col.drop('loan_status') #剔除目標(biāo)變量

loans_ml_df = loans? # 復(fù)制數(shù)據(jù)至變量loans_ml_df

特征縮放(Feature Scaling)

????我們采用的是標(biāo)準(zhǔn)化的方法,調(diào)用scikit-learn模塊preprocessing的子模塊StandardScaler。

sc =StandardScaler()? # 初始化縮放器

loans_ml_df[col] =sc.fit_transform(loans_ml_df[col])? #對數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化


特征選擇(Feature Selecting)

????目的:首先,優(yōu)先選擇與目標(biāo)相關(guān)性較高的特征;其次,去除不相關(guān)特征可以降低學(xué)習(xí)的難度。

#構(gòu)建X特征變量和Y目標(biāo)變量

x_feature = list(loans_ml_df.columns)

x_feature.remove('loan_status')

x_val = loans_ml_df[x_feature]

y_val = loans_ml_df['loan_status']

len(x_feature) # 查看初始特征集合的數(shù)量

103

????首先,選出與目標(biāo)變量相關(guān)性較高的特征。這里采用的是Wrapper方法,通過暴力的遞歸特征消除 (Recursive Feature Elimination)方法篩選30個與目標(biāo)變量相關(guān)性最強(qiáng)的特征,逐步剔除特征從而達(dá)到首次降維,自變量從103個降到30個。


# 建立邏輯回歸分類器

model = LogisticRegression()

# 建立遞歸特征消除篩選器

rfe = RFE(model, 30) #通過遞歸選擇特征,選擇30個特征

rfe = rfe.fit(x_val, y_val)

# 打印篩選結(jié)果

print(rfe.n_features_)

print(rfe.estimator_ )

print(rfe.support_)

print(rfe.ranking_) #ranking 為 1代表被選中,其他則未被代表未被選中


  1. col_filter = x_val.columns[rfe.support_] #通過布爾值篩選首次降維后的變量

  2. col_filter

Filter

?在第一次降維的基礎(chǔ)上,通過皮爾森相關(guān)性圖譜找出冗余特征并將其剔除;同時,可以通過相關(guān)性圖譜進(jìn)一步引導(dǎo)我們選擇特征的方向。

colormap = plt.cm.viridis

plt.figure(figsize=(12,12))

plt.title('Pearson Correlation of Features', y=1.05, size=15)

sns.heatmap(loans_ml_df[col_filter].corr(),linewidths=0.1,vmax=1.0, square=True, cmap=colormap, linecolor='white', annot=True)


drop_col = ['funded_amnt', 'funded_amnt_inv', 'out_prncp', 'out_prncp_inv', 'total_pymnt_inv', 'total_rec_prncp',

? ? ? ? ? ?'num_actv_rev_tl', 'num_rev_tl_bal_gt_0', 'home_ownership_RENT', 'application_type_Joint App',

? ? ? ? ? ? 'term_ 60 months', 'purpose_debt_consolidation', 'verification_status_Source Verified', 'home_ownership_OWN',?

? ? ? ? ? ? ?'verification_status_Verified',]

col_new = col_filter.drop(drop_col) #剔除冗余特征


len(col_new) ?# 特征子集包含的變量從30個降維至15個。

15

Embedded

? ? 下面需要對特征的權(quán)重有一個正確的評判和排序,可以通過特征重要性排序來挖掘哪些變量是比較重要的,降低學(xué)習(xí)難度,最終達(dá)到優(yōu)化模型計算的目的。這里,我們采用的是隨機(jī)森林算法判定特征的重要性,工程實現(xiàn)方式采用scikit-learn的featureimportances 的方法。


names = loans_ml_df[col_new].columns

clf=RandomForestClassifier(n_estimators=10,random_state=123) #構(gòu)建分類隨機(jī)森林分類器

clf.fit(x_val[col_new], y_val) #對自變量和因變量進(jìn)行擬合

for feature in zip(names, clf.feature_importances_):

? ? print(feature)


plt.style.use('ggplot')

?

## feature importances 可視化##

importances = clf.feature_importances_

feat_names = names

indices = np.argsort(importances)[::-1]

fig = plt.figure(figsize=(20,6))

plt.title("Feature importances by RandomTreeClassifier")

plt.bar(range(len(indices)), importances[indices], color='lightblue',? align="center")

plt.step(range(len(indices)), np.cumsum(importances[indices]), where='mid', label='Cumulative')

plt.xticks(range(len(indices)), feat_names[indices], rotation='vertical',fontsize=14)

plt.xlim([-1, len(indices)])

plt.show()

?

# 下圖是根據(jù)特征在特征子集中的相對重要性繪制的排序圖,這些特征經(jīng)過特征縮放后,其特征重要性的和為1.0。

# 由下圖我們可以得出的結(jié)論:基于決策樹的計算,特征子集上最具判別效果的特征是“total_pymnt”。


6.模型訓(xùn)練

處理樣本不均衡

? ? 前面已提到,目標(biāo)變量“l(fā)oans_status”正常和違約兩種類別的數(shù)量差別較大,會對模型學(xué)習(xí)造成困擾。我們采用過采樣的方法來處理樣本不均衡問題,具體操作使用的是SMOTE(Synthetic Minority Oversampling Technique),SMOET的基本原理是:采樣最鄰近算法,計算出每個少數(shù)類樣本的K個近鄰,從K個近鄰中隨機(jī)挑選N個樣本進(jìn)行隨機(jī)線性插值,構(gòu)造新的少數(shù)樣本,同時將新樣本與原數(shù)據(jù)合成,產(chǎn)生新的訓(xùn)練集。

# 構(gòu)建自變量和因變量

X = loans_ml_df[col_new]

y = loans_ml_df["loan_status"]

?

n_sample = y.shape[0]

n_pos_sample = y[y == 0].shape[0]

n_neg_sample = y[y == 1].shape[0]

print('樣本個數(shù):{}; 正樣本占{:.2%}; 負(fù)樣本占{:.2%}'.format(n_sample,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?n_pos_sample / n_sample,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?n_neg_sample / n_sample))

print('特征維數(shù):', X.shape[1])

# 處理不平衡數(shù)據(jù)


sm = SMOTE(random_state=42)? ? # 處理過采樣的方法

X, y = sm.fit_sample(X, y)

print('通過SMOTE方法平衡正負(fù)樣本后')

n_sample = y.shape[0]

n_pos_sample = y[y == 0].shape[0]

n_neg_sample = y[y == 1].shape[0]

print('樣本個數(shù):{}; 正樣本占{:.2%}; 負(fù)樣本占{:.2%}'.format(n_sample,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?n_pos_sample / n_sample,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?n_neg_sample / n_sample))


構(gòu)建分類器訓(xùn)練

? ? 本次項目我們采用交叉驗證法劃分?jǐn)?shù)據(jù)集,將數(shù)據(jù)劃分為3部分:訓(xùn)練集(training set)、驗證集(validation set)和測試集(test set)。讓模型在訓(xùn)練集進(jìn)行學(xué)習(xí),在驗證集上進(jìn)行參數(shù)調(diào)優(yōu),最后使用測試集數(shù)據(jù)評估模型的性能。


? ? 模型調(diào)優(yōu)我們采用網(wǎng)格搜索調(diào)優(yōu)參數(shù)(grid search),通過構(gòu)建參數(shù)候選集合,然后網(wǎng)格搜索會窮舉各種參數(shù)組合,根據(jù)設(shè)定評定的評分機(jī)制找到最好的那一組設(shè)置。

構(gòu)建分類器訓(xùn)練

? ? 本次項目我們采用交叉驗證法劃分?jǐn)?shù)據(jù)集,將數(shù)據(jù)劃分為3部分:訓(xùn)練集(training set)、驗證集(validation set)和測試集(test set)。讓模型在訓(xùn)練集進(jìn)行學(xué)習(xí),在驗證集上進(jìn)行參數(shù)調(diào)優(yōu),最后使用測試集數(shù)據(jù)評估模型的性能。


? ? 模型調(diào)優(yōu)我們采用網(wǎng)格搜索調(diào)優(yōu)參數(shù)(grid search),通過構(gòu)建參數(shù)候選集合,然后網(wǎng)格搜索會窮舉各種參數(shù)組合,根據(jù)設(shè)定評定的評分機(jī)制找到最好的那一組設(shè)置。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 0) # random_state = 0 每次切分的數(shù)據(jù)都一樣

# 構(gòu)建參數(shù)組合

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

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

# C:Inverse of regularization strength; must be a positive float. Like in support vector machines, smaller values specify stronger regularization.

grid_search = GridSearchCV(LogisticRegression(),? param_grid, cv=10) # 確定模型LogisticRegression,和參數(shù)組合param_grid ,cv指定10折

grid_search.fit(X_train, y_train) # 使用訓(xùn)練集學(xué)習(xí)算法


print("Best parameters: {}".format(grid_search.best_params_))

print("Best cross-validation score: {:.5f}".format(grid_search.best_score_))


print("Best estimator:\n{}".format(grid_search.best_estimator_)) # grid_search.best_estimator_ 返回模型以及他的所有參數(shù)(包含最優(yōu)參數(shù))

現(xiàn)在使用經(jīng)過訓(xùn)練和調(diào)優(yōu)后的模型在測試集上測試。

y_pred = grid_search.predict(X_test)

print("Test set accuracy score: {:.5f}".format(accuracy_score(y_test, y_pred,)))

Test set accuracy score: 0.66064

print(classification_report(y_test, y_pred))


  1. roc_auc = roc_auc_score(y_test, y_pred)

  2. print("Area under the ROC curve : %f" % roc_auc)

Area under the ROC curve : 0.660654

總結(jié)

????最后結(jié)果不太理想,實際工作中還要做特征分箱處理,計算IV值和WOE編碼也是需要的。模型評估方面也有不足,這為以后的工作提供了些經(jīng)驗。


up主教學(xué)主頁 ?

https://study.163.com/provider/400000000398149/index.htm?share=2&shareId=400000000398149


up主教學(xué)主頁


《Lending Club—構(gòu)建貸款違約預(yù)測模型》點評的評論 (共 條)

分享到微博請遵守國家法律
葫芦岛市| 纳雍县| 淮滨县| 会同县| 重庆市| 廉江市| 礼泉县| 夏津县| 东至县| 南漳县| 万山特区| 白沙| 巴东县| 台江县| 仁怀市| 航空| 固阳县| 陆丰市| 曲松县| 景德镇市| 辽宁省| 赤峰市| 景德镇市| 勃利县| 英超| 新和县| 屏东县| 铜陵市| 吉木萨尔县| 忻州市| 万全县| 杭锦旗| 兴义市| 临桂县| 双辽市| 楚雄市| 文安县| 蒙阴县| 拉萨市| 松江区| 迁安市|