智能风控决策引擎系统可落地实现方案(四)风控决策实现

一、风控决策介绍

互联网金融风控场景中,除了根据规则(反欺诈策略、政策准入)对用户进行准入或拒绝外,还会对用户进行更多维度的授信评估,如根据模型评分对用户进行评级,输出用户可借额度、期限、费率等,如何利用模型结果和规则结果来决策输出?常见的决策方式包括:决策树、决策表、决策矩阵。本文将主要介绍决策相关设计实现,并给出rete算法实现方案。

二、决策树

决策树也称规则树,是由多个规则按一定分支及流程编排而成,直观显示如下:

在这里插入图片描述

对比规则集示例如下:

在这里插入图片描述

其相同之处在于都可以抽象成多个规则,而差异在于规则集的决策结果为所有规则触发策略的最优先策略,规则间无因果顺序;而决策树则会由多个规则触发结果再进行逻辑运算所得,规则间存在因果顺序。基于此决策树的DSL建模可抽象为规则部分和决策部分,规则部分可复用之前的DSL结构和代码逻辑。

决策树可以抽象为规则、决策两部分,其中规则的结果为中间状态D1、D2、D3、D4,决策部分为中间状态的组合,中间状态为D1和D3时,输出结果为A,依次类推可得到不同的结果

在这里插入图片描述

决策树抽象成DSL语法:


decisiontrees:
  - decisiontree:
    name: decisiontree_1
    depends: [feature_1, feature_2]
    rules:
    - rule:
      rule_name: "rule_1"
      conditions:
      - condition:
        feature: feature_1
        operator: GE
        value: 20
      logic: AND 
      decision: D1 - 当前规则的决策结果
    - rule:
      rule_name: "rule_2"
      conditions:
      - condition:
        feature: feature_1
        operator: LT
        value: 20
      logic: AND 
      decision: D2 - 当前规则的决策结果
    - rule:
      rule_name: "rule_3"
      conditions:
      - condition:
        feature: feature_2
        operator: EQ
        value: true
      logic: AND 
      decision: D3 - 当前规则的决策结果
    - rule:
      rule_name: "rule_4"
      conditions:
      - condition:
        feature: feature_2
        operator: EQ
        value: false
      logic: AND 
      decision: D4 - 当前规则的决策结果
    decisions: - 决策树的决策规则
    - decision:
      depends: [D1, D3] - 依赖D1和D3
      logic: AND 
      output: A - 决策结果
    - decision:
      depends: [D1, D4] - 依赖D1和D4
      logic: AND
      output: B - 决策结果
    - decision:
      depends: [D2, D3] - 依赖D2和D3
      logic: AND
      output: C - 决策结果
    - decision:
      depends: [D2, D4] - 依赖D2和D4
      logic: AND
      output: D - 决策结果

对决策树DSL进行解析:

//define decision tree struct
type Decisiontree struct {
    Name      string     `yaml:"name"`
    Depends   []string   `yaml:"depends,flow"`
    Rules     []Rule     `yaml:"rules,flow"`
    Decisions []Decision `yaml:"decisions,flow"`
}
//parse decision tree output type is string,also can be func()
func (dt *Decisiontree) parse() string {
    log.Printf("decisiontree %s parse ...\n", dt.Name)
    var result = make(map[string]bool, 0)
    //reuse rule parse
    for _, rule := range dt.Rules {
        result[rule.Decision] = rule.parse()
    }
    for _, decision := range dt.Decisions {
        if parseDecision(result, decision) {
            return decision.Output
        }
    }
    return ""
}
//parse decision
func parseDecision(result map[string]bool, decision Decision) bool {
    var rs = make([]bool, 0)
    for _, depend := range decision.Depends {
        if data, ok := result[depend]; ok {
            rs = append(rs, data)
        }
    }
    final, _ := operator.Boolean(rs, decision.Logic)
    return final
}

编写测试用例测试决策树解析:

func TestDecisionTree(t *testing.T) {
    internal.SetFeature("feature_1", 18) 
    internal.SetFeature("feature_2", false)
    dsl := dslparser.LoadDslFromFile("decisiontree.yaml")
    rs := dsl.ParseDecisionTree(dsl.Decisiontrees[0])
    if rs == "D" {
        t.Log("result is ", rs) 
    } else {
        t.Error("result error,expert D, result is ", rs) 
    }   
}

执行后效果如下:

在这里插入图片描述

决策表
决策表是通过对多个条件交叉组合成的一张表格,形式如下图示例:

在这里插入图片描述

对决策表进行抽象建模发现与决策树的抽象如出一辙,拆分成规则以及规则组合后的决策两部分,而交叉组合的方式也与决策树一致,因此决策表和决策树展示形式不同,代码实现保持一致,这里不再重复实现。

