?本項目主要實現邏輯如下:
1.將測試數據分表格存入mysql資料庫。
2.設計知識圖譜關係圖,按照設計思路將node與對應的relationship存入neo4j資料庫。
3.設計一套有效的特徵,提取特徵用於機器學習模型進行訓練,用以風控判斷。
4.將提取特徵的cypher語句存入mysql,使用SpringBoot搭建微服務,用以讀取api獲取每個進件的特徵矩陣。
5.使用邏輯回歸、GBDT,神經網路等模型在訓練數據上搭建風控模型,通過AUC指標判斷模型的準確率。
6.使用測試數據,通過最優模型獲取預測結果。
下面講解具體實現過程:
我們準備了如下幾個測試數據集
將以上所有數據導入mysql
由測試數據可直接得到以下關係: 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中,得到類似於以下結構的數據
因為最終傳入機器學習模型的訓練應該是一個二維數組,所以我們需要從neo4j中提取每個進件的特徵。實際項目中,可能需要設計幾十個或上百個規則才可以達到需要的準確率,在這裡以7個特徵為例做講解。
我們需要將以上規則存入mysql,用以後續調用
代碼結構如下:業務代碼放在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值較低,所以需要對測試數據集進行一定處理,樣本不均衡問題的解決方案不在此做過多闡述。
使用邏輯回歸、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)
載入模型,調取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+ ) else: f2.write(NORMAL+ ) f2.flush(
推薦閱讀: