1. 程式人生 > >基於知識圖譜+機器學習,搭建風控模型的專案落地

基於知識圖譜+機器學習,搭建風控模型的專案落地

本專案主要實現邏輯如下:
1.將測試資料分表格存入mysql資料庫。
2.設計知識圖譜關係圖,按照設計思路將node與對應的relationship存入neo4j資料庫。
3.設計一套有效的特徵,提取特徵用於機器學習模型進行訓練,用以風控判斷。
4.將提取特徵的cypher語句存入mysql,使用SpringBoot搭建微服務,用以讀取api獲取每個進件的特徵矩陣。
5.使用邏輯迴歸、GBDT,神經網路等模型在訓練資料上搭建風控模型,通過AUC指標判斷模型的準確率。
6.使用測試資料,通過最優模型獲取預測結果。

下面講解具體實現過程:

1.測試資料準備

我們準備瞭如下幾個測試資料集

person:標註使用者姓名、性別、手機號、使用者黑名單

在這裡插入圖片描述

phone:手機號、手機號黑名單

在這裡插入圖片描述

phone2phone:通話記錄撥打方、接聽方、通話的起止時間

在這裡插入圖片描述

apply_train與apply_test:進件貸款金額、實現、申請人工作、地點、父母手機號、同事手機號、公司電話、申請人id、進件狀態(其中apply_test內status值為空)

在這裡插入圖片描述
將以上所有資料匯入mysql

2.設計知識圖譜

由測試資料可直接得到以下關係:
1.people節點與apply節點之間有fill關係
2.apply節點與phone節點之間有parent_phone、colleague_phone、company_phone等關係
3.people與phone之間有has_phone的關係
然後通過上述關係可推得以下關係:
4.parent_phone的持有人與進件的申請人為parent_of關係,同理可推得colleague_of關係
5.通過通話記錄可推得兩個people節點之間的known關係
在這裡插入圖片描述


通過以上關係圖譜,使用APOC將資料以對應的關係存入neo4j中,得到類似於以下結構的資料
在這裡插入圖片描述

3.設計特徵提取規則

因為最終傳入機器學習模型的訓練應該是一個二維陣列,所以我們需要從neo4j中提取每個進件的特徵。實際專案中,可能需要設計幾十個或上百個規則才可以達到需要的準確率,在這裡以7個特徵為例做講解。
在這裡插入圖片描述
我們需要將以上規則存入mysql,用以後續呼叫
在這裡插入圖片描述

4.搭建SpringBoot微服務

程式碼結構如下:業務程式碼放在RuleController類中
在這裡插入圖片描述

@RestController
@Api(value = "/" , description = "規則引擎服務")
@RequestMapping("v1")
public class RuleController {

    @Autowired
    private SqlSessionTemplate template;

    @Autowired
    private Driver driver;

    @ApiOperation(value = "獲取規則引擎中規則執行的結果",httpMethod = "POST")
    @RequestMapping(value = "/getRuleResult", method = RequestMethod.POST)
    public int getRuleResult(@RequestParam String ruleID, @RequestParam Integer applyId){
        /**
         * 從mysql中拿到規則
         */
        String ruleCypher = template.selectOne("getRule",ruleID);

        /**
         * 獲取到neo4j的session 物件,用來執行cypher語句
         */
        Session session = driver.session();
        Map ruleMap = new HashMap();
        ruleMap.put("applyId",applyId);

        //用來儲存Cypher最終執行的結果
        int resultCount = 0;

        // 執行cypher語句
        StatementResult result = session.run(ruleCypher,ruleMap);

        Map resultMap = new HashMap();
        while (result.hasNext()){
            Record record = result.next();
            resultMap = record.asMap();
            Long resultLong = (Long) resultMap.get("count(a)");
            resultCount = Math.toIntExact(resultLong);
        }
        return resultCount;
    }
}

我們在傳入對應的rule_id和進件id時,可以通過微服務拿到我們需要的特徵值,然後將所有特徵組合為二維向量,形成機器學習模型所需的測試資料集。
此時所有OVERDUE狀態的進價,我們將label標記為1,其他狀態的進件標記為0,匯入data.txt檔案

import re
import requests

