news 2026/10/29 20:11:38

IEEE-CIS欺诈检测Notebook实战:特征工程与时间切分避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
IEEE-CIS欺诈检测Notebook实战:特征工程与时间切分避坑指南

简介:面向数据科学竞赛学习者与风控建模初学者的IEEE-CIS欺诈检测EDA资源包,围绕二分类欺诈识别任务展开,帮助读者理解如何从原始交易数据中完成探索性分析与特征准备。压缩包共6个文件,以3个Python脚本、1个Jupyter Notebook为主,辅以说明文档与配置项,整体约1.02MB,体积轻量却覆盖数据清洗、可视化报告与特征工程三条主线。其中Notebook承载深入的EDA分析流程,脚本文件分别封装数据清理、图表报告与特征整理函数,便于按模块复用和二次改造。已有599人学习,适合希望快速上手Kaggle欺诈检测赛题、梳理EDA思路并积累可复用工具函数的读者参考。

1. 一份被反复回炉的欺诈检测 Notebook:它到底能解决什么

拿到 IEEE-CIS-Fraud-Detection 这个资源包时,我第一反应不是看模型结构,而是先翻它的数据读取和特征工程部分。原因很简单:欺诈检测这类任务,模型换三四个,AUC 可能只动零点几个点;但特征怎么拼、时间怎么切、类别怎么编码,一步走错,后面全白搭。这份以 Jupyter Notebook 为载体的资源,核心价值不在某个炫技模型,而在于它把「交易表 + 身份表」双表合并、时间特征拆解、类别高基数编码、交叉验证切分这几件脏活累活串成了一条能跑通的流水线。适合谁?手上有一份结构化交易流水、想做二分类风险识别、又不想从零搭特征管道的从业者。新手能照着单元格顺序跑通,熟手能直接拆出特征工程模块塞进自己的训练框架。它解决的不是「教你什么是欺诈检测」,而是「给你一条能复现、能改参数、能定位问题的基线」。

2. 双表合并与时间特征:先把数据底座搭稳

2.1 交易表与身份表的合并逻辑

这份资源的数据结构是典型的「主表 + 辅表」:交易表记录每笔交易的金额、产品类型、卡片信息、邮箱域名等,身份表记录持卡人的设备信息、浏览器版本、屏幕分辨率等。两张表通过一个交易标识关联,但身份表并不是每笔交易都有记录,存在大量缺失。常见做法是左连接,以交易表为主,身份表字段缺失就保留 NaN,交给后面的树模型自己处理。这里有个容易翻车的点:有人图省事用内连接,结果样本量直接掉一大截,而且掉掉的往往正是信息不全的可疑交易,模型学出来的分布就偏了。

import pandas as pd # 读入两张表,低内存模式避免大文件撑爆内存 train_txn = pd.read_csv('train_transaction.csv', low_memory=False) train_idn = pd.read_csv('train_identity.csv', low_memory=False) # 左连接:以交易表为主,身份信息缺失保留 NaN train = train_txn.merge(train_idn, on='TransactionID', how='left') print(train.shape) print(train['isFraud'].mean()) # 正样本比例,通常很低

这段代码的关键在how='left'和low_memory=False。前者保证不丢交易样本,后者避免 pandas 分块推断类型时把某些列读成混合类型再报警告。合并后先看正样本比例,这个数字决定了后面评估指标怎么选——正样本极低时,准确率没有意义,得看 AUC 和召回。

2.2 时间戳拆解与周期性特征

交易时间是一个连续数值,直接丢进模型等于让树去硬切分,效率低。合格的做法是把它转成「相对起始时间的天数 + 小时 + 星期几」这类可解释特征。欺诈行为往往有强时间模式:深夜、凌晨、发薪日前后,风险分布不一样。我一般会保留原始时间差特征,同时派生小时和星期,让模型自己选。

# 以最小时间戳为基准,转成相对天数 train['TransactionAmt'] = train['TransactionAmt'].astype(float) start = train['TransactionDT'].min() train['day'] = (train['TransactionDT'] - start) / (24 * 60 * 60) train['hour'] = (train['TransactionDT'] // 3600) % 24 train['weekday'] = (train['TransactionDT'] // (24 * 3600)) % 7

TransactionDT单位是秒,除以 86400 得到天数,取模得到小时和星期。这里不要用真实日历时间,因为数据本身是脱敏的相对时间,硬套日期反而引入噪声。参数上,day保留浮点,hour和weekday取整,后续如果做目标编码要注意按时间切分,避免未来信息泄漏。

2.3 高基数类别特征的编码取舍

