← Back to Blog

Case Study - Sales Transaction Fraud Detection

Jan 13, 2018 · WeifanD

1. Introduction (引言)

欺诈行为(Fraud)是当今商业环境中各行业的顽疾,直接威胁企业的运营安全与营收底线。在汉语语境中,“欺诈”意指以狡猾奸诈之手段蒙骗他人。古籍《战国策·燕策二》记载:“齐田单欺诈骑劫,卒败燕军,复收七十城以复齐”,描述了军事上的诈术;而《汉书·西域传》中提到的“欺诈单于”,则涉及外交层面的欺骗。到了宋代,苏澈在论及役人制度时指出:“盖定差乡户人有家业,欺诈逃亡之弊,比之雇募浮浪,其势必少”,揭示了经济活动中因利益驱动而产生的欺诈风险。

随着商业模式的数字化,欺诈的表现形式愈发隐蔽且多样化,主要可分为以下几类:

  • 信贷欺诈 (Credit Fraud):在民间信贷或银行领域,不法分子通过伪造个人信息、虚构社会关系网络或美化财务报表来骗取贷款。
  • 点击欺诈 (Click Fraud):在企业广告渠道合作中,利用自动化脚本、僵尸网络或“点击农场”制造虚假流量,以此骗取广告预算,导致营销 ROI 严重失真。
  • 交易欺诈 (Transaction Fraud):在线下或线上销售场景中,销售人员或外部人员为了获取不当利益(如佣金、提成、奖金),通过虚报销售记录、篡改交易金额、伪造退货流程或串通客户刷单来损害企业利益。

无论欺诈的形式如何演变,其核心目的都是造成被欺诈方(个人或企业)的经济损失。因此,构建高效的反欺诈策略不仅具有显著的经济意义,更是维护市场公平与社会信用的关键所在。本案例研究将聚焦于销售交易欺诈,通过数据挖掘技术识别异常交易模式,为企业风控提供数据支持。

2. Data Overview (数据概览)

针对销售交易欺诈行为,我们获取了一份涵盖 6,000 名销售人员4,000 多种商品 的历史交易记录数据集。数据粒度精确到每一笔单笔交易,包含销量(Quantity)与交易金额(Value)等核心指标,并附带了部分审计结果标签。

2.1 数据结构初探

原始数据呈现为典型的高维稀疏表格,主要字段定义如下:

  • ID: 销售人员唯一标识 (Factor)
  • Prod: 产品唯一标识 (Factor)
  • Quant: 交易数量 (Integer)
  • Val: 交易金额 (Double)
  • Insp: 审计结果标签 (ok: 正常, unkn: 未知/未审计, fraud: 确认欺诈)

数据前几行示例如下:

#> # A tibble: 6 x 5
#>       ID   Prod Quant   Val   Insp
#>       
#> 1     v1     p1   182  1665   unkn
#> 2     v2     p1  3072  8780   unkn
#> 3     v3     p1 20393 76990   unkn
#> 4     v4     p1   112  1100   unkn
#> # ... with 2 more rows

2.2 数据分布特征

对全量数据进行描述性统计分析,我们发现该数据集具有三个显著的挑战性特征,这直接决定了后续建模的难点:

#>        ID              Prod            Quant                Val         
#>  v431   : 10159   p1125  :  3923   Min.   :      100   Min.   :   1005  
#>  v54    :  6017   p3774  :  1824   1st Qu.:      107   1st Qu.:   1345  
#>  v426   :  3902   p1437  :  1720   Median :      168   Median :   2675  
#>  v1679  :  3016   p1917  :  1702   Mean   :     8442   Mean   :  14617  
#>  v1085  :  3001   p4089  :  1598   3rd Qu.:      738   3rd Qu.:   8680  
#>  v1183  :  2642   p2742  :  1519   Max.   :473883883   Max.   :4642955  
#>  (Other):372409   (Other):388860   NA's   :13842       NA's   :1182     
#>     Insp       
#>  ok   : 14462  
#>  unkn :385414  
#>  fraud:  1270  
#>                
#>                
#>                
#> 

