第4章:常见图谱特征——度数、聚类系数、PageRank 等

图谱特征是什么?说白了,就是把社交网络、交易网络里那些“谁连接谁”的原始关系,提炼成能喂给模型的数值。我最早做反欺诈时,以为只要把节点和边扔进模型就能自动学出规律。后来才发现,没有这些手工特征打底,模型学到的全是噪声。

这一章我们聊聊三个最常用的图谱特征:度数、聚类系数、PageRank。它们是反欺诈变量衍生里的“基础三件套”。理解了它们,你就能看懂大部分图谱风控方案。

一句话总结:这三者分别刻画了节点“有多活跃”、“周围有多抱团”、“有多重要”。

三类核心图谱特征 度数 Degree 聚类系数 Clustering Coefficient PageRank / 中心性 共性:均通过图结构量化节点属性 用于识别异常聚集、虚假交易、风险传递 找“广撒网”钓鱼账号 识别刷单团伙 检测资金网络关键节点

4.1 度数:节点有多“忙”

度数是最简单也是最直观的特征。一个节点的度数,就是它有多少条边连着。在反欺诈场景里,它能直接反映一个实体的“活动量”。

举个例子。你去看一个电商交易图,每个用户就是一个节点,每笔交易就是一条边。如果一个用户在一小时内跟100个完全不同的商家交易,他的度数就很高。正常人会这么干吗?不会。我当时在一个支付反欺诈项目里,发现某个设备ID的度数异常高——它一天内连接了300多个银行卡号。果断拉黑,命中率超过80%。

造特征小技巧:度数可以按时间段(近1小时、近24小时、近7天)分别计算,并做 Z-score 归一化。这样能有效捕捉短期爆发式增长。

但注意了,度数高不一定就是坏人。有些真实的高价值用户(比如黄牛、批发商)度数也高,需要结合其他特征过滤。我个人习惯把度数拆成入度和出度,比如转账给别人的出度 vs. 收到转账的入度。很多欺诈模式是“只出不进”或“只进不出”,一对比就现形。

指标 计算公式 反欺诈含义
节点度数 \(deg(v) = |N(v)|\) 与多少邻居直接相连
入度 指向该节点的边数 收到多少转账/关注
出度 该节点指向外的边数 主动发起了多少行为

4.2 聚类系数:这个小圈子抱团吗?

聚类系数衡量的是“你的朋友之间有多大可能也是朋友”。一个完全抱团的小团体,聚类系数接近1;一个孤立的节点,聚类系数为0。

反欺诈里最经典的应用就是识别“羊毛党团伙”。你想想看,真实用户的社交网络是错综复杂的,朋友之间不一定相互认识。但刷单团伙为了养号,往往会相互关注、相互转账,形成一个高度抱团的簇。这时候聚类系数就会很高。

坑点提示:聚类系数对孤立节点(度数=0或1)会直接赋值为1,因为公式分母为零。我遇到过有人直接用默认值,结果把孤立点当成“完美小团体”……千万别犯这个错。处理方式:对度<2的节点,聚类系数直接设为NaN或-1。

还有一种场景:虚假用户邀请。比如某公司拉新活动,一个用户邀请了大量新用户,但这个用户本身的邻居之间并没有相互连接——聚类系数很低。正常情况下的邀请关系应该是树状,聚类系数趋近于0。如果有人恶意构造环状邀约结构,聚类系数就会显著偏高。这是个很灵的欺诈信号。

4.3 PageRank 及其他中心性指标

PageRank 是最早由谷歌提出来衡量网页重要性的算法,后来被反欺诈领域“拿来主义”——用它找网络里的“关键人物”。

原理很简单:一个节点如果被很多重要节点连接,那它自己也很重要。在资金网络里,PageRank 高的节点往往是资金的中转站或汇缴账户。我曾经在一个洗钱案件里,把PageRank排名前1%的节点全部标记出来,后续人工核实的准确率超过90%。

除了PageRank,还有几个中心性指标可以配合使用:

  • 介数中心性(Betweenness Centrality): 节点出现在多少最短路径上。常用于识别“桥梁”节点——资金过路站。
  • 接近中心性(Closeness Centrality): 节点到其他所有节点的平均距离。能快速找到整个网络的“中心”。
  • 特征向量中心性(Eigenvector Centrality): 类似PageRank但更强调邻居的全局质量。

推荐组合:「度数 + 聚类系数 + 介数中心性」是反欺诈变量衍生的“铁三角”。度数抓活跃度,聚类系数抓抱团,介数抓中转角色。三者一起用,基本覆盖80%的异常模式。

# 示例:用 NetworkX 计算三种特征
import networkx as nx

G = nx.Graph()
G.add_edges_from([ (1,2), (1,3), (2,3), (3,4) ])

degree = dict(G.degree())
clustering = nx.clustering(G)
pagerank = nx.pagerank(G)

print("度数:", degree)
print("聚类系数:", clustering)
print("PageRank:", pagerank)

4.4 避坑指南:我踩过的那些坑

这些特征看着简单,真正落地时全是细节。我整理了几个最常见的坑,希望能帮你少走弯路。

  1. 特征的时间窗口没对齐。 比如度数统计的是全量历史,聚类系数却只用了近7天的子图,两者量纲不同。我建议 统一时间窗口,或者用滚动窗口做多个版本。
  2. 忽略了图的连通性。 当你计算PageRank时,如果图有多个连通分量,每个分量内PageRank总和是1,但分量之间无法比较。解决办法:给每个连通分量单独归一化,或者添加一个全局虚拟节点连接所有分量。
  3. “一阶特征”的陷阱。 度数、聚类系数这些只是节点的一阶属性。你需要在它们之上再衍生二阶交叉特征,比如“度数 × 聚类系数”、“度数/介数”等。我见过有人只用了原始度数做模型,AUC死活上不去,一加交叉特征立刻提升3个点。
  4. 数值分布偏态严重。 度数的分布通常满足幂律——大部分节点度数低,少数节点极高。直接喂给线性模型会出问题。我习惯用 分箱 或者 对数变换 处理。注意分箱时机:先做特征衍生,再做分箱,不能颠倒。

曾经我犯的一个低级错误:在计算PageRank时用了无向图,但实际场景是转账方向。结果重要节点全算反了。记住:有向图一定要用有向版本,否则方向信息丢得一干二净。

好了,这章内容不算多,但每个知识点都够琢磨一阵子。图谱特征衍生的核心就三个字:算、比、验。算出来,对比不同窗口,验证业务逻辑。剩下的就是工程上的细节优化了。