卡片品牌、邮箱域名、浏览器版本这些列,取值动辄几百上千。直接 one-hot 会炸维度,直接标签编码又会让树模型误以为类别间有大小关系。这份 Notebook 里常见的处理是:对频次高的类别保留,低频的归为「其他」,再做标签编码或频次编码。我的经验是,频次编码对树模型更友好,因为它把「这个域名出现多少次」变成了一个连续风险信号。

# 频次编码:把类别出现次数作为新特征 for col in ['card1', 'card2', 'addr1', 'P_emaildomain']: if col in train.columns: freq = train[col].value_counts() train[f'{col}_freq'] = train[col].map(freq)

value_counts统计每个取值出现次数,map回填。注意频次要在训练集上统计,验证集和测试集用同一张映射表,否则就是数据泄漏。这一步做完,原始类别列可以保留也可以丢弃,取决于模型对类别列的原生支持程度。

3. 交叉验证与模型基线:别让时间泄漏毁掉评估

3.1 按时间切分而非随机切分

欺诈检测最隐蔽的坑是随机切分。交易数据有时间顺序,随机打乱会让「未来」的样本进入训练集,评估分数虚高,上线就崩。正确做法是按day排序后切分,或者用时间序列交叉验证。这份资源里如果用的是随机 KFold,我建议直接改成按时间分组的切分方式,哪怕分数掉几个点,那也是真实水平。

from sklearn.model_selection import TimeSeriesSplit # 按时间排序后做时间序列交叉验证 train_sorted = train.sort_values('TransactionDT').reset_index(drop=True) tscv = TimeSeriesSplit(n_splits=5) for fold, (tr_idx, va_idx) in enumerate(tscv.split(train_sorted)): X_tr, y_tr = train_sorted.iloc[tr_idx], train_sorted.iloc[tr_idx]['isFraud'] X_va, y_va = train_sorted.iloc[va_idx], train_sorted.iloc[va_idx]['isFraud'] # 这里接模型训练

TimeSeriesSplit保证训练集永远在验证集之前,n_splits=5表示切五折。参数上,如果数据时间跨度大,可以增大折数;如果正样本在时间上分布极不均匀,要检查每折的正样本比例,必要时做分层时间切分。

3.2 基线模型选型与评估指标

这份 Notebook 通常以梯度提升树作为基线,原因很直接:结构化表格数据、大量缺失值、类别特征混合,树模型对缺失和异常值天然鲁棒,不需要精细归一化。评估指标用 AUC 为主,辅以召回率在固定误报率下的表现。别只看 AUC,业务上更关心「在可接受的误报量下能抓多少欺诈」。

from sklearn.metrics import roc_auc_score import lightgbm as lgb # 简单基线:只取数值特征,缺失交给 LightGBM 处理 feat_cols = [c for c in train_sorted.columns if train_sorted[c].dtype != 'object' and c not in ['isFraud', 'TransactionID']] model = lgb.LGBMClassifier(n_estimators=500, learning_rate=0.05, num_leaves=64) model.fit(X_tr[feat_cols], y_tr) pred = model.predict_proba(X_va[feat_cols])[:, 1] print('AUC:', roc_auc_score(y_va, pred))

num_leaves=64控制树复杂度,learning_rate=0.05配合 500 棵树是常见起点。如果 AUC 上不去,先别调参,回头检查特征里有没有泄漏列,比如某些在交易发生后才能拿到的字段。

3.3 缺失值比例与特征筛选

身份表合并后会有大量列缺失率超过 90%。这些列不是直接删,而是先看缺失本身有没有信号——某些设备信息缺失,可能恰恰意味着交易环境异常。我的做法是保留缺失率极高的列,但额外加一列「该行缺失字段数量」作为特征,让模型自己判断。

# 统计每行缺失字段数,作为环境异常信号 idn_cols = [c for c in train.columns if c.endswith('_idn') or c in train_idn.columns] train['missing_cnt'] = train[idn_cols].isna().sum(axis=1)

isna().sum(axis=1)按行统计缺失数。这个特征在树模型里往往能排进重要性前列,因为它隐式刻画了「这笔交易的信息完整度」。

4. 避坑与排查:五个让我回炉重跑的血泪记录

4.1 现象:本地 AUC 0.95,换时间切分掉到 0.78

原因:随机切分导致时间泄漏,模型记住了未来样本的分布。解决:改用TimeSeriesSplit或按day阈值切分,重新评估。别心疼掉下来的分数,那才是上线后的真实预期。

4.2 现象:合并后样本量莫名减少

原因:误用了内连接,或者关联键类型不一致(一边是整数一边是字符串),导致匹配失败。解决:合并前统一TransactionID类型,用how='left',合并后对比行数是否等于主表行数。