核心挑战深度分析:

  1. 严重的类别不平衡 (Class Imbalance)

    • 总样本量约 40 万条,其中确认为欺诈(fraud)的仅 1,270 条,占比不足 0.3%
    • 正常交易(ok)约占 3.6%,而绝大多数(96.1%)处于未审计或未知状态(unkn)。
    • 影响:这种极端的偏态分布使得传统分类模型(如逻辑回归)极易偏向多数类,导致模型倾向于预测所有样本为“正常”,从而产生极高的漏报率(False Negative Rate)。
  2. 长尾分布 (Long-tail Distribution)

    • 销售人员和产品的分布极度不均(Power Law 分布)。头部销售人员(如 v431)拥有上万条记录,贡献了大部分交易量;而大量尾部人员记录极少,甚至只有几条。
    • 产品销量跨度极大,最大值达到 4.7 亿,均值却仅为 8,442。这说明存在极端的异常大单(Outliers),这些大单往往是高额欺诈的高发区,但也可能是合法的大宗交易,难以区分。
  3. 多维缺失值 (Complex Missing Data)

    • 虽然整体缺失比例看似不高(销量缺失约 3.5%,金额缺失约 0.3%),但缺失并非随机分布(MCAR)。
    • 若特定销售人员或特定产品的关键指标大面积缺失,可能暗示着系统录入漏洞、人为故意隐瞒或业务流程异常。

3. Data Preprocessing (数据预处理)

针对上述挑战,我们采取了分阶段的精细化预处理策略,而非简单的“删除”或“填充”。

3.1 缺失值的多维度治理 (Missing Data Strategy)

对于缺失值,简单的全局删除或均值填充往往会破坏数据的业务逻辑,甚至掩盖欺诈线索。我们需要从 “销售人员 (Salesperson)”“产品 (Product)” 两个维度进行交叉审视。

分析逻辑: 假设我们有上千个检测目标,如果某人的所有关键信息缺失,对他个人而言是 100% 的信息丢失,但在百万级样本中可能被稀释为微不足道的 0.01%。因此,必须计算每个 ID 和每个 Prod 的缺失率,识别“系统性缺失”。

我们首先筛选出同时缺失 QuantVal 的记录(即完全无度量信息的空壳交易):

#>      [,1] [,2]
#> [1,] 6016 4548

(注:此处显示有 6016 个销售人员和 4548 个产品涉及此类缺失)

进一步统计完全缺失的记录总数:

#> [1] 888

在 401,146 条总记录中,仅有 888 条是完全缺失度量信息的。我们评估了删除这些记录的影响:

#> [1] 3.5 0.3

(注:分别代表销量和金额的总体缺失比例)

以及删除后对标签分布的影响:

#> 
#>    ok  unkn fraud 
#>   3.6  96.1   0.3

决策: 由于删除这 888 条记录对整体样本结构(特别是稀有的欺诈样本)影响微乎其微(<1%),且这些记录无法提供任何建模价值,我们决定直接剔除这些共同缺失的记录。

3.2 缺失模式的可视化诊断

为了更精细地处理非共同缺失的情况,我们绘制了各维度的缺失率分布图。以下 R 代码展示了如何按销售人员和产品分组,计算缺失比例并进行可视化诊断:

library(ggplot2)
library(dplyr)
library(gridExtra)

# 定义通用绘图函数:计算分组缺失率并绘图
plot_missing_rate <- function(data, group_var, measure_var, title_label) {
  data %>% 
    group_by({{group_var}}) %>% 
    summarise(missing_rate = round(sum(is.na({{measure_var}}))/n(), 2)) %>% 
    arrange(desc(missing_rate)) %>% 
    filter(missing_rate > 0.1) %>% # 仅展示缺失率大于10%的组,聚焦主要问题
    ggplot(aes(x = reorder({{group_var}}, missing_rate), missing_rate)) +
    geom_point(aes(colour = ifelse(missing_rate > 0.9, '#d95f02', '#363636')), size=2) +
    labs(x = title_label, y = "Missing Rate", title = paste("Missing Rate by", title_label)) +
    coord_flip() +
    theme_classic() +
    theme(legend.position = "none")
}

