邏輯迴歸:信貸違規預測!
theme: smartblue
公眾號:尤而小屋
作者:Peter
編輯:Peter
大家好,我是Peter~
今天給大家帶來一篇新的kaggle資料建模文章:信貸違約預測
本文是基於一份Lendingclub上面的信貸資料,根據貸款人的歷史資料和貸款資訊,建立一個邏輯迴歸模型來預測借款人是否會償還他們的貸款。
導圖顯示本文的主要工作,其中缺失值處理和特徵工程是重點。
匯入庫
```python import numpy as np import pandas as pd
import matplotlib.pyplot as plt import seaborn as sns
import missingno as ms import plotly.express as px import plotly.graph_objs as go import plotly.figure_factory as ff from plotly.subplots import make_subplots import plotly.offline as pyo pyo.init_notebook_mode() sns.set_style('darkgrid')
from sklearn.decomposition import PCA from imblearn.over_sampling import SMOTE from sklearn.model_selection import train_test_split,cross_val_score
from sklearn.ensemble import RandomForestClassifier,AdaBoostClassifier from sklearn.svm import SVC from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.metrics import f1_score as f1 from sklearn.metrics import confusion_matrix
plt.rc('figure',figsize=(18,9))
import warnings warnings.filterwarnings("ignore") ```
資料基本資訊
資料來自 LendingClub,它是美國一家個人對個人貸款公司,總部位於加利福尼亞州舊金山,號稱是全球最大的個人對個人(p2p)借貸平臺。
檢視資料量、欄位型別等:
缺失值處理
缺失值處理是本次資料處理的一項重要工作。由於存在字元型和數值型的變數,而且這兩種型別下的資料都存在缺失值,所以在分開處理。
缺失值視覺化
In [6]:
```
4、缺失值情況
df.isnull().sum().sort_values(ascending=False) ```
Out[6]:
id 105451
hardship_start_date 105451
member_id 105451
hardship_type 105451
hardship_reason 105451
...
open_acc_6m 0
tot_cur_bal 0
tot_coll_amt 0
acc_now_delinq 0
max_bal_bc 0
Length: 137, dtype: int64
In [7]:
``` ms.bar(df,color="blue")
plt.show() ```
如果取值是1,說明是完整的欄位,沒有缺失值;可以看到還是存在很多欄位有缺失值。
刪除全部缺失欄位
1、部分欄位是全部缺失的,將它們進行刪除:
In [8]:
```
方法1:使用dropna的how引數
data.dropna(axis=1, how='all')
```
In [9]:
```
在這裡我們使用下面的【方法2】
1、檢視每個欄位的缺失值比例
isnull_col_percent = df.isnull().sum(axis=0).sort_values(ascending=False) / float(len(df)) isnull_col_percent ```
Out[9]:
id 1.0
hardship_start_date 1.0
member_id 1.0
hardship_type 1.0
hardship_reason 1.0
...
open_acc_6m 0.0
tot_cur_bal 0.0
tot_coll_amt 0.0
acc_now_delinq 0.0
max_bal_bc 0.0
Length: 137, dtype: float64
In [10]:
isnull_col_percent[:20] # 前20個
Out[10]:
id 1.000000
hardship_start_date 1.000000
member_id 1.000000
hardship_type 1.000000
hardship_reason 1.000000
hardship_status 1.000000
deferral_term 1.000000
hardship_amount 1.000000
hardship_end_date 1.000000
url 1.000000
payment_plan_start_date 1.000000
hardship_length 1.000000
hardship_dpd 1.000000
hardship_loan_status 1.000000
orig_projected_additional_accrued_interest 1.000000
hardship_payoff_balance_amount 1.000000
desc 1.000000
hardship_last_payment_amount 1.000000
sec_app_mths_since_last_major_derog 0.977866
sec_app_revol_util 0.936188
dtype: float64
在上面的結果中,比例為1的欄位就是全部缺失的(前面18個欄位),對於建模無用,我們將其刪除:
In [11]:
no_use_col = df.columns[df.isnull().all()].tolist()
no_use_col
Out[11]:
['id',
'member_id',
'url',
'desc',
'hardship_type',
'hardship_reason',
'hardship_status',
'deferral_term',
'hardship_amount',
'hardship_start_date',
'hardship_end_date',
'payment_plan_start_date',
'hardship_length',
'hardship_dpd',
'hardship_loan_status',
'orig_projected_additional_accrued_interest',
'hardship_payoff_balance_amount',
'hardship_last_payment_amount']
In [12]:
df.drop(no_use_col,axis=1,inplace=True)
In [13]:
df.shape # 137-18 = 119,成功刪除18個屬性
Out[13]:
(105451, 119)
刪除缺失值在30%以上的欄位
2、有些欄位是部分缺失值;缺失量過大也會對建模造成影響。
在這裡我們設定刪除缺失值在30%(可以設定其他值)以上的欄位(按照列的方向來統計)
In [14]:
```
最大的缺失值比例高達97.78%
df.isnull().sum(axis=0).sort_values(ascending=False) / float(len(df)) ```
Out[14]:
sec_app_mths_since_last_major_derog 0.977866
sec_app_revol_util 0.936188
revol_bal_joint 0.935458
sec_app_earliest_cr_line 0.935458
sec_app_inq_last_6mths 0.935458
...
total_rec_int 0.000000
total_rec_prncp 0.000000
total_pymnt_inv 0.000000
total_pymnt 0.000000
hardship_flag 0.000000
Length: 119, dtype: float64
In [15]:
``` thresh = len(df)*0.3 # 閥值(缺失值數量)
某列資料缺失的數量超過閥值就被刪除
df.dropna(thresh=thresh, axis=1, inplace=True) ```
In [16]:
df.shape
Out[16]:
(105451, 102)
In [17]:
df.isnull().sum(axis=0).sort_values(ascending=False) / float(len(df))
Out[17]:
mths_since_recent_revol_delinq 0.648405
mths_since_last_delinq 0.484765
il_util 0.126884
mths_since_recent_inq 0.113313
emp_title 0.064314
...
total_pymnt_inv 0.000000
total_pymnt 0.000000
out_prncp_inv 0.000000
out_prncp 0.000000
hardship_flag 0.000000
Length: 102, dtype: float64
新資料(刪除缺失值)
新資料缺失值視覺化
In [18]:
``` ms.bar(df,color="blue")
plt.show() ```
和之前的對比,發現缺失值的欄位少了很多
處理後的資料量:只剩下102個欄位
In [19]:
df.shape
Out[19]:
(105451, 102)
欄位型別統計
In [20]:
df.dtypes.value_counts()
Out[20]:
int64 54
float64 25
object 23
dtype: int64
唯一值欄位
3、某些欄位的取值是唯一的,比如全部是0,這樣的欄位對於建模也是無用的,我們要將這些欄位進行刪除。
首先找出這些欄位:使用Pandas中的nunique函式來確定取值是否唯一。
In [21]:
nunique_data = df.apply(pd.Series.nunique) != 1 # 不唯一的欄位
nunique_data
Out[21]:
loan_amnt True
funded_amnt True
funded_amnt_inv True
term True
int_rate True
...
tot_hi_cred_lim True
total_bal_ex_mort True
total_bc_limit True
total_il_high_credit_limit True
hardship_flag False
Length: 102, dtype: bool
In [22]:
```
df1:刪除唯一值欄位後的資料
df1 = df.loc[:, nunique_data] df1.shape ```
Out[22]:
(105451, 97)
欄位從102變成了97,說明還是存在5個取值唯一的欄位
In [23]:
```
再次檢視欄位型別
df1.dtypes.value_counts() ```
Out[23]:
int64 51
float64 25
object 21
dtype: int64
缺失值處理-分型別變數
針對分型別變數(取值為字串型別)的缺失值處理,一般是採用型別編碼、獨熱碼、因子化等操作
In [24]:
object_df = df1.select_dtypes(include="object")
object_df.columns
Out[24]:
Index(['term', 'int_rate', 'grade', 'sub_grade', 'emp_title', 'emp_length',
'home_ownership', 'verification_status', 'issue_d', 'loan_status',
'purpose', 'title', 'zip_code', 'addr_state', 'earliest_cr_line',
'revol_util', 'initial_list_status', 'last_pymnt_d', 'next_pymnt_d',
'last_credit_pull_d', 'application_type'],
dtype='object')
比如欄位grade的取值是真實的Object型別:
In [25]:
```
grade
df1["grade"].value_counts() ```
Out[25]:
C 36880
B 31301
A 17898
D 12015
E 4847
F 1725
G 785
Name: grade, dtype: int64
下面出現的欄位雖然是object型別,但是實際上行它們的取值仍存在一定的大小關係
In [26]:
```
int_rate
df1["int_rate"].value_counts() ```
Out[26]:
16.02% 4956
5.32% 4365
15.05% 4195
14.08% 4168
12.74% 4155
...
30.75% 119
30.49% 113
30.74% 98
21.49% 89
6.00% 4
Name: int_rate, Length: 65, dtype: int64
In [27]:
```
revol_util
df1["revol_util"].value_counts() ```
Out[27]:
0% 468
60% 244
64% 230
50% 227
53% 220
...
116.20% 1
110.10% 1
106.10% 1
125% 1
113% 1
Name: revol_util, Length: 1076, dtype: int64
分型別變數轉成數值
- 將百分比的資料轉成浮點型:
In [28]:
```
將右側的%去掉,同時強制轉成float型別
df1["int_rate"] = df1["int_rate"].str.rstrip("%").astype("float") df1["revol_util"] = df1["revol_util"].str.rstrip("%").astype("float") ```
- 關於年份的處理:轉成數值,並且10+直接用10代替,<1的部分直接用0代替:
In [29]:
```
emp_length
df1["emp_length"].value_counts() ```
Out[29]:
10+ years 35438
2 years 9914
< 1 year 9542
3 years 8495
1 year 7034
4 years 6453
5 years 6382
6 years 4526
7 years 3847
9 years 3828
8 years 3295
Name: emp_length, dtype: int64
In [30]:
df1["emp_length"].isnull().sum() # 存在缺失值
Out[30]:
6697
現將缺失值填充為<1 year
:
In [31]:
df1["emp_length"] = df1["emp_length"].fillna("< 1 year")
In [32]:
```
1、先將year或years去掉
df1["emp_length"] = df1["emp_length"].apply(lambda x: x.split("y")[0].rstrip(" ")) ```
In [33]:
df1["emp_length"].value_counts()
Out[33]:
10+ 35438
< 1 16239
2 9914
3 8495
1 7034
4 6453
5 6382
6 4526
7 3847
9 3828
8 3295
Name: emp_length, dtype: int64
In [34]:
```
2、轉成數值型
df1["emp_length"] = df1["emp_length"].apply(lambda x: "10" if x == "10+" else x) df1["emp_length"] = df1["emp_length"].str.replace("< 1","0")
df1["emp_length"] = df1["emp_length"].astype("float") ```
In [35]:
df1["emp_length"].value_counts()
Out[35]:
python
10.0 35438
0.0 16239
2.0 9914
3.0 8495
1.0 7034
4.0 6453
5.0 6382
6.0 4526
7.0 3847
9.0 3828
8.0 3295
Name: emp_length, dtype: int64
分型別變數視覺化
In [36]:
object_df = df1.select_dtypes(include="object")
object_df.columns
Out[36]:
Index(['term', 'grade', 'sub_grade', 'emp_title', 'home_ownership',
'verification_status', 'issue_d', 'loan_status', 'purpose', 'title',
'zip_code', 'addr_state', 'earliest_cr_line', 'initial_list_status',
'last_pymnt_d', 'next_pymnt_d', 'last_credit_pull_d',
'application_type'],
dtype='object')
In [37]:
``` ms.matrix(object_df)
plt.show() ```
主要是兩個欄位缺失值:emp_title、next_pymnt_d
缺失值填充
In [38]:
object_df.isnull().sum()
Out[38]:
term 0
grade 0
sub_grade 0
emp_title 6782
home_ownership 0
verification_status 0
issue_d 0
loan_status 0
purpose 0
title 0
zip_code 0
addr_state 0
earliest_cr_line 0
initial_list_status 0
last_pymnt_d 145
next_pymnt_d 3921
last_credit_pull_d 3
application_type 0
dtype: int64
在這裡我們直接填充為“Unknown”:
In [39]:
object_df.fillna("Unknown",inplace=True)
再次檢視發現已經沒有缺失值:
In [40]:
缺失值處理——數值型變數
In [41]:
number_df = df1.select_dtypes(exclude="object")
number_df.columns
Out[41]:
Index(['loan_amnt', 'funded_amnt', 'funded_amnt_inv', 'int_rate',
'installment', 'emp_length', 'annual_inc', 'dti', 'delinq_2yrs',
'inq_last_6mths', 'mths_since_last_delinq', 'open_acc', 'pub_rec',
'revol_bal', 'revol_util', 'total_acc', 'out_prncp', 'out_prncp_inv',
'total_pymnt', 'total_pymnt_inv', 'total_rec_prncp', 'total_rec_int',
'total_rec_late_fee', 'last_pymnt_amnt', 'collections_12_mths_ex_med',
'acc_now_delinq', 'tot_coll_amt', 'tot_cur_bal', 'open_acc_6m',
'open_il_6m', 'open_il_12m', 'open_il_24m', 'mths_since_rcnt_il',
'total_bal_il', 'il_util', 'open_rv_12m', 'open_rv_24m', 'max_bal_bc',
'all_util', 'total_rev_hi_lim', 'inq_fi', 'total_cu_tl', 'inq_last_12m',
'acc_open_past_24mths', 'avg_cur_bal', 'bc_open_to_buy', 'bc_util',
'chargeoff_within_12_mths', 'delinq_amnt', 'mo_sin_old_il_acct',
'mo_sin_old_rev_tl_op', 'mo_sin_rcnt_rev_tl_op', 'mo_sin_rcnt_tl',
'mort_acc', 'mths_since_recent_bc', 'mths_since_recent_inq',
'mths_since_recent_revol_delinq', 'num_accts_ever_120_pd',
'num_actv_bc_tl', 'num_actv_rev_tl', 'num_bc_sats', 'num_bc_tl',
'num_il_tl', 'num_op_rev_tl', 'num_rev_accts', 'num_rev_tl_bal_gt_0',
'num_sats', 'num_tl_120dpd_2m', 'num_tl_30dpd', 'num_tl_90g_dpd_24m',
'num_tl_op_past_12m', 'pct_tl_nvr_dlq', 'percent_bc_gt_75',
'pub_rec_bankruptcies', 'tax_liens', 'tot_hi_cred_lim',
'total_bal_ex_mort', 'total_bc_limit', 'total_il_high_credit_limit'],
dtype='object')
In [42]:
number_df.shape
Out[42]:
(105451, 79)
缺失值視覺化
In [43]:
ms.matrix(number_df)
plt.show()
如何判斷某行是否全部為空
檢視缺失值情況
In [48]:
number_df.isnull().sum().sort_values(ascending=False)
Out[48]:
mths_since_recent_revol_delinq 68375
mths_since_last_delinq 51119
il_util 13380
mths_since_recent_inq 11949
num_tl_120dpd_2m 5278
...
tot_cur_bal 0
tot_coll_amt 0
acc_now_delinq 0
collections_12_mths_ex_med 0
total_il_high_credit_limit 0
Length: 79, dtype: int64
找出存在缺失值的欄位
In [49]:
```
存在缺失值的為True,否則為False
number_df.isnull().sum() > 0 ```
Out[49]:
loan_amnt False
funded_amnt False
funded_amnt_inv False
int_rate False
installment False
...
tax_liens False
tot_hi_cred_lim False
total_bal_ex_mort False
total_bc_limit False
total_il_high_credit_limit False
Length: 79, dtype: bool
In [50]:
number_df.columns[number_df.isnull().sum() > 0]
Out[50]:
Index(['dti', 'mths_since_last_delinq', 'revol_util', 'mths_since_rcnt_il',
'il_util', 'all_util', 'avg_cur_bal', 'bc_open_to_buy', 'bc_util',
'mo_sin_old_il_acct', 'mths_since_recent_bc', 'mths_since_recent_inq',
'mths_since_recent_revol_delinq', 'num_tl_120dpd_2m',
'percent_bc_gt_75'],
dtype='object')
缺失值填充
對於數值型變數的缺失值,我們採用每列的均值來填充
In [51]:
```
方法1
for col in number_df.columns[number_df.isnull().sum() > 0]: mean_val = number_df[col].mean() # 每列的均值 number_df[col].fillna(mean_val, inplace=True) # 均值填充 ```
In [52]:
```
方法2
老版本報錯
from sklearn.preprocessing import Imputer
使用新版本
from sklearn.impute import SimpleImputer imputer = SimpleImputer(missing_values=np.nan, strategy='mean') ```
In [53]:
number_df.isnull().sum().sort_values(ascending=False)
Out[53]:
python
loan_amnt 0
mo_sin_old_rev_tl_op 0
num_accts_ever_120_pd 0
mths_since_recent_revol_delinq 0
mths_since_recent_inq 0
..
acc_now_delinq 0
collections_12_mths_ex_med 0
last_pymnt_amnt 0
total_rec_late_fee 0
total_il_high_credit_limit 0
Length: 79, dtype: int64
新建模資料new_data
手動過濾欄位
有些欄位對建模是無用的,即存在冗餘的欄位資訊,我們需要手動刪除。
In [54]:
object_df.isnull().sum()
Out[54]:
term 0
grade 0
sub_grade 0
emp_title 0
home_ownership 0
verification_status 0
issue_d 0
loan_status 0
purpose 0
title 0
zip_code 0
addr_state 0
earliest_cr_line 0
initial_list_status 0
last_pymnt_d 0
next_pymnt_d 0
last_credit_pull_d 0
application_type 0
dtype: int64
In [55]:
object_df["application_type"].value_counts()
Out[55]:
INDIVIDUAL 98619
JOINT 6813
DIRECT_PAY 19
Name: application_type, dtype: int64
- term:申請人的貸款償還期數,通常是36或者60,對於建模沒有指導意義,保留(1)
- grade和sub_grade:存在重複資訊,選擇刪除欄位sub_gracde,保留grade(12)
- emp_title:不能反映借款人的收入或者資產情況,可刪除
- home_ownership:房屋所在狀態,保留(3)
- verification_status:收入是否被LC驗證、未驗證或收入來源是否被驗證,保留(4)
- issue_d:貸款發行時間,對於是否違規預測也沒有指導意義,可刪除
- loan_status:貸款的當前狀態,保留(5)
- purpose:貸款目的,保留(6)
- title:和purpose重複,可刪除
- zip_code:地址郵編,對於建模無效
- addr_state:申請人的地址所在州,建模無效
- earliest_cr_line:借款人最早公佈的信用額度開通的月份,對於是否違規模型搭建無意義,考慮刪除
- initial_list_status:貸款的初始上市狀態,可謂W或者F,保留(7)
- last_pymnt_d、next_pymnt_d、last_credit_pull_d:貸款後的資訊,對於是否違規預測為意義,可刪除
- application_type:指示貸款是單獨申請還是與兩個共同借款人的聯合申請,保留(8)
最終留下8個有用的欄位資訊:
In [56]:
``` object_df = object_df[["term","grade","home_ownership","verification_status","loan_status", "purpose","initial_list_status","application_type"]]
object_df ```
資料合併
將兩個資料合併起來:
In [57]:
new_data = pd.concat([object_df,number_df],axis=1)
new_data.head()
基本資訊
In [58]:
new_data.dtypes
Out[58]:
term object
grade object
home_ownership object
verification_status object
loan_status object
...
tax_liens int64
tot_hi_cred_lim int64
total_bal_ex_mort int64
total_bc_limit int64
total_il_high_credit_limit int64
Length: 87, dtype: object
In [59]:
new_data.shape
Out[59]:
(105451, 87)
描述統計資訊
針對數值型欄位的描述統計資訊,檢視最值,四分位數等:
In [60]:
new_data.describe()
特徵工程
特徵衍生
In [61]:
installment / (annual_inc / 12):表示每個月的還款金額佔據月收入的比例,數值越大,還款壓力越大
```python
installment:每月的還款金額
annual_inc:申請人年度總收入
新特徵
new_data["installment_percent"] = new_data[["installment","annual_inc"]].apply(lambda x: x.installment / (x.annual_inc / 12), axis=1).replace([np.inf,0]) new_data.head() ```
Out[61]:
貸款狀態編碼與視覺化
編碼
In [62]:
new_data["loan_status"].value_counts()
Out[62]:
Current 99850
Fully Paid 3896
In Grace Period 932
Late (31-120 days) 436
Late (16-30 days) 312
Charged Off 25
Name: loan_status, dtype: int64
In [63]:
```
違約=1, 正常=0
new_data["loan_status"] = new_data["loan_status"].apply(lambda x: 0 if (x == "Fully Paid" or x == "Current") else 1) ```
In [64]:
new_data["loan_status"].value_counts()
Out[64]:
0 103746
1 1705
Name: loan_status, dtype: int64
視覺化
In [65]:
```python
貸款狀態柱狀圖統計
fig, axs = plt.subplots(1,2,figsize=(12,6)) sns.countplot(x='loan_status', data=new_data, ax=axs[0])
axs[0].set_title("Frequency of each Loan Status(Bar)")
餅圖:統計每個型別的佔比
new_data['loan_status'].value_counts().plot(x=None, y=None, kind='pie', ax=axs[1], autopct='%1.2f%%') axs[1].set_title("Percentage of each Loan status(Pie)") plt.show() ```
可以看到違規和沒有違規的比例差別是很大的,後面會通過取樣的方法來解決。
有序變數編碼
部分欄位的取值是存在一定的順序關係。比如服裝的尺碼大小,"XS"、"S"、"M"、"L"等,它們的取值本身是有大小關係的。
在這裡我們實施硬編碼:
In [66]:
new_data.select_dtypes("object")
無序特徵編碼
採用的獨熱碼,通過get_dummies函式來實現
In [68]:
df1 = new_data.select_dtypes("object") # 字元型
df2 = new_data.select_dtypes(exclude=["object"]) # 非字元型
df1.head()
Out[68]:
特徵縮放:標準化
針對數值型特徵(資料df2)的特徵縮放,將資料規範到一定範圍內,便於後期加快演算法的收斂速度
In [70]:
```
目標變數load_status
Y = df2[["loan_status"]] Y.head() ```
Out[70]:
| | loan_status | | ---: | ----------: | | 0 | 0 | | 1 | 0 | | 2 | 0 | | 3 | 0 | | 4 | 0 |
In [71]:
```
df2中剩餘的數值型變數構成df3
df3 = df2.drop("loan_status",axis=1) df3.head() ```
```python
對df3實施標準化處理
from sklearn.preprocessing import StandardScaler ss = StandardScaler() ss_data = ss.fit_transform(df3)
df4 = pd.DataFrame(ss_data, columns=df3.columns) df4.head() ```
SMOTE取樣(重點)
可以看到違規和沒有違規的比例差別是很大的,也就是說樣本及其不均衡,常用的處理方式有兩種:
- 過取樣(oversampling),增加正樣本使得正、負樣本數目接近,然後再進行學習
- 欠取樣(undersampling),去除一些負樣本使得正、負樣本數目接近,然後再進行學習。
下面通過欠取樣方法來處理:
In [75]:
positive_data = new_df[new_df["loan_status"] == 1] # 違約
negetive_data = new_df[new_df["loan_status"] == 0] # 未違約
In [76]:
print("length of positive_data: ",len(positive_data))
print("length of negetive_data: ",len(negetive_data))
length of positive_data: 1705
length of negetive_data: 103746
In [77]:
``` selected_data = negetive_data.sample(len(positive_data))
selected_data.shape ```
Out[77]:
(1705, 104)
下面生成的new_data就是最終用於建模的資料:
In [78]:
new_data = pd.concat([positive_data,selected_data],axis=0)
new_data
建模
特徵和目標分離
In [79]:
y = new_data[["loan_status"]]
X = new_data.drop("loan_status", axis=1)
訓練集和測試集切分
In [80]:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=4)
邏輯迴歸分類器
基於邏輯迴歸的分類器
In [81]:
``` from sklearn.linear_model import LogisticRegression clf = LogisticRegression() # 構建邏輯迴歸分類器
clf.fit(X_train, y_train) ```
Out[81]:
LogisticRegression()
In [82]:
```
進行預測
predict = clf.predict(X_test) predict[:5] ```
Out[82]:
array([1, 1, 0, 1, 1])
預測準確率
檢視預測的準確率:
In [83]:
``` from sklearn.metrics import accuracy_score
accuracy_score(predict, y_test) ```
Out[83]:
0.7067448680351907
混淆矩陣的資訊:
In [84]:
from sklearn.metrics import confusion_matrix
m = confusion_matrix(y_test, predict)
m
Out[84]:
array([[262, 87],
[113, 220]])
In [85]:
```
混淆矩陣視覺化
plt.figure(figsize=(12,8)) sns.heatmap(m)
plt.show() ```
上面視覺化的結果表示:顏色越深代表的人數越多,也就是真陽性的人數是最多的;而假陽性是最少的
roc曲線
In [86]:
``` from sklearn.metrics import roc_curve, auc false_positive_rate, true_positive_rate,thresholds = roc_curve(y_test, predict)
roc_auc = auc(false_positive_rate,true_positive_rate) roc_auc ```
Out[86]:
0.7056884965194421
In [87]:
``` import matplotlib.pyplot as plt plt.figure(figsize=(10,10)) plt.title("ROC") # Receiver Operating Characteristic plt.plot(false_positive_rate, true_positive_rate, color="red", label="AUC = %0.2f"%roc_auc )
plt.legend(loc="lower right") plt.plot([0,1],[0,1],linestyle="--") plt.axis("tight")
真陽性:預測類別為1的positive;預測正確True
plt.ylabel("True Positive Rate")
假陽性:預測類別為1的positive;預測錯誤False
plt.xlabel("False Positive Rate") ```
Out[87]:
Text(0.5, 0, 'False Positive Rate')
總結
整體方案的ROC值達到了71%,還是有一定的提升空間。後續可以優化的點:
- 特徵屬性過多:可以考慮降維或者特徵的多重線性檢驗,找出更具有價值的特徵
- 離散型變數的編碼:目前是統一的標準化處理,沒有編碼工作;後續可以考慮加入編碼工作,比如:因子化、特徵分箱等
- 建模優化:嘗試使用不同的分類模型,以及模型融合方法
- 引數調優:可以考慮做一個引數的調優,比如網格搜尋、隨機搜尋等等
- 基於機器學習分類演算法的鋼材缺陷檢測分類
- JSON資料,Python搞定!
- 邏輯迴歸:信貸違規預測!
- kaggle實戰-腫瘤資料統計分析
- Pandas操作mysql資料庫!
- 數學公式編輯神器-Mathpix Snipping Tool
- 精選20個Pandas統計函式
- 露一手,利用Python分析房價
- 德國信貸資料建模baseline!
- Python函式傳參機制詳解
- Python爬蟲周遊全國-蘭州站
- 一道Pandas題:3種解法
- 機器學習實戰:基於3大分類模型的中風病人預測
- 利用seaborn繪製柱狀圖
- 機器學習實戰:基於MNIST資料集的二分類問題
- 基於深度學習Keras的深圳租房建模
- 機器學習高頻使用程式碼片段
- Python入門:Python變數和賦值
- 深度學習框架Keras入門保姆教程
- kaggle實戰:極度不均衡的信用卡資料分析