4.3 现象:频次编码后验证集分数异常高

原因:频次统计用了全量数据,验证集信息泄漏进训练特征。解决:频次映射只在训练折上拟合,验证折用map应用同一张表,未出现的类别填 0 或全局默认值。

4.4 现象:LightGBM 训练报类别特征类型错误

原因:类别列里混了数值和字符串,pandas 推断成 object,但模型要求 category 类型或整数编码。解决:显式转换astype('category'),或者统一做标签编码后再喂给模型,别让 pandas 自己猜。

4.5 现象:内存爆掉,Notebook 跑到一半被杀

原因:一次性读入全部列且未指定数据类型,浮点默认 float64,几十万行乘几百列直接吃满内存。解决:读入时用dtype参数字典把已知数值列降为 float32,类别列设为 category,或者分块读取后拼接。

5. 从 Notebook 到可复用模块:我的收尾习惯

把这份资源跑通只是第一步,真正省时间的是把它拆成可复用模块。我一般会做三件事:第一,把特征工程部分抽成独立函数,输入原始两张表、输出特征矩阵,函数内部固定「先合并、再时间拆解、后频次编码」的顺序,避免每次手动改单元格顺序出错;第二,把时间切分的索引逻辑固化下来,训练脚本和评估脚本共用同一套切分,杜绝「训练用一套、评估用另一套」的玄学;第三,留一个最小验证脚本,只跑前一万行,确认管道不报错再上全量,这个习惯帮我省过好几次半夜等结果的时间。

def build_features(txn, idn): df = txn.merge(idn, on='TransactionID', how='left') start = df['TransactionDT'].min() df['day'] = (df['TransactionDT'] - start) / 86400 df['hour'] = (df['TransactionDT'] // 3600) % 24 for col in ['card1', 'addr1', 'P_emaildomain']: if col in df.columns: df[f'{col}_freq'] = df[col].map(df[col].value_counts()) return df

这个函数刻意不包含模型训练,只负责特征,方便单独测试。参数上,start用当前数据集的最小值,如果训练和测试分开处理,要保证测试集用训练集的start,否则时间基准不一致。验证方法很简单:拿一小批数据跑一遍,检查输出列数、缺失比例、时间特征范围是否符合预期,再上全量。

从那以后我每次拿到这类双表结构化数据,都强制先跑一遍「合并行数校验 + 时间切分校验 + 小样本冒烟」这三步,再谈调参。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 20:09:01

WMI开发文档解读:WBEM、CIM、WQL与远程管理实践

简介:这是一份面向 Windows 开发与系统管理人员的英文 WMI 开发文档,适合需要理解管理数据模型、编写自动化脚本或开发管理应用程序的 C、C、Visual Basic 及 .NET 开发者查阅。压缩包内仅含 1 个 PDF 文件,体积约 57.3MB,结构完整…

作者头像 李华
网站建设 2026/10/29 20:04:11

常见的智能体介绍

国内外主流智能体Agent介绍 ✅ 国内智能体 1. WorkBuddy(腾讯云) 研发企业:腾讯云(CodeBuddy团队) 底层调用模型:原生腾讯混元Hy3/Hy4;兼容DeepSeek、GLM、Kimi、MiniMax,支持自定义API Key切换多模型 特色与功能 桌面本地执行型办公智能体,俗称腾讯小龙虾Agent;支…

作者头像 李华
网站建设 2026/10/29 19:53:24

(已解决)关于fpga的时序收敛问题记录

问题记录 1、Axi stream或者Axi Lite和逻辑通信时,因时钟时序不匹配,造成时序不收敛。 2、从别处考来的工程中,自带使用set_clock_groups -asynchronous组时,-of objects[get pins U_xxxx/xxxx…]&#xff…

作者头像 李华
网站建设 2026/10/29 19:52:20

【移动元件库】15.时间选择器

时间选择器是移动端场景下用于选择日期、时间或同时选择二者的输入类组件,属于级联选择器在日期选择场景的垂直化应用,其选项关联交互逻辑与级联选择器同源,复杂度相对更低。 1️⃣动图效果 元件库目前共提供三类时间选择器,分别为…

作者头像 李华
网站建设 2026/10/29 19:50:08

鸣潮模组怎么装:WuWa-Mod 的 .pak 安装与配置,三步完成启动

鸣潮模组怎么装:WuWa-Mod 的 .pak 安装与配置,三步完成启动 【免费下载链接】wuwa-mod Wuthering Waves pak mods 项目地址: https://gitcode.com/GitHub_Trending/wu/wuwa-mod 日常任务里每个技能都要等冷却条,跑图时体力耗尽又得停下…

作者头像 李华