f2 = open('data.txt', 'a+', encoding='utf8')
with open('train.txt', 'r', encoding='utf8') as f:
    for i in f.readlines():
        l = []
        num = re.findall('(\d{6})', i)[0]
        l.append(int(num))
        for rule in range(1, 8):
            r = requests.post(
                'http://localhost:9527/v1/getRuleResult?ruleID=' + str(rule) + '&applyId=' + str(num)).text
            l.append(int(r))
        status = re.findall('IN_PROGREESS|REPAID|OVERDUE|RETURNING', i)[0]

        if status == 'OVERDUE':
            label = 1
        else:
            label = 0
        l.append(label)
        f2.write(str(l)+',')

當然,猶豫樣本不均衡的原因,直接使用測試資料會導致模型AUC值較低,所以需要對測試資料集進行一定處理,樣本不均衡問題的解決方案不在此做過多闡述。

5.機器學習模型訓練

使用邏輯迴歸、GBDT、神經網路等常用二分類問題模型,對測試資料進行訓練,再次僅以神經網路模型進行程式碼演示。
匯入資料集

import pandas as pd
dataArray = eval(open('data.txt', 'r', encoding='utf8').read())
df = pd.DataFrame(dataArray)
X = df.iloc[:, 1:8].values
y = df.iloc[:,8].values

建立神經網路模型進行訓練:通過K-FORD交叉驗證對模型進行調參

from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import KFold
from sklearn.metrics import roc_auc_score
import numpy as np

param_hidden_layer_sizes = np.linspace(10, 200, 20)  # 針對引數 “hidden_layer_sizes”, 嘗試幾個不同的值
param_alphas = np.logspace(-4,1,6)  # 對於引數 "alpha", 嘗試幾個不同的值

best_hidden_layer_size = param_hidden_layer_sizes[0]
best_alpha = param_alphas[0]

for size in param_hidden_layer_sizes:
    for val in param_alphas:
        sc = []
        for train_index, test_index in kf.split(X):
            mlp = MLPClassifier(alpha=int(val),hidden_layer_sizes=int(size)).fit(X[train_index],y[train_index])
            y_predict = mlp.predict(X[test_index])
            sc.append(roc_auc_score(y[test_index],y_predict))
        auc_list = np.array(sc)
        auc_avg = auc_list.mean()
        print(auc_avg)
        if auc_avg > best_auc_avg:
            best_auc_avg = auc_avg
            best_hidden_layer_size = size
            best_alpha = val
            auc_std = auc_list.std()
            
print ("auc均值最高時,引數hidden_layer_size值為: %f" % (best_hidden_layer_size))
print ("auc均值最高時,引數alpha值為: %f" % (best_alpha))
print ("此時auc平均值為: %f" % (best_auc_avg))
print ("此時auc標準差為: %f" % (auc_std))
mlp = MLPClassifier(alpha=best_alpha,hidden_layer_sizes=best_hidden_layer_size).fit(X,y)
y_pred = clf.predict(X)
print("模型準確率為: %f" % (clf.score(X,y)))

當獲得最優引數的模型後,對模型進行儲存

from sklearn.externals import joblib
joblib.dump(mlp, 'mlp.pkl')

6.對測試資料進行標記

載入模型,調取test.txt檔案的測試資料,通過SpringBoot獲取特徵陣列,將陣列傳入神經網路獲取label值,然後存入applt_test_pred檔案中,到此整個風控模型專案的搭建就結束了。

import re
import requests
lr = joblib.load('mlp.pkl')
f2 = open('applt_test_pred.txt', 'a+', encoding='utf8')
with open('test.txt', 'r', encoding='utf8') as f:
    for i in f.readlines():
        l = []
        num = re.findall('(\d{6})', i)[0]
        for rule in range(1, 8):
            r = requests.post(
                'http://localhost:9527/v1/getRuleResult?ruleID=' + str(rule) + '&applyId=' + str(num)).text
            l.append(int(r))    
        label = lr.predict(l)[0]
        if label == 1:
            f2.write('OVERDUE'+'\n')
        else:
            f2.write('NORMAL'+'\n')
        f2.flush()

稍後將會把部分程式碼和測試資料集上傳至github中,有疑問的同學請在部落格下方留言或提Issuees,謝謝!