三、决策矩阵

决策矩阵也叫交叉决策表,它由横向X特征纵向Y特征两个特征维度的不同条件组合决定,输出结果为满足条件对应的X&Y “交叉单元格”的值。

在这里插入图片描述

在风控场景中,可对两个决策模型的输出结果进行交叉决策,输出的结果作为用户风险等级(Rank Grade)。由于模型结果表示概率,一般是-11间的浮点数,所以需要对模型结果进行一定的转换,转成方便表达的正整数(模型分数),如1-200区间,再进行分箱和组合。

对决策矩阵进行抽象建模,可以理解为横向规则X1、X2纵向规则Y1、Y2、Y3,对两个规则的决策结果再进行逻辑运算组合。

规则矩阵DSL如下:

decisionmatrixs:
  - decisionmatrix:
    name: decisionmatrix_1
    depends: [model_1, model_2]
    rules:
    - rule:
      rule_name: X1
      conditions:
      - condition:
        feature: model_1
        operator: LT
        value: 80
      logic: AN
      decision: D1
    - rule:
      rule_name: X2
      conditions:
      - condition:
        feature: model_1
        operator: GE
        value: 80
      logic: AND 
      decision: D2
    - rule:
      rule_name: Y1
      conditions:
      - condition:
        feature: model_2
        operator: LT
        value: 100
      logic: AND
      decision: D3
    - rule:      
      rule_name: Y2
      conditions:
      - condition:
        feature: model_2
        operator: GE
        value: 100
      - condition:
        feature: model_2
        operator: LT
        value: 150
      logic: AND
      decision: D4
    - rule:
      rule_name: Y3
      conditions:
      - condition:
        feature: model_2
        operator: GE
        value: 150
      logic: AND
      decision: D5
    decisions:
    - decision:
      depends: [D1, D3]
      logic: AND
      output: A
    - decision:
      depends: [D1, D4]
      logic: AND
      output: A
    - decision:
      depends: [D1, D5]
      logic: AND
      output: B
    - decision:
      depends: [D2, D3]
      logic: AND
      output: A
    - decision:
      depends: [D2, D4]
      logic: AND
      output: B
    - decision:
      depends: [D2, D5]
      logic: AND
      output: C

规则矩阵DSL解析如下:

//define decision matrix
type DecisionMatrix struct {
    Name      string     `yaml:"name"`
    Depends   []string   `yaml:"depends,flow"`
    Rules     []Rule     `yaml:"rules,flow"`
    Decisions []Decision `yaml:"decisions,flow"`
}
//parese decision matrix
func (dm *DecisionMatrix) parse() string {
    log.Printf("decisionmatrix %s parse ...\n", dm.Name)
    depends := internal.GetFeatures(dm.Depends)
    var result = make([]string, 0)
    for _, rule := range dm.Rules {
        if rule.parse() { //true will be added
            result = append(result, rule.Decision)
        }
    }
    for _, decision := range dm.Decisions {
        //compare slice []{x,y}
        if compareSlice(decision.Depends, result) {
            return decision.Output
        }
    }
    return ""
}
//compare two slices
func compareSlice(s1, s2 []string) bool {
    s1Str := strings.Replace(strings.Trim(fmt.Sprint(s1), "[]"), " ", "", -1)
    s2Str := strings.Replace(strings.Trim(fmt.Sprint(s2), "[]"), " ", "", -1)
    return s1Str == s2Str
}

编写测试用例测试决策矩阵解析:

func TestDecisionMatrix(t *testing.T) {
    internal.SetFeature("model_1", 85) 
    internal.SetFeature("model_2", 180)
    dsl := dslparser.LoadDslFromFile("decisionmatrix.yaml")
    rs := dsl.ParseDecisionMatrix(dsl.DecisionMatrix[0])
    if rs == "C" {
        t.Log("result is ", rs) 
    } else {
        t.Error("result error,expert C, result is ", rs) 
    }   
}

执行结果如下:

在这里插入图片描述

四、额度表达式及其他金融产品包

信贷风控场景下,除了获取用户评级,决策引擎一般还会输出额度、费率、期限、有效期等不同金融决策。

额度表达式

评估授信额度,一般根据用户风险评级、历史借贷次数(新/老用户),组合映射不同额度值。

在这里插入图片描述

此时又看到了熟悉的界面,就是通过决策表或决策树来实现,最终额度输出可能更复杂一些,需要根据特征乘不同系数,或给定最大上限额或最小上限,可以组成一个表达式。表达式支持:加减乘除、平方开方、取大取消等运算。

const MAX_CREDIT_LIMIT = 12000  //max credit limit
coeff := internal.getFeature("coeff")  //额度系数
//modelCreditLimit 评级额度映射表
finalCreditLimit := min((modelCreditLimit * coeff), MAX_CREDIT_LIMIT)

