2020-09-24

xiaoxi96發表於2020-09-24

第四次打卡

1. 匯入相關庫和相關設定

import pandas as pd
import numpy as np
import warnings
import os
import seaborn as sns
import matplotlib.pyplot as plt
"""
sns 相關設定
@return:
"""
# 宣告使用 Seaborn 樣式
sns.set()
# 有五種seaborn的繪圖風格,它們分別是:darkgrid, whitegrid, dark, white, ticks。預設的主題是darkgrid。
sns.set_style("whitegrid")
# 有四個預置的環境,按大小從小到大排列分別為:paper, notebook, talk, poster。其中,notebook是預設的。
sns.set_context('talk')
# 中文字型設定-黑體
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解決儲存影像是負號'-'顯示為方塊的問題
plt.rcParams['axes.unicode_minus'] = False
# 解決Seaborn中文顯示問題並調整字型大小
sns.set(font='SimHei')

2. 讀取資料

# reduce_mem_usage 函式通過調整資料型別,幫助我們減少資料在記憶體中佔用的空間
def reduce_mem_usage(df):
    start_mem = df.memory_usage().sum() 
    print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))
    
    for col in df.columns:
        col_type = df[col].dtype
        
        if col_type != object:
            c_min = df[col].min()
            c_max = df[col].max()
            if str(col_type)[:3] == 'int':
                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                    df[col] = df[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                    df[col] = df[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                    df[col] = df[col].astype(np.int32)
                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                    df[col] = df[col].astype(np.int64)  
            else:
                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                    df[col] = df[col].astype(np.float16)
                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                    df[col] = df[col].astype(np.float32)
                else:
                    df[col] = df[col].astype(np.float64)
        else:
            df[col] = df[col].astype('category')

    end_mem = df.memory_usage().sum() 
    print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
    print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
    
    return df

3. 簡單建模

Tips1:金融風控的實際專案多涉及到信用評分,因此需要模型特徵具有較好的可解釋性,所以目前在實際專案中多還是以邏輯迴歸作為基礎模型。但是在比賽中以得分高低為準,不需要嚴謹的可解釋性,所以大多基於整合演算法進行建模。

Tips2:因為邏輯迴歸的演算法特性,需要提前對異常值、缺失值資料進行處理【參考task3部分】

Tips3:基於樹模型的演算法特性,異常值、缺失值處理可以跳過,但是對於業務較為了解的同學也可以自己對缺失異常值進行處理,效果可能會更優於模型處理的結果。

# 建模前操作
from sklearn.model_selection import KFold
# 分離資料集,方便進行交叉驗證
X_train = data.loc[data['sample']=='train', :].drop(['id','issueDate','isDefault', 'sample'], axis=1)
X_test = data.loc[data['sample']=='test', :].drop(['id','issueDate','isDefault', 'sample'], axis=1)
y_train = data.loc[data['sample']=='train', 'isDefault']

# 5折交叉驗證
folds = 5
seed = 2020
kf = KFold(n_splits=folds, shuffle=True, random_state=seed)
# 對訓練集資料進行劃分,分成訓練集和驗證集,並進行相應的操作
from sklearn.model_selection import train_test_split
import lightgbm as lgb
# 資料集劃分
X_train_split, X_val, y_train_split, y_val = train_test_split(X_train, y_train, test_size=0.2)
train_matrix = lgb.Dataset(X_train_split, label=y_train_split)
valid_matrix = lgb.Dataset(X_val, label=y_val)

params = {
            'boosting_type': 'gbdt',
            'objective': 'binary',
            'learning_rate': 0.1,
            'metric': 'auc',
            'min_child_weight': 1e-3,
            'num_leaves': 31,
            'max_depth': -1,
            'reg_lambda': 0,
            'reg_alpha': 0,
            'feature_fraction': 1,
            'bagging_fraction': 1,
            'bagging_freq': 0,
            'seed': 2020,
            'nthread': 8,
            'silent': True,
            'verbose': -1,
}

# 使用訓練集資料進行模型訓練
model = lgb.train(params, train_set=train_matrix, valid_sets=valid_matrix, num_boost_round=20000, verbose_eval=1000, early_stopping_rounds=200)

4. 模型調參

4.1. 貪心調參

先使用當前對模型影響最大的引數進行調優,達到當前引數下的模型最優化,再使用對模型影響次之的引數進行調優,如此下去,直到所有的引數調整完畢。

這個方法的缺點就是可能會調到區域性最優而不是全域性最優,但是隻需要一步一步的進行引數最優化除錯即可,容易理解。

需要注意的是在樹模型中引數調整的順序,也就是各個引數對模型的影響程度,這裡列舉一下日常調參過程中常用的引數和調參順序:

①:max_depth、num_leaves
②:min_data_in_leaf、min_child_weight
③:bagging_fraction、 feature_fraction、bagging_freq
④:reg_lambda、reg_alpha
⑤:min_split_gain

4.2. 網格搜尋

sklearn 提供GridSearchCV用於進行網格搜尋,只需要把模型的引數輸進去,就能給出最優化的結果和引數。相比起貪心調參,網格搜尋的結果會更優,但是網格搜尋只適合於小資料集,一旦資料的量級上去了,很難得出結果。

4.3 貝葉斯調參

在使用之前需要先安裝包bayesian-optimization,執行如下命令即可:

pip install bayesian-optimization

貝葉斯調參的主要思想是:給定優化的目標函式(廣義的函式,只需指定輸入和輸出即可,無需知道內部結構以及數學性質),通過不斷地新增樣本點來更新目標函式的後驗分佈(高斯過程,直到後驗分佈基本貼合於真實分佈)。簡單的說,就是考慮了上一次引數的資訊,從而更好的調整當前的引數。

貝葉斯調參的步驟如下:

定義優化函式(rf_cv)
建立模型
定義待優化的引數
得到優化結果,並返回要優化的分數指標