# 生成四个子图:人员销量缺失、人员金额缺失、产品销量缺失、产品金额缺失
p1 <- plot_missing_rate(sales, ID, Quant, "Salesperson (Qty)")
p2 <- plot_missing_rate(sales, ID, Val, "Salesperson (Val)")
p3 <- plot_missing_rate(sales, Prod, Quant, "Product (Qty)")
p4 <- plot_missing_rate(sales, Prod, Val, "Product (Val)")

# 布局展示 (2x2 矩阵)
layout <- matrix(c(1,2,3,4), 2, 2, byrow=TRUE)
multiplot <- function(..., layout=matrix(c(1,2,3,4), 2, 2, byrow=TRUE)){
  plots <- list(...)
  do.call(grid.arrange, c(plots, list(layout=layout)))
}

multiplot(p1, p2, p3, p4, layout=layout)

plot of chunk missing-analysis

图表解读与处理策略:

  1. 极端缺失个体:上图显示有 7 名销售人员 的销量记录缺失率接近 100%(红色点)。然而,他们的金额数据是存在的。
    • 策略:这表明可能是录入系统故障或人为只填金额不填数量。我们可以利用同产品下的平均单价($Price = Val / Quant$)反推销量,或使用该销售人员历史同类产品的中位数销量进行插补 (Imputation),而非直接删除,以保留潜在的欺诈线索。
  2. 无效产品:发现 2 个产品 没有任何销量记录,仅有金额或完全为空。
    • 策略:这极可能是系统测试数据、录入笔误或已下架的无效 SKU。除非有特殊的业务背景,否则将其标记为异常噪声,在建模前予以剔除或单独归类,避免干扰模型学习。
  3. 长尾产品的缺失:大量尾部产品的缺失率波动较大。
    • 策略:对于低频产品,采用全局众数同类产品均值填充,避免因样本过少导致的过拟合。

3.3 稀疏交易与小样本问题 (Few Transactions)

初步清洗后,产品分布的方差依然巨大。最少记录的产品仅十余条,而热门产品高达数千条。这种稀疏性 (Sparsity) 会导致统计特征不稳定,使得基于统计的规则容易误判。

我们采用 Kolmogorov-Smirnov (KS) 检验 来评估不同产品间价格分布的同质性。如果某些产品的价格分布与整体显著不同(P-value < 0.05),则可能需要单独建模或进行分箱处理。

# 示例:对高频产品进行 KS 检验,判断其价格分布是否显著偏离整体
# 选取交易次数大于100的产品作为高频产品集合
high_freq_prods <- sales %>% 
  group_by(Prod) %>% 
  filter(n() > 100) %>% 
  pull(Prod) %>% 
  unique()

# 对前10个高频产品进行 KS 检验
ks_results <- lapply(high_freq_prods[1:10], function(p) {
  sample_data <- sales$Val[sales$Prod == p]
  # 检验该产品的价格分布是否与整体价格分布一致
  ks.test(sample_data, sales$Val, alternative = "two.sided")
})

# 输出 P 值,若 P < 0.05 则拒绝原假设,认为分布显著不同
sapply(ks_results, function(x) x$p.value)

通过 KS 检验,我们可以识别出那些价格行为异常的产品群体,将它们作为高风险特征输入模型,或者针对这些群体建立独立的子模型。

4. Feature Engineering & Modeling Strategy (特征工程与建模策略)

(本节为根据上下文逻辑补充的核心内容,旨在完善案例分析)

面对 0.3% 的欺诈率和海量稀疏数据,直接套用基础模型往往效果不佳。我们需要构建针对性的特征工程 pipeline 和建模策略。

4.1 特征构造 (Feature Construction)

