ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

交叉表驱动风控规则挖掘:从样本切片到规则上线的完整链路

交叉表驱动风控规则挖掘:从样本切片到规则上线的完整链路

风控规则这件事,很多人第一反应是找算法团队要模型、要评分卡,但真正在一线做策略的人都知道,业务早期或者数据积累不够的时候,最管用的往往不是复杂模型,而是一批能解释、能落地、能快速迭代的规则。而规则从哪来?不是拍脑袋想出来的,也不是从别人那里抄来的,最扎实的来源之一就是交叉表。

交叉表这个东西听起来朴素,甚至有点"土",但它本质上是对样本做多维度的条件切片,把"什么特征组合下坏样本占比高"这件事直接摊在你面前。你拿一张交叉表,横轴放一个维度,纵轴放另一个维度,格子里填坏样本率或者lift,一眼就能看出哪些组合是高风险区。基于交叉表生成风控规则,说白了就是把这些人眼能识别的高风险格子,翻译成机器能执行的if-else条件。这篇内容适合谁看?适合刚接触风控策略、手里有样本但不知道怎么下手的人,也适合做数据分析想往策略方向转的朋友。我会把从原始数据到交叉表、从交叉表到规则、从规则到验证的完整链路拆开讲,中间穿插我自己踩过的坑和实操中总结的判断标准,尽量让你看完就能在自己的样本上跑一遍。

1. 为什么交叉表是规则挖掘的起点而不是终点

1.1 交叉表在风控策略里的真实定位

先把这个工具的定位说清楚,不然后面容易用偏。交叉表(crosstab)在统计学里就是个频数分布表,但在风控场景下,我们关心的不是频数本身,而是每个格子里的坏样本浓度。一张二维交叉表,行是一个特征的分箱,列是另一个特征的分箱,每个格子里可以放三个数:样本量、坏样本数、坏样本率。坏样本率高的格子就是潜在的高风险规则候选区。

为什么说它是起点?因为交叉表是单变量分析和多变量分析之间的桥梁。单变量分析告诉你"这个特征整体上有区分度",但区分度可能只集中在某个区间;交叉表则告诉你"这个特征在另一个特征的某个区间内,区分度被放大了"。很多强规则不是单特征能表达出来的,而是"年龄在某个段 + 某个行为次数超过阈值"这种组合条件,交叉表恰好就是发现这种组合的天然工具。

但为什么又说它不是终点?因为交叉表只能看两个维度(最多三个,再多就碎得没法看),而真实的风险往往是多因素交织的。交叉表挖出来的是候选规则,不是最终规则。候选规则还要经过覆盖率、稳定性、与其他规则的重叠度、业务可解释性这几道关,才能进规则集。把交叉表当终点的人,往往会挖出一堆在样本上lift很高、上线后却频繁误杀或者根本触发不了的规则,这个问题后面会专门讲。

1.2 交叉表相比决策树和分箱的取舍逻辑

有人会问,既然要挖组合规则,为什么不直接用决策树?决策树确实能自动找分裂点,输出就是规则,看起来更省事。但我实际用下来,交叉表有几个决策树替代不了的优势。

第一是可控性。决策树的分裂是算法按信息增益或者基尼系数选的,它选出来的分裂点你不一定认可,而且树的深度一深,规则就变得又长又难解释。交叉表是你自己指定行和列,分箱是你自己定的,每个格子的业务含义你心里有数,挖出来的规则能直接跟业务方讲明白"为什么这条规则合理"。

第二是样本量透明。决策树的叶节点样本量经常小得可怜,一个叶子只有几十个样本,坏样本率再高也不敢用。交叉表每个格子的样本量是明摆着的,你可以直接设一个最小样本量门槛,比如低于500个样本的格子直接不看,避免在小样本上过拟合。

第三是迭代速度快。业务方今天说"帮我看看某个新特征跟逾期有没有关系",你用交叉表十分钟就能出一版结果,决策树还要调参、还要处理缺失、还要解释树结构。策略早期拼的就是迭代速度,交叉表在这个阶段效率碾压。

当然,交叉表也有明显短板:维度一多就组合爆炸,而且它只看两两交互,三阶以上的交互它表达不了。所以我的做法是交叉表打头阵做快速筛查,决策树或者规则挖掘算法做补充做深度,两者不是替代关系。

1.3 一张合格交叉表该长什么样

在动手写代码之前,先明确目标产物。一张能用来生成规则的交叉表,至少要有这几列:行分箱、列分箱、样本量、坏样本数、坏样本率、以及一个lift值(该格子坏样本率除以整体坏样本率)。lift大于1说明这个组合的风险高于平均水平,lift越高越值得关注。

我习惯再加一列覆盖率,就是该格子样本量占总样本的比例。这个列非常关键,因为一个lift很高但覆盖率只有0.1%的格子,做出来的规则上线后可能一个月都触发不了几次,对整体风险大盘没有实质影响。反过来,lift中等但覆盖率高的格子,往往是真正能压降风险的主力规则。

还有一点容易被忽略:交叉表的行和列分箱不能太细。我见过有人把一个连续特征分成二十个箱,再跟另一个二十箱的特征交叉,出来四百个格子,每个格子平均几十个样本,这种表看着信息量大,实际上全是噪声。我的经验是每个维度控制在4到6个箱,二维交叉最多36个格子,这样每个格子的样本量才有统计意义。分箱太细是新手最容易犯的错,后面会展开讲怎么定分箱。

2. 从原始样本到可分析交叉表的完整预处理链路

2.1 样本定义与好坏标签的确定

交叉表分析的前提是有一份带标签的样本。风控里的标签通常是"坏"和"好",但"坏"的定义必须先跟业务对齐。是逾期超过30天算坏,还是超过60天?观察期多长?表现期多长?这些定义不同,挖出来的规则可能完全不一样。

举个具体的场景:假设我们做的是某类分期场景,定义"坏"为放款后90天内出现逾期超过15天,观察窗口取放款前6个月的行为数据。这个定义要在代码里固化成标签字段,比如bad_flag,1为坏,0为好。标签定义一旦定了,整个分析过程不能中途改,否则交叉表的结论会前后矛盾。

样本里还要注意排除项。比如放款后极短时间内就结清的样本、或者数据严重缺失的样本,这些要么单独处理,要么直接剔除,不要让它们污染交叉表的坏样本率。我一般会在预处理阶段加一个valid_sample标记,把不满足分析条件的样本标出来,后续统计时过滤掉。

2.2 连续特征的分箱策略与阈值选择

交叉表的行和列必须是离散的,所以连续特征要先分箱。分箱方法有等频、等距、卡方分箱、以及基于业务经验的手工分箱。我的建议是优先用业务经验分箱,再用等频分箱做对照。

为什么优先业务分箱?因为风控规则最终要给人看、要给业务方解释。你说"年龄在[23.5, 31.2)区间风险高",业务方一脸懵;你说"年龄在23到31岁之间风险高",大家都能理解。而且业务分箱的边界往往对应真实的业务节点,比如"借款次数1次、2到3次、4次以上",这种分箱出来的规则天然可解释。

等频分箱的好处是每个箱样本量均衡,适合探索阶段快速看趋势。我通常先用等频分箱跑一版,看看坏样本率随特征变化的整体走势,如果走势单调,说明这个特征有区分度,再根据拐点手工调整分箱边界。

代码上,分箱可以用pandas.cut或者pandas.qcut。qcut是等频,cut是自定义边界。这里给一个自定义分箱的示例:

import pandas as pd import numpy as np # 假设 df 是样本数据,含 age 和 bad_flag bins = [0, 23, 31, 40, 50, 100] labels = ['23以下', '23-31', '31-40', '40-50', '50以上'] df['age_bin'] = pd.cut(df['age'], bins=bins, labels=labels, right=False)

注意right=False表示左闭右开,这个细节要统一,不然相邻箱的边界样本会重复计数或者漏计。分箱边界的选择要避免把坏样本率突变的位置切在箱内部,否则会稀释掉信号。

2.3 缺失值处理对交叉表结论的干扰

缺失值在交叉表里是个大坑。很多人直接把缺失样本drop掉,结果发现某个格子的坏样本率特别高,一查才发现是因为这个格子里缺失样本占比很大,而缺失本身就跟风险相关。缺失不是随机发生的,在风控场景里,一个字段缺失往往意味着某种行为没发生或者数据采集有问题,这本身就是信息。

我的处理方式是:把缺失单独作为一个分箱。比如"收入"字段,分箱为"低、中、高、缺失"四档。这样交叉表里缺失格子的坏样本率就能被单独观察,如果缺失格子的坏样本率显著高于其他格子,那"该字段缺失"本身就可以成为一条规则。

代码上,pd.cut对NaN会返回NaN,需要先填充一个特殊值再分箱:

df['income'] = df['income'].fillna(-999) bins = [-1000, 3000, 8000, 20000, 99999999] labels = ['缺失', '低', '中', '高'] df['income_bin'] = pd.cut(df['income'], bins=bins, labels=labels, right=False)

用-999这种哨兵值填充,再在分箱边界里把它单独划一档,是最省事的做法。但要注意哨兵值不能跟真实值冲突,选一个业务上不可能出现的值。

3. 交叉表的核心计算与高风险格子的识别方法

3.1 用pandas构建带统计量的交叉表

基础的双维频数交叉表用pd.crosstab一行就能出,但它默认只给频数,我们要的是坏样本率和lift。所以更实用的做法是用groupby聚合,把样本量、坏样本数、坏样本率、lift一次性算出来。

# 整体坏样本率 overall_bad_rate = df['bad_flag'].mean() # 按两个维度聚合 cross = df.groupby(['age_bin', 'income_bin']).agg( total=('bad_flag', 'size'), bad=('bad_flag', 'sum') ).reset_index() cross['bad_rate'] = cross['bad'] / cross['total'] cross['lift'] = cross['bad_rate'] / overall_bad_rate cross['coverage'] = cross['total'] / len(df)

这段代码跑出来的cross就是我们的分析底表。groupby的好处是能同时算多个统计量,而且后续筛选、排序都方便。注意groupby默认会丢掉含有NaN的分组,所以前面缺失值处理一定要做干净。

如果想让结果更直观,可以把它pivot成矩阵形式:

pivot_lift = cross.pivot(index='age_bin', columns='income_bin', values='lift') pivot_total = cross.pivot(index='age_bin', columns='income_bin', values='total')

这样行是年龄箱,列是收入箱,格子里是lift,旁边再配一张样本量的矩阵,两张表对照着看,哪些格子是"高lift且样本量够"的一目了然。

3.2 lift、坏样本率与覆盖率的三角权衡

识别高风险格子不能只看lift。我总结了一个三角权衡的判断框架,三个指标要一起看:

指标含义判断标准陷阱
lift该格子坏样本率/整体坏样本率一般大于1.5才值得关注lift高但样本少,不可靠
坏样本率格子内坏样本占比绝对值要显著高于整体整体坏率低时,小幅波动就显高
覆盖率格子样本量/总样本一般不低于1%才有实际意义覆盖率过低规则触发不了

具体怎么用这个框架?假设整体坏样本率是5%。一个格子的坏样本率是15%,lift是3,看起来很棒,但如果这个格子只有200个样本、覆盖率0.2%,那这条规则上线后可能一个月触发不了几次,对大盘没有实质贡献,最多作为辅助规则。反过来,一个格子坏样本率8%、lift1.6、覆盖率8%,虽然lift不算惊艳,但覆盖率高,压降的坏样本绝对数量可能更大,这种规则才是主力。

我的实操标准是:主力规则要求lift≥1.5且覆盖率≥3%;辅助规则可以放宽到lift≥2且覆盖率≥1%;lift再高但覆盖率低于0.5%的,只做记录不做上线。这个标准不是死的,要看业务当前的规则集密度,如果已经有几百条规则了,新规则的门槛就要提高,避免规则冗余。

3.3 用热力图快速定位候选格子

数字矩阵看久了容易眼花,我习惯把lift矩阵画成热力图,颜色深的区域就是高风险区。用matplotlib或者seaborn几行代码就能出:

import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(10, 6)) sns.heatmap(pivot_lift, annot=True, fmt='.2f', cmap='Reds') plt.title('Lift Heatmap by Age and Income') plt.show()

热力图的价值在于模式识别。有时候高风险不是一个孤立的格子,而是连续的一片区域,比如"年龄偏大 + 收入偏低"这一整片lift都偏高,那说明风险是沿着这两个维度的组合连续变化的,这时候规则可以写成区间条件而不是精确到某个格子,泛化能力更强。

反过来,如果高风险格子是孤立的、周围格子lift都很低,那要警惕是不是小样本噪声,或者是不是某个特殊群体导致的,这种孤立高点做规则要格外谨慎。

4. 从高风险格子到可执行规则的翻译与打磨

4.1 规则条件的自然语言化与代码化

交叉表里定位到高风险格子后,下一步是把它翻译成规则。翻译分两层:先翻译成自然语言给业务方看,再翻译成代码给系统执行。

自然语言这层不能省。比如一个高风险格子是"年龄23-31 + 收入低",自然语言规则就是"年龄在23到31岁之间且月收入低于3000元的客户,拒绝或转人工"。这句话业务方能听懂,能判断合不合理,能提出修改意见。很多策略同学跳过这步直接写代码,结果规则上线后业务方不认账,返工成本很高。

代码化这层要注意条件的完备性。交叉表的分箱是左闭右开,代码里的条件也要严格对应,不能出现边界遗漏。比如:

def rule_age_income_low(row): return (23 <= row['age'] < 31) and (row['income'] < 3000)

这里23 <= age < 31对应分箱[23, 31),income < 3000对应收入的最低档。如果分箱用的是right=False,代码就必须用左闭右开,两边要对齐,否则会有样本落在规则之外或者重复命中。

还有一点,规则里的阈值最好用变量而不是硬编码。比如把3000抽成配置项,后续调阈值不用改代码。规则多了以后,硬编码的阈值散落在各处,维护起来是灾难。

4.2 规则覆盖率与命中坏样本数的量化评估

一条规则好不好,不能只看lift,要看它能拦住多少坏样本。这个指标叫"命中坏样本数",等于规则覆盖率乘以该格子的坏样本率再乘以总样本量。更直观的算法是:规则命中样本中坏样本的绝对数量。

我一般会算三个数:规则命中样本量、命中坏样本数、命中坏样本占全部坏样本的比例(召回率)。比如一条规则命中1000个样本,其中坏样本150个,全部坏样本是5000个,那这条规则的召回率是3%。召回率低的规则,即使lift高,对整体风险压降的贡献也有限。

这里有个反直觉的点:多条规则叠加时,召回率不是简单相加。规则A和规则B可能命中同一批坏样本,叠加后的召回率小于两者之和。所以评估规则不能一条条孤立看,要看规则集整体的覆盖。实操中我会维护一个"已覆盖坏样本"的集合,每加一条新规则,就把它新覆盖的坏样本加进去,看边际增量。边际增量小的规则,优先级就往后排。

4.3 规则之间的重叠度与优先级排序

规则重叠是规则集管理的核心难题。两条规则如果命中的样本高度重合,那它们本质上是同一条规则,留着只会增加维护成本。衡量重叠度可以用杰卡德相似度:两条规则命中样本的交集除以并集,值越接近1重叠越严重。

def jaccard(rule_a_hits, rule_b_hits): intersection = len(rule_a_hits & rule_b_hits) union = len(rule_a_hits | rule_b_hits) return intersection / union if union > 0 else 0

重叠度超过0.7的两条规则,我一般只保留lift更高或者更可解释的那条。重叠度在0.3到0.7之间的,可以都保留,但要标注关联关系,后续调整时一起看。

优先级排序我用的逻辑是:先按召回率排,召回率相近的按lift排,lift相近的按可解释性排。召回率高的规则放前面,因为它们是压降风险的主力;可解释性好的规则优先保留,因为风控规则要经得起复盘和审计,一条说不清道理的规则,出了问题没法交代。

5. 规则上线前的验证与稳定性排查

5.1 跨时间样本的规则稳定性检验

在训练样本上lift很高的规则,换个时间段可能就失效了。这是交叉表挖规则最大的风险,因为交叉表是对历史样本的拟合,样本一变,格子里的坏样本率就可能大变。

验证方法是时间外采样。把样本按时间切成两段,前一段挖规则,后一段验证。如果规则在后一段的lift仍然大于1.3,说明相对稳定;如果lift掉到1以下甚至反转,说明这条规则是过拟合的,不能用。

我还会看逐月的lift走势。把验证样本按月拆开,算规则每个月的lift,如果lift在几个月内波动很大,比如某个月2.5、下个月0.8,那这条规则不稳定,可能是受某个短期事件影响。稳定的规则,逐月lift应该在一个区间内小幅波动。

这个检验很费时间,但绝对不能省。我见过太多规则在开发样本上表现漂亮,上线后第一个月就误杀一片,最后被迫紧急下线,反而影响业务。稳定性检验是规则上线前的最后一道闸门。

5.2 规则误杀分析与业务可接受度评估

lift和召回率都是统计指标,但规则最终作用在真实客户身上,误杀是要付出代价的。一条规则命中1000个样本,其中850个是好样本,这850个就是被误杀的好客户。误杀率等于1减去格子坏样本率。

误杀率多高可以接受,取决于业务。高客单、低频次的业务,误杀一个客户的损失大,误杀率要压得很低;高频、低客单的业务,误杀容忍度可以高一些。这个标准必须跟业务方一起定,不能策略自己拍。

我的做法是给每条候选规则算一个误杀成本估算:误杀样本量乘以单客平均价值,再跟规则拦住的坏样本损失做对比。如果拦住坏样本挽回的损失明显大于误杀成本,规则才值得上。这个账算出来,业务方也更容易接受规则。

5.3 规则上线后的监控指标设计

规则上线不是终点,是监控的起点。至少要监控四个指标:触发量、触发率、命中坏样本率、规则lift。触发量突然暴涨或暴跌,说明上游数据或者客群结构变了;命中坏样本率下降,说明规则在失效;lift持续走低,要考虑下线或者调整阈值。

监控频率上,高频业务按天看,低频业务按周看。我习惯给每条规则设一个lift的告警线,比如连续两周lift低于1.2就触发告警,人工介入排查。排查方向无非三个:数据源变了、客群变了、还是规则本身过时了。这三个方向的排查顺序是先看数据源,再看客群,最后才怀疑规则,因为数据问题最常见也最好修。

6. 实操中反复踩到的几个坑与应对经验

6.1 分箱过细导致的小样本假信号

这个坑我踩过不止一次。早期做交叉表,总想把分箱切细一点,觉得信息量大,结果出来一堆lift 5以上、样本量只有几十个的格子,兴冲冲做成规则,上线后要么触发不了,要么触发的那几个全是噪声。后来我给自己定了个硬规矩:任何进入候选规则的格子,样本量不得低于总样本的0.5%,且绝对数量不低于300。低于这个门槛的格子,lift再高也只记录不采用。

小样本假信号的根源是统计波动。一个格子只有50个样本,坏样本率稍微波动几个点,lift就大变。样本量越小,这种波动越不可靠。用置信区间能更严谨地判断,但实操中设个样本量门槛就够了,简单有效。

6.2 特征穿越与标签泄漏的隐蔽表现

特征穿越是风控建模里最隐蔽的错误,交叉表分析同样会中招。所谓穿越,就是用了放款之后才能拿到的数据去预测放款前的风险。比如用"放款后30天的还款行为"去挖规则,那规则当然准,但上线时这个数据根本拿不到。

交叉表里穿越的表现是:某个格子的lift高得离谱,比如10以上,而且这个特征跟标签的相关性强得不正常。遇到这种情况,第一反应应该是查这个特征的时间口径,确认它是不是在观察窗口内就能拿到。我一般会在特征清单里给每个特征标注"数据可用时点",分析前先过滤掉时点晚于决策时点的特征。

标签泄漏是穿越的近亲,指的是标签信息以某种形式混进了特征。比如特征里有个"是否进入催收名单",这个字段本身就是坏样本的结果,拿它做规则等于作弊。这类字段要靠业务理解来识别,没有通用的代码检测方法,只能靠对数据字典的熟悉。

6.3 规则阈值微调带来的连锁反应

规则上线后调阈值是常事,但阈值一动,影响的不只是这一条规则。比如把某条规则的收入阈值从3000调到3500,命中样本量会增加,但新增的这批样本可能已经被另一条规则覆盖了,导致规则集整体重叠度上升。更麻烦的是,阈值调整可能改变规则之间的优先级关系,原本排第二的规则可能因为阈值变化变得冗余。

所以调阈值不能单条调,要在规则集层面评估。我的做法是维护一个规则集的模拟环境,任何阈值调整都先在模拟环境里跑一遍,看整体召回率、误杀率、规则重叠度的变化,确认没有负面连锁反应再上线。这个模拟环境其实就是一份历史样本加上规则集的批量执行脚本,不复杂,但能避免很多线上事故。

6.4 交叉表结论与业务直觉冲突时的处理

有时候交叉表挖出来的规则跟业务直觉完全相反。比如业务方坚信"老客户风险低",但交叉表显示某个老客户群体在特定条件下坏样本率很高。这种冲突不能简单用数据压人,也不能盲目信业务。

我的处理方式是先查数据口径,再查样本代表性,最后才讨论结论。数据口径问题最常见,比如老客户的定义在数据里和业务理解里不一致;样本代表性问题次之,比如那个高风险的老客户群体在样本里占比很小,可能是特殊时期的特殊群体。如果口径和代表性都没问题,那就要认真对待这个反直觉结论,它可能揭示了业务没意识到的风险点。这种情况下,我会把交叉表的明细拿给业务方一起看,共同判断,而不是策略单方面下结论。

7. 把交叉表规则挖掘做成可复用的分析流程

7.1 参数化配置让分析脚本适配不同特征对

一次性分析一个特征对,写一段脚本没问题;但要批量分析几十个特征对,就得把流程参数化。我的做法是把"特征对、分箱方案、样本量门槛、lift门槛"都抽成配置,用一个循环批量跑,输出每对特征的候选规则清单。

feature_pairs = [ ('age_bin', 'income_bin'), ('loan_count_bin', 'overdue_history_bin'), # 更多特征对 ] results = [] for f1, f2 in feature_pairs: cross = build_cross_table(df, f1, f2, min_samples=300) candidates = cross[(cross['lift'] >= 1.5) & (cross['coverage'] >= 0.01)] results.append(candidates)

这样跑一遍,所有特征对的候选规则就都出来了,再统一做重叠度分析和优先级排序。参数化的好处是标准统一,不会因为分析不同特征时手松手紧导致标准漂移。

7.2 候选规则清单的标准化输出格式

候选规则清单要有一个固定格式,方便后续评审和入库。我用的字段包括:规则ID、规则描述(自然语言)、规则条件(代码表达式)、命中样本量、命中坏样本数、坏样本率、lift、覆盖率、召回率、误杀率、稳定性评级、建议动作(拒绝/转人工/观察)。

这个清单既是分析产物,也是跟业务方评审的材料,还是后续规则入库的输入。格式统一了,评审效率高,入库也不用手工转换。规则ID的编码我习惯带上特征对和时间戳,方便追溯这条规则是哪次分析、基于哪对特征挖出来的。

7.3 从分析到规则库的衔接要点

分析出来的候选规则,最终要进规则库、进决策引擎。衔接时有几个要点:一是规则的执行顺序要定好,高优先级规则先执行,命中即终止,避免多条规则重复计算;二是规则的版本管理,每次调整都要留版本记录,出问题能回滚;三是规则的失效机制,给每条规则设一个有效期或者复核周期,到期自动提醒复核,避免规则库越积越臃肿。

交叉表分析产出的规则,天然带着分析时的样本时间戳,这个时间戳要跟着规则一起入库。后续复核时,拿新样本重新跑一遍交叉表,对比lift变化,就能判断规则是否还该保留。这套衔接机制建起来之后,规则挖掘就从一次性分析变成了可持续的运营流程。

8. 交叉表之外:什么时候该换更重的工具

交叉表能解决大部分两维组合规则的挖掘,但有些场景它力不从心。第一种是三阶及以上交互,比如"年龄+收入+历史逾期"三者组合才有区分度,两两交叉都看不出来,这时候得上决策树或者规则挖掘算法。第二种是连续特征的精细切分,交叉表的分箱是粗粒度的,如果风险在某个连续区间内是渐变的,交叉表会把它压平,这时候用评分卡或者逻辑回归更合适。第三种是特征数量很大的情况,几十个特征两两交叉就是上千对,人工看不过来,得靠自动化规则挖掘工具批量筛。

判断标准很简单:如果交叉表跑出来的候选规则,经过验证后召回率和稳定性都达标,就没必要上更重的工具;如果反复调整分箱和特征对,候选规则始终不理想,那说明风险模式超出了两维组合的表达能力,该换工具了。工具是为目标服务的,不是越复杂越好,交叉表能解决的问题,用决策树反而是杀鸡用牛刀,还牺牲了可解释性。

我自己在实际操作中的体会是,交叉表最大的价值不在于它多精确,而在于它逼着你去理解每一个格子的业务含义。用决策树的时候,你容易把规则当成黑盒输出直接上线;用交叉表的时候,你必须盯着每个格子想"为什么这个组合风险高",这个思考过程本身就是策略能力的积累。挖出来的规则会过时,但这种对风险结构的理解不会过时。所以哪怕后来用上了更复杂的工具,我还是会先用交叉表把数据摸一遍,心里有个底,再去上模型。这个习惯保持了很多年,至今没觉得过时。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进