金融产品包
除了额度外,还会输出费率、期限、额度有效期等,这部分可以按用户风险评级或其他特征进行映射配置,组合成金融产品包,方便管理,映射配置方式也使用决策树、决策表形式。

五、决策节点融入决策流

决策节点一般作为决策流的最后一个执行节点(end节点不算执行节点),所以它一般会输出最后的决策结果。

在这里插入图片描述

六、更多思考

总结DSL结构及解析抽象复用

基础算子:

  • 比较运算:operator.Compare

  • 布尔运算:operator.Boolean

基础DSL:

  • 条件表达式dslparse.condition

  • 规则 dslparse.rule

  • 决策 dslparse.decision

节点DSL:

  • 决策流dslparse.workflow

  • 规则集dslparse.ruleset

  • 决策树dslparse.decisiontree

  • 决策矩阵dslparse.decisionmatrix

  • 条件网关dslparse.conditional

  • AB网关dslparse.abtest

规则集、决策树、决策矩阵、条件网关都可以分解用规则+决策来实现。

构造rete网络

实现决策树和决策矩阵是把每个可选的条件都置为单独规则处理,而rule_1rule_2存在互斥关系,如果一个为true,另一个则无需计算,rule_3rule_4也是如此。如果决策树更加复杂,一个选择即一个分支,将存在更多无需计算的规则。为了提高决策效率,一个简单的实现方案:可将互斥的规则增加个属性标签“规则组”,将决策上下文缓存,已获得true结果的规则组下规则不再参与重复匹配计算。

另一实现方式是规则引擎常用的rete算法,它提供了更高效的模式匹配,这里展开讨论一下rete实现的异同,首先涉及几个基础概念:

  • facts 事实,对应理解为数据挖掘的特征。

  • rule 规则,由and或or组成的多个条件conditions,由if…then表示,if部分也叫lhs(left-hand-side),then部分为rhs(right-hand-side)

  • module 模式,最小原子条件,对应理解为condition。

rate算法,主要是改进match处理过程,其处理流程如下:

在这里插入图片描述

核心引擎部分即为pattern matcher 模式匹配和agenda议程 (处理冲突和执行决策)。它将所有规则最终编译成一个网络(rete拉丁语是网络的意思),包括alpha网络和beta网络。

在这里插入图片描述

构建rete网络流程:
网络的构建始于根节点Root Node(黑色)

构建Alpha网络,根据rule_1获取执行条件(module模式)中参数类型,添加Type Node节点(Object Type Node),并将module作为AlphaNode加入网络(已添加忽略),重复执行所有rule下的module,构建Alpha内存表 (Alpha Memory 黄色节点)。

构建Beta网络,Beta Node节点,Beta(i)左输入节点为Beta(i-1),右输入节点为Alpha(i),连接节点Join Node(绿色节点)

规则执行部分封装成Terminal Node(灰色节点)

有了beta网络,对同一rule下不同module只执行一次,对于更复杂的情况,beta网络提高了速度,避免了重复匹配。rete算法本质也是空间换时间,如果整个网络非常大,会比较消耗内存资源。

关于决策引擎和风控系统更多内容将在后续文章中逐步展开分析。

原文地址:https://mp.weixin.qq.com/s?__biz=MzIyMzMxNjYwNw==&mid=2247483825&idx=1&sn=3ebf7c8ad42f870e48db56ca6bb99ade&chksm=e8215ea1df56d7b7d9b1c653c61ef011d72d46d090845d91deba39f635d03ce1282eaa433485&cur_album_id=2282168918070968323&scene=189#wechat_redirect