为了捕捉欺诈模式,我们构建了以下三类特征:

  1. 聚合统计特征 (Aggregated Statistics)

    • salesperson_avg_qty: 该销售员历史平均销量。
    • product_std_val: 该产品历史交易金额的标准差(衡量价格波动性,波动大可能意味着管理混乱)。
    • deviation_ratio: 当前交易金额与该销售员/该产品历史均值的偏离度($|Val - Mean| / Std$),偏离度越大,风险越高。
    • salesperson_fraud_rate: 该销售员历史被标记为欺诈的比例(如果有历史标签)。
  2. 时间序列特征 (Temporal Features)

    • time_since_last_trade: 距离该销售员上一笔交易的时间间隔。欺诈往往发生在非正常时间段(如深夜)或突发高频交易。
    • is_weekend: 交易是否发生在周末(某些行业周末交易异常可能意味着风险)。
  3. 交互特征 (Interaction Features)

    • is_new_prod_for_sales: 该销售员是否首次销售该产品。新组合(New Pair)往往缺乏历史行为参照,风险较高。
    • qty_val_ratio: 销量与金额的比值,用于检测单价异常。

4.2 处理类别不平衡 (Handling Imbalance)

针对 fraud 样本极少的问题,单一的重采样往往不够,我们采用组合策略:

  • 欠采样 (Undersampling):对 unknok 类进行随机欠采样或 Tomek Links 清理,使正负样本比例调整至 1:10 左右,减少多数类主导。
  • SMOTE (Synthetic Minority Over-sampling Technique):在特征空间合成少数类样本,增加欺诈样本的多样性,防止过拟合。
  • 代价敏感学习 (Cost-Sensitive Learning):在 XGBoost 或 LightGBM 模型中,设置 scale_pos_weight 参数(例如设为 num_negative / num_positive),大幅提高误判欺诈样本(False Negative)的惩罚权重,迫使模型关注少数类。

4.3 模型选择与评估

鉴于数据的表格特性和非线性关系,我们首选 Gradient Boosting Decision Trees (GBDT) 系列算法(如 XGBoost, LightGBM, CatBoost)。

  • 优势:它们对缺失值有原生处理能力,能自动捕捉特征间的复杂交互,且对异常值不敏感。
  • 评估指标:由于类别极度不平衡,准确率 (Accuracy) 已失效。我们将重点关注 AUC-ROC, Precision-Recall Curve (PR-AUC) 以及 Recall (召回率)。在反欺诈场景中,宁可误报(False Positive)也不能漏报(False Negative),因此 Recall 是首要优化目标。

5. Conclusion (结论)

本案例研究展示了在处理大规模销售交易数据时,如何应对缺失值、长尾分布和极端类别不平衡这三大难题。

  1. 精细化清洗:不能简单地全局删除缺失值,必须结合业务维度(人、货)进行差异化处理,利用可视化手段识别系统性缺失。
  2. 统计洞察:通过描述性统计和 KS 检验,我们识别出了数据中的异常模式和无效噪声,为特征工程奠定了基础。
  3. 建模方向:未来的工作重点将放在特征工程的深度挖掘和不平衡学习算法的调优上。目标是在控制误报率(False Positive)的前提下,最大化召回率(Recall),从而精准拦截潜在的销售欺诈行为。

通过这一全流程的数据挖掘方案,我们不仅能提升模型的预测性能,更能为业务部门提供可解释的风险预警,助力企业构建更坚固的风控防线,将事后追责转变为事前预防。

Reference

  1. 如何界定是否属于欺诈?
  2. Chawla, N. V., Bowyer, K. W., Hall, L. O., & Kegelmeyer, W. P. (2002). SMOTE: synthetic minority over-sampling technique. Journal of artificial intelligence research, 16, 321-357.
  3. Friedman, J. H. (2001). Greedy function approximation: a gradient boosting machine. Annals of statistics, 1189-1232.
  4. Chen, T., & Guestrin, C. (2016). Xgboost: A scalable tree boosting system. In Proceedings of the 22nd acm sigkdd international conference on knowledge discovery and data mining (pp. 785-794).
#Case Study #Data Science #Fraud Detection #R Language #Machine Learning