天天看點

基于lightgbm的金融風控算法實踐(Python版)

自國内金融P2P暴雷,國内很多小貸機構便湧入了東南亞、非洲等未開拓的市場,像印尼、印度、菲律賓、泰國、越南、奈及利亞等國家。

分析這些東南亞/非洲國家的市場特點,有低金融包容性(2017年越南有30.8%的人擁有銀行賬戶),對金融的高需求(2017年借貸的人口比例49.0%)和網際網路普及率(2018年為66%)和移動連通性,為東南亞金融科技貸款的發展提供了最有利的條件,開啟了野蠻生長的模式。

結合這些地域的貸款市場情況,通常征信體系建設及經濟情況都比較差,且大部分的使用者資質比較差(也并不滿足銀行的貸款資格)。種種因素下,機構對于放貸使用者的信用/欺詐風險的掌握是比較差的,小貸機構壞賬率普遍地高(如一些機構的新借貸使用者壞賬率可達 20~30%,而銀行壞賬通常在10%左右)。

在東南亞開展的小額貸款産品,普遍是714高炮(貸款周期7-14天,收取高額逾期費用或放貸時提前從本金中扣除利息-砍頭息,有的實際年化利率竟達到300%)。

高利率必然帶着高風險,這種業務也很容易受到金融監管政策的封殺。

小貸風控體系介紹

這麼高的壞賬情況,如果小貸機構在對借貸使用者信用情況的掌握不足,即使高利率也未必覆寫這麼高的信用風險。

可見,風控能力是小貸業務控制損失的核心,風控體系通常由 反欺詐(證件資訊核實、人臉識别驗證、黑名單)+ 申請評分模型組成。

風控好壞關鍵在于資料擷取及積累。一個明顯差異展現在于,機構新借貸的使用者壞賬率是20~30%(裡面騙貸欺詐的比重應該挺高),而對于在機構内複貸的老使用者(之前有借貸的再重複貸款的使用者)壞賬率僅有4%。

也就是,對于機構有掌握借貸曆史的使用者,其壞賬率是顯著較低的!信貸風控能力的差異其實也就是資料壟斷優勢的展現! 對于小貸機構,營銷擴充新使用者後,如何應用風控模型盡量準确地評估新使用者,并給予較低的額度,當其有較好的信貸曆史後再提高額度,好好維持及擴充這部分複貸使用者就是業務盈利的關鍵。

海外的小貸機構申請評分模型的資料主要來源有:

  • 機構曆史借貸記錄:如使用同一手機号申請貸款次數、逾期次數。在征信體系建設覆寫不完全的情況下,在機構内(或聯合機構)的借貸曆史往往也是最有說服力及有效的。
  • 客戶基本資料:如身份資訊、聯系方式、職業、收入、借款用途等資訊。由于線上申請這些資料往往沒有人工稽核,資訊的可靠性是存疑的,通常可以借助多方資料來核驗這些是不是一緻及可靠的。
  • 征信機構的征信報告:全球三大商業個人征信巨頭分别為益百利(Experian)、艾克發(Equifax)和環聯(Trans union),可以提供貸款申請次數、貸款額度、信用賬戶數等資訊。但不足的地方在于,對于征信體系建設不完善的地區,覆寫度、資訊記錄會比較差(本項目驗證的Experian實際覆寫度80%左右)。
  • 手機短信:短信可以提供很多有價值的資訊,如話費欠費、銀行卡收入支出、聯系人數量、日常閑聊短信、機構催收短信、信貸廣告數量。可以通過簡單關鍵字比對、詞袋模型等方法抽取關鍵特征,進一步還可以通過短信分類、資訊抽取(實體抽取)等方法統計催收短信數量、欠款金額、收入支出金額等資料(注:擷取短信資料肯定是不合規的,對于機構隻想要更多的資料保證,而對于使用者急着用錢哪還管什麼隐私資料。目前,有些APP已被禁止擷取短信、通話記錄,這也是要随着監管不斷完善。)
  • 手機通訊錄:可用于統計關聯的聯系人的逾期次數等特征,以及其他的一些社交資訊;
  • APP資料:可統計安裝信貸類APP、社交類APP的數量,以及app使用率;
  • 登入IP、GPS、裝置号資訊:可以用于關聯特征,如同一IP下逾期次數,以及建立IP、裝置黑名單;
  • 銀行對賬單資料:如工資流水等資訊,可以比較有效展現使用者還款能力。

申請評分模型實踐

1 征信特征加工

本項目基于東南亞某國近期的500筆的小額貸款交易(資料源于網絡,侵删),擷取相應Experian征信報告資料,并用Python加工出滑動視窗的征信特征:如近30天的貸款次數,貸款平均額度、最近貸款日期間隔、曆史逾期次數等特征,通過LightGBM建構申請評分模型。

基于lightgbm的金融風控算法實踐(Python版)

本項目模組化較為簡化,更為完整的評分卡模組化全流程可以參考之前文章:​​真香啊,一文講透金融風控模組化全流程(Python)​​

基于lightgbm的金融風控算法實踐(Python版)

Experian征信報告原始封包包含了個人基本資訊、近期貸款資訊、信用卡、貸款等曆史表現等資訊。如下代碼滑動時間視窗,提取相應的特征。

def add_fea_grids(fea_dict, mult_datas, apply_dt='20200101', dt_key='Open_Date', calc_key="data['Amount_Past_Due']",groupfun=['count','sum', 'median','mean','max','min','std'], dt_grids=[7, 30,60,360,9999]):
    """
    征信報告使用滑動時間視窗-近N天,加工字段A的 計數、平均、求和等特征.
    fea_dict:最終特征存儲的字典
    mult_datas:多條的記錄值
    calc_key:資料特征字段的相對位置 
    """
    new_fea = {} # 記錄各時間視窗的原始特征
    for _dt in dt_grids:
        new_fea.setdefault(_dt, [])# 按時間視窗初始化
    fea_suffix = calc_key.split("'")[-2]  + str(len(calc_key))   # 字首備注
    if mult_datas:
        mult_datas = con_list(mult_datas) 
        for data in mult_datas:
            if len(data[dt_key]) >=4  and  data[dt_key] < apply_dt: #篩選申請日期前的記錄,報告應該為準實時調用的
                for _dt in dt_grids:
                    if (_dt==9999) or (ddt.datetime.strptime(str(data[dt_key]),"%Y%m%d") >= (ddt.datetime.strptime(str(apply_dt),"%Y%m%d") + ddt.timedelta(days=-_dt))) :# 篩選為近N天的記錄,為9999則不做篩選
                        if "Date" in  calc_key or "Year" in   calc_key : #判斷是否為日期型,日期直接計算為時間間隔
                            fea_value = diff_date(apply_dt, eval(calc_key) )
                        elif "mean" in groupfun: # 判斷是否為數值型,直接提取到相應的時間窗
                            fea_value = to_float_ornan(eval(calc_key))
                        else:# 其他按字元型處理
                            fea_value = eval(calc_key)
                        new_fea[_dt].append(fea_value)  #  { 30: [2767.0, 0.0]}
    for _k, data_list in new_fea.items(): # 生成具體特征
        for fun in groupfun:
            fea_name = fea_suffix+ '_'+ fun + '_' +str(_k)
            fea_dict.setdefault(fea_name, [])
            if len(data_list) > 0:
                final_value = fun_dict[fun](data_list)
            else :
                final_value = np.nan
            fea_dict[fea_name].append(final_value)      
基于lightgbm的金融風控算法實踐(Python版)

3.2 特征選擇

考慮征信報告的隐私性,本項目僅提供一份報告示例做特征加工。特征加工後特征選擇,關聯逾期标簽,形成如下最終資料特征寬表。

df2 = pd.read_pickle('filter_feas_df.pkl')
print(df2.label.value_counts()) # 逾期标簽為label==0
df2.head()      
基于lightgbm的金融風控算法實踐(Python版)

3.3 模型訓練

train_x, test_x, train_y, test_y = train_test_split(df2.drop('label',axis=1),df2.label,random_state=1)

lgb = lightgbm.LGBMClassifier()
lgb.fit(train_x, train_y,
        eval_set=[(test_x,test_y)],
        eval_metric='auc',
        early_stopping_rounds=50,
        verbose=-1)


print('train ',model_metrics2(lgb,train_x, train_y))
print('test ',model_metrics2(lgb,test_x,test_y))      
基于lightgbm的金融風控算法實踐(Python版)