4. 数据集构建与EDA:模拟交易数据生成、特征分布分析、标签不平衡问题可视化
在构建实时异常交易检测模型之前,高质量的数据集是模型性能的基石。本章将引导你从零开始构建一个模拟交易数据集,并通过探索性数据分析(EDA)深入理解数据特征分布与标签不平衡问题。我们将使用Python的numpy、pandas和matplotlib库完成这一过程。
4.1 模拟交易数据生成
由于真实金融交易数据涉及用户隐私且难以获取,我们采用蒙特卡洛模拟方法生成合成数据。数据生成需遵循以下原则:
- 时间连续性:交易时间戳按秒递增,模拟真实流水。
- 特征多样性:包含数值型(金额、频率)、类别型(交易类型、渠道)和时序型特征。
- 异常注入:人为注入约1%的异常样本,模拟欺诈、盗刷等行为。
数据生成参数表
| 特征名称 | 数据类型 | 正常分布 | 异常分布 | 说明 |
|---|---|---|---|---|
transaction_id |
字符串 | UUID4 | UUID4 | 唯一标识 |
timestamp |
datetime | 均匀间隔 | 均匀间隔 | 模拟时间戳 |
amount |
float | LogNormal(μ=4.5, σ=0.8) | LogNormal(μ=6.0, σ=1.2) + 随机大额 | 交易金额(元) |
transaction_type |
类别 | {消费, 转账, 充值} 各33% | 转账占比70% | 交易类型 |
channel |
类别 | {APP, Web, POS} 各33% | Web占比60% | 交易渠道 |
hour_of_day |
int | 均匀分布 0-23 | 凌晨2-5点占比40% | 交易小时 |
is_fraud |
int | 0 | 1 | 标签(1为异常) |
import numpy as np
import pandas as pd
from datetime import datetime, timedelta
np.random.seed(42)
n_samples = 100000
fraud_ratio = 0.01
# 生成时间戳
base_time = datetime(2024, 1, 1)
timestamps = [base_time + timedelta(seconds=i) for i in range(n_samples)]
# 生成金额
amounts = np.where(
np.random.rand(n_samples) < fraud_ratio,
np.random.lognormal(mean=6.0, sigma=1.2, size=n_samples) * np.random.uniform(1, 5, n_samples),
np.random.lognormal(mean=4.5, sigma=0.8, size=n_samples)
)
# 生成标签
labels = np.random.choice([0, 1], size=n_samples, p=[1-fraud_ratio, fraud_ratio])
# 生成类别特征
types = np.where(labels == 1,
np.random.choice(['转账', '消费', '充值'], size=n_samples, p=[0.7, 0.2, 0.1]),
np.random.choice(['转账', '消费', '充值'], size=n_samples, p=[0.33, 0.33, 0.34]))
channels = np.where(labels == 1,
np.random.choice(['APP', 'Web', 'POS'], size=n_samples, p=[0.2, 0.6, 0.2]),
np.random.choice(['APP', 'Web', 'POS'], size=n_samples, p=[0.33, 0.33, 0.34]))
# 生成小时特征
hours = np.where(labels == 1,
np.random.choice(range(24), size=n_samples, p=[0.05]*2 + [0.1]*3 + [0.02]*19),
np.random.choice(range(24), size=n_samples))
df = pd.DataFrame({
'transaction_id': [f'TXN{i:08d}' for i in range(n_samples)],
'timestamp': timestamps,
'amount': np.round(amounts, 2),
'transaction_type': types,
'channel': channels,
'hour_of_day': hours,
'is_fraud': labels
})
print(f"数据集形状: {df.shape}")
print(f"异常比例: {df['is_fraud'].mean():.4f}")
4.2 特征分布分析
EDA的核心是理解每个特征在正常样本与异常样本上的分布差异。我们重点关注以下三个维度:
- 数值特征分布:交易金额的分布形态,异常样本是否呈现长尾或双峰。
- 类别特征分布:交易类型和渠道在两组样本中的占比差异。
- 时序特征分布:交易发生的小时分布,异常是否集中在特定时段。
EDA关键发现:在模拟数据中,异常交易的金额均值约为正常交易的3.2倍,且标准差更大;凌晨2-5点的异常交易占比是正常时段的4倍以上。
下面通过SVG图展示交易金额在正常与异常样本上的分布对比:
4.3 标签不平衡问题可视化
异常交易检测是典型的类别不平衡问题。在模拟数据中,异常样本仅占1%左右。这种极端的标签不平衡会导致模型倾向于预测多数类(正常),从而忽略少数类(异常)。
不平衡问题的三个核心影响:
- 模型偏差:分类器会偏向多数类,导致召回率极低。
- 评估误导:整体准确率可能高达99%,但异常样本几乎全被漏检。
- 训练困难:梯度更新被多数类主导,少数类学习信号微弱。
注意:在后续章节中,我们将采用过采样(SMOTE)、欠采样、代价敏感学习或异常检测算法(如孤立森林)来缓解不平衡问题。EDA阶段必须量化不平衡程度,为后续策略选择提供依据。
下面通过SVG图展示标签分布及不平衡比率:
4.4 特征相关性初步分析
在EDA的最后阶段,我们通过计算特征与标签的相关性,初步筛选对异常检测有区分度的特征。下表展示了模拟数据中主要特征与is_fraud的相关系数:
| 特征 | 与标签的相关系数 | 区分度评估 |
|---|---|---|
amount |
0.32 | 中等正相关 |
hour_of_day |
-0.18 | 弱负相关 |
transaction_type (转账) |
0.25 | 中等正相关 |
channel (Web) |
0.21 | 弱正相关 |
timestamp (秒级) |
0.01 | 几乎无关 |
EDA结论:交易金额、交易类型(转账)和交易渠道(Web)是区分异常与正常交易的关键特征。后续特征工程将围绕这些特征进行交叉组合与变换。
至此,我们完成了模拟交易数据集的构建与EDA分析。下一阶段将基于这些发现进行特征工程与模型训练。