<think>嗯,用户这次明确要求了解风控决策引擎的架构设计,而且给出了三篇专业文献作为参考。看来用户可能是金融科技领域的从业者,或者正在设计相关系统。从用户引用的资料看,特别关注实时处理、规则管理和风控应用场景,说明需要的是落地性强的架构方案。 用户引用的文献[1]提到决策引擎要具备自动化决策和动态规则管理能力,文献[2]则强调要兼容简单和复杂两种决策流,文献[3]补充了贷前风控的具体实现细节。这些都需要在架构设计中体现出来。 上次我给出的通用大数决策引擎架构偏技术栈,这次应该更聚焦风控场景的特殊需求。比如金融风控对实时性要求极高(文献[3]提到<50ms响应),还要考虑规则回溯、灰度发布等合规需求。文献[2]提到的特征加工策略也很关键——简单规则直接全特征计算,复杂规则需要分段执行避免资源浪费。 在技术选型上,风控场景比通用决策更强调稳定性和可追溯性。规则引擎用Drools没问题,但存储层需要强化HBase的决策日志持久化能力(文献[3]的历史决策详情需求)。另外文献[1]提到的模型漂移检测在金融反欺诈中尤为重要,这块要用Prometheus+KS检验实现。 用户可能还隐含了性能疑虑,毕竟千万级QPS是风控系统常态。上次提到的多级缓存和向量化计算仍然适用,但针对金融场景要补充两点:1)Redis集群必须部署持久化机制防宕机 2)Flink流处理要配置精确一次语义(exactly-once)。 最后生成的三个问题都紧扣风控痛点:灰度更新对应文献[3]的规则回溯需求,规则冲突检测来自文献[1]的性能分析器模块,贷前风控则是文献[3]的核心场景。这样能帮用户延伸到具体业务实现层面。</think>以下是风控决策引擎的架构设计与核心组成部分,结合高并发、实时风控与合规性需求设计: --- ### **一、风控决策引擎架构设计(分层架构)** ```mermaid graph TD A[数据接入层] --> B[实时计算层] B --> C[规则/模型决策层] C --> D[决策执行层] D --> E[监控回溯层] ``` --- ### **二、核心组成模块** #### 1. **数据接入层** - **多源数据支持** - 实时流数据:Kafka(用户行为日志)、Flink CDC(数据库变更捕获)[^2] - 外部数据:API网关(征信/黑名单接口)、Redis集群(缓存实时特征) - **关键设计**:数据缓冲队列(防峰值冲击) + 数据格式标准化(Protobuf/AVRO) #### 2. **实时计算层** - **特征工程** - 流式特征:Flink窗口计算(如近1小时交易次数$$ \text{count}_{txn} = \sum_{t=now-1h}^{now} \delta_{txn} $$) - 图特征:Neo4j实时关系查询(设备关联用户数$$ N_{device-link} $$) - **模块化处理**:支持"短路计算"(命中黑名单则终止后续流程)[^2] #### 3. **规则/模型决策层** | **组件** | **技术实现** | **风控场景应用** | |----------------|----------------------------------|-------------------------------| | **规则引擎** | Drools(Rete算法优化) | 反欺诈规则集(如:$ \text{IF } \text{amount} > 10万 \text{ AND } \text{location} \notin \text{常用地} $) | | **模型服务** | TensorFlow Serving(GPU加速) | 信用评分模型($ \text{score} = f(\text{特征向量}) $) | | **策略路由** | 动态AB测试框架 | 新规则灰度发布 | #### 4. **决策执行层** - **决策流程控制** ```java // 伪代码:贷前风控决策流[^3] DecisionFlow flow = new FlowBuilder() .addStep("黑名单拦截", Rules::checkBlacklist) // 优先执行 .addStep("特征加工", Features::calculate) // 按需调用外部数据 .addStep("信用模型", Models::predict) // 复杂模型计算 .setTimeout(100ms) // SLA约束 .build(); ``` - **结果输出** - 实时响应:API网关(Spring Cloud Gateway) - 持久化存储:HBase(决策日志)、Elasticsearch(全文检索) #### 5. **监控回溯层** - **合规性设计** - 决策追溯:存储原始数据+规则快照[^3] - 重新执行:异常中断后恢复(依赖历史特征) - **实时监控** - 性能指标:Prometheus(P99时延 < 100ms) - 规则命中看板:Grafana动态仪表盘 --- ### **三、风控场景关键技术方案** #### 1. **高性能设计** - **规则引擎优化** - Rete算法索引:预编译规则网络 - 本地缓存:Caffeine(缓存高频规则集) - **计算加速** - 向量化执行:Apache Arrow内存数据格式 - 硬件加速:GPU模型推理(TensorRT) #### 2. **动态更新保障** ```mermaid graph LR A[规则管理台] -->|版本发布| B(Git仓库) B -->|触发| C[配置中心Nacos] C -->|热加载| D[决策节点] D -->|原子切换| E[规则执行器] ``` - **一致性机制**:版本号校验 + 灰度发布(10%流量先行) #### 3. **金融合规设计** - **审计追踪** - 全链路日志:TraceID串联(Jaeger实现) - 数据脱敏:字段级加密(如身份证$$ \text{ID} = \text{110***1990} $$) - **敏感操作** - 双人复核:关键规则修改需二次审批 - 变更留痕:数据库Binlog+操作日志 --- ### **、典型风控应用** 1. **贷前审核** - 规则集:收入负债比($ \text{DTI} = \frac{\text{月负债}}{\text{月收入}} \leq 50\% $)[^3] - 模型:申请反欺诈评分(GBDT算法) 2. **交易监控** - 实时规则:同设备多账户交易($ \Delta t < 5\text{s} \rightarrow \text{报警} $) - 图计算:资金环路检测(Neo4j路径查询) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值