2. 团伙识别基础:什么是团伙识别、常见团伙模式(如刷单、薅羊毛)、特征工程概述

2.1 什么是团伙识别

团伙识别(Collusion Group Detection)是风控与反欺诈领域的关键技术,其目标是从海量用户行为数据中,发现那些有组织、有目的、协同行动的异常群体。与单点欺诈(如单个账号盗刷)不同,团伙欺诈利用多个账号、设备、IP 甚至真实身份,通过分工协作绕过单维度规则,给平台造成巨大损失。

核心区别:单点欺诈依赖个体异常特征(如高频下单、异地登录);团伙欺诈依赖群体关联特征(如共享设备指纹、共用支付账号、规律性时间窗口操作)。

团伙识别在实时计算场景中面临三大挑战:

  • 数据稀疏性:单个成员行为可能完全正常,只有聚合分析才能暴露异常。
  • 时效性要求:刷单、薅羊毛等行为通常在活动开始后几分钟内爆发,需秒级识别。
  • 对抗性演化:团伙不断变换 IP、设备、账号组合,规则需动态更新。

2.2 常见团伙模式

不同业务场景下,团伙欺诈的表现形式差异显著。下表总结了四种典型模式及其行为特征:

模式名称 典型场景 行为特征 识别难点
刷单 电商、外卖、直播打榜 短时间内大量下单、相同收货地址/手机号、支付账号循环使用 订单数据量大,需实时聚合关联
薅羊毛 新用户红包、优惠券、积分兑换 同一设备注册多个账号、IP 段集中、领取时间间隔极短 设备指纹与 IP 可被篡改
恶意注册 社交平台、金融开户 批量生成账号、使用接码平台、头像/昵称模板化 注册门槛低,需结合行为序列分析
虚假流量 广告点击、视频播放、投票 固定时间窗口内大量请求、User-Agent 重复、来源 IP 段固定 流量特征与正常用户高度相似
实战提示:在 Kafka + Spark 实时管道中,刷单和薅羊毛是最常被回放验证的两种模式,因为它们具有明显的时间窗口聚集性和资源共用性,适合用图计算(GraphX)或滑动窗口聚合来检测。

2.3 团伙识别特征工程概述

特征工程是团伙识别的核心环节,其质量直接决定模型效果。团伙识别特征通常分为三类:

  1. 个体行为特征:单用户维度的统计量,如下单频率、登录次数、支付成功率。
  2. 群体关联特征:用户之间的共享资源(设备、IP、手机号、银行卡)数量与密度。
  3. 时序演化特征:行为在时间轴上的聚集程度,如相邻操作间隔、活跃时段分布。

下表列出团伙识别中常用的特征维度及其计算方式:

特征类别 特征名称 计算方式 实时计算可行性
个体行为 单位时间下单量 滑动窗口内订单数 / 窗口时长 高(Spark Structured Streaming 窗口聚合)
个体行为 支付失败率 支付失败次数 / 总支付次数 高
群体关联 共享设备数 同一设备关联的不同用户数 中(需维护设备-用户映射表)
群体关联 IP 段聚集度 同一 C 段 IP 下用户数 / 总用户数 中
时序演化 操作间隔标准差 相邻操作时间差的波动程度 低(需排序后计算,适合微批次)
时序演化 活跃时段熵 24 小时各时段操作分布的熵值 低
注意:实时特征工程中,群体关联特征(如共享设备数)需要维护状态存储(如 Redis 或 Spark StateStore),在回放验证时需确保状态与历史时间点对齐,否则会产生特征穿越问题。

2.4 团伙识别流程架构

下图展示了一个典型的团伙识别实时处理流程,从数据接入到特征计算再到模型判定:

团伙识别实时处理流程架构 用户行为日志 交易流水 设备指纹 Kafka 消息队列 Spark Structured Streaming 滑动窗口聚合 + 状态管理 特征工程(个体+群体+时序) 模型判定 / 规则引擎 告警 / 阻断 / 回放验证 回放验证: 用历史数据模拟实时流

2.5 特征工程在回放验证中的关键作用

在《团伙识别回放验证》课程中,特征工程是连接历史数据与实时模型的桥梁。回放验证的核心逻辑是:

  • 将历史行为日志按时间顺序重新注入 Kafka 主题。
  • Spark Streaming 消费这些消息,在与历史时间对齐的状态下计算特征。
  • 对比模型输出与历史真实标签,评估特征有效性。

以下是一个简单的特征计算代码示例(基于 Spark Structured Streaming):

// 滑动窗口内统计每个用户的订单量
Dataset<Row> windowedOrders = events
    .withWatermark("eventTime", "10 minutes")
    .groupBy(
        functions.window(col("eventTime"), "5 minutes", "1 minute"),
        col("userId")
    )
    .agg(
        count("orderId").as("orderCount"),
        countDistinct("deviceId").as("deviceCount")
    );

// 关联设备共享特征(需外部状态)
Dataset<Row> enriched = windowedOrders
    .join(deviceShareMapping, "deviceId")
    .select(
        col("userId"),
        col("orderCount"),
        col("deviceCount"),
        col("sharedUserCount")
    );
课程关联:本章后续将深入讲解如何利用 Kafka 的精确一次语义(Exactly-Once Semantics)保证回放数据不重不漏,以及 Spark 的 StateStore 如何维护群体关联特征的增量更新。