1. 程式人生 > >隨機森林篩選變數(Python實現)

隨機森林篩選變數(Python實現)

#文章轉自每日一Python公眾號

當資料集的特徵過多時,容易產生過擬合,可以用隨機森林來在訓練之後可以產生一個各個特徵重要性的資料集,利用這個資料集,確定一個閾值,選出來對模型訓練幫助最大的一些特徵,篩選出重要變數後可以再訓練模型;

本文所用資料集是從kaggle網站上下載的lend club資料,通過隨機森林篩選出對預測是否逾期的重要性變數:

# 首先匯入資料,檢視資料集的基本情況:
df = pd.read_csv('loan.csv')
df.head()
df.shape
資料集共887379行,74列

#然後轉換目標值,將Charged Off和Late (31-120 days歸為壞客戶1,其餘歸為0
df['loan_status'].unique()
df['y'] = df['loan_status'].map(lambda x: int((x == 'Charged Off') | (x == 'Late (31-120 days')))
df.drop('loan_status', axis=1,inplace=True)

接下來處理特徵變數,先剔除一些對預測無關的貸後和貸中變數:

df.drop(['id', 'member_id', 'url','next_pymnt_d','last_pymnt_d',
          'pymnt_plan','last_credit_pull_d','total_rec_prncp',
          'total_rec_int','out_prncp','last_pymnt_amnt',
          'installment','total_pymnt_inv', 'total_rec_prncp',
          'total_rec_int'], axis=1,inplace=True)

再刪除缺失值大於90%的變數:

df.dropna(thresh = len(df) * 0.1 , axis=1,inplace=True)

接下來補全缺失值,對缺失值較多變數,將缺失值作為一種狀態,對缺失值較少的變數,數值型用平均值補全,類別型用眾數補全:

#對於desc有描述的標為1,空值標為0
def Desc(x):
    if type(x).__name__ == 'float':
        return 0
    else:
        return 1
df['desc']= df['desc'].map(Desc)

#emp_title空值用“空值”補全
df['emp_title'] = df['emp_title'].fillna('missing')

'''mths_since_last_delinq,mths_since_last_record ,
mths_since_last_major_derog ,tot_coll_amt,tot_cur_bal,
total_rev_hi_lim 用-1代替'''
for col in ['mths_since_last_delinq','mths_since_last_record',
             'mths_since_last_major_derog','tot_coll_amt',
             'tot_cur_bal','total_rev_hi_lim']:
    df[col].fillna(-1,inplace=True)

#剩餘缺失值較少的,數值型變數用平均值代替

for col in ['annual_inc','acc_now_delinq',
             'collections_12_mths_ex_med','total_acc',
             'pub_rec','open_acc','inq_last_6mths','delinq_2yrs',
             'revol_util']:
    df[col].fillna(df[col].mean(), inplace=True)

另外再構造一個衍生變數,算申請時間issue_d和第一次借貸時間earliest_cr_line之間的月份差值

import datetime
def ConvertDate(x):

    mth_dict = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 
                'Jun': 6, 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10,
                'Nov': 11, 'Dec': 12}
    yr = int(x[4:6])
    mth = mth_dict[x[:3]]
    return datetime.datetime(yr, mth, 1)
df['issue_d'] = df['issue_d'].map(lambda x :ConvertDate(x))
df['earliest_cr_line'] = df['earliest_cr_line'].map(lambda x :ConvertDate(x))

from dateutil.relativedelta import relativedelta
def MonthGap(earlyDate, lateDate):
    if lateDate > earlyDate:
        gap = relativedelta(lateDate, earlyDate)
        yr = gap.years
        mth = gap.months
        return yr*12 + mth
    else:
        return 0
df['earliest_cr_to_app'] = df.apply(lambda x : MonthGap(x.earliest_cr_line, x.issue_d),axis=1)

df.drop(['issue_d', 'earliest_cr_line'],axis=1, inplace=True)

因為決策樹只能處理數值型和標稱型變數,所以轉換一下類別變數

'''因為本文只運用隨機森林來判斷變數的重要性,而樹模型不需要One-Hot編碼,
所以只對型別型變數LabelEncoding就可以'''

#term ,將months替換成空值
df['term']= df['term'].apply(lambda x :int(x.replace("months" , "")))
cols = df.select_dtypes(include=['O']).columns.tolist()
for col in cols:
    df[col] = preprocessing.LabelEncoder().fit_transform(df[col])

訓練模型

#訓練模型,這裡隨機森林模型引數都用預設值
y = df['y']
x = df.drop('y', axis=1)
clf = RandomForestClassifier()
clf.fit(x, df['y'])

篩選變數:

importance = clf.feature_importances_
indices = np.argsort(importance)[::-1]
features = x.columns
for f in range(x.shape[1]):
    print(("%2d) %-*s %f" % (f + 1, 30, features[f], importance[indices[f]])))

現在各變數對是否逾期的重要性就計算出來了,如果接下來運用這些變數預測是否逾期的模型是樹模型或者樸素貝葉斯模型,就可以直接通過重要性大於某個閾值或者重要性排名大於某個某個閾值來篩選出變數訓練模型了,如果是接下來用迴歸模型或者線性模型,還需要考慮各個變數之間的共線性;