结构化数据增强的生成式算法案例:客户交易数据增强

1 基础信息

1.1 案例背景

这是一个用于增强结构化客户交易数据的生成式算法。这种类型的数据增强在金融、电子商务等领域非常有用,可以帮助解决数据不平衡问题或在小数据集上提高模型性能。

1.2 问题定义

给定原始交易数据集D={x₁, x₂, ..., xₙ},其中每条记录包含:

交易金额

交易时间

客户年龄

客户收入水平

交易类别

地理位置

是否为欺诈交易(标签)

目标:生成与原始数据分布相似但多样化的新样本,同时保持字段间的合理关系。

2 实现步骤

2.1 数据预处理

import pandas as pd
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer

# 假设原始数据已加载为df
# 分离数值型和类别型特征
numeric_features = ['amount', 'age', 'income']
categorical_features = ['time_of_day', 'category', 'location']

# 构建预处理管道
preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), numeric_features),
        ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)
    ])

# 对特征进行预处理
X_processed = preprocessor.fit_transform(df.drop('is_fraud', axis=1))
y = df['is_fraud'].values

2.2 构建CVAE模型

import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Lambda, Concatenate
from tensorflow.keras.models import Model
from tensorflow.keras import backend as K

# 定义编码器
def build_encoder(input_dim, latent_dim, label_dim):
    inputs = Input(shape=(input_dim,))
    labels = Input(shape=(label_dim,))
    x = Concatenate()([inputs, labels])
    
    h = Dense(256, activation='relu')(x)
    h = Dense(128, activation='relu')(h)
    
    z_mean = Dense(latent_dim)(h)
    z_log_var = Dense(latent_dim)(h)
    
    return Model([inputs, labels], [z_mean, z_log_var], name='encoder')

# 定义解码器
def build_decoder(latent_dim, output_dim, label_dim):
    latent_inputs = Input(shape=(latent_dim,))
    labels = Input(shape=(label_dim,))
    x = Concatenate()([latent_inputs, labels])
    
    h = Dense(128, activation='relu')(x)
    h = Dense(256, activation='relu')(h)
    outputs = Dense(output_dim, activation='linear')(h)
    
    return Model([latent_inputs, labels], outputs, name='decoder')

# 采样函数
def sampling(args):
    z_mean, z_log_var = args
    batch = K.shape(z_mean)[0]
    dim = K.int_shape(z_mean)[1]
    epsilon = K.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon

# 构建完整CVAE
input_dim = X_processed.shape[1]
latent_dim = 16
label_dim = 1  # 二分类

encoder = build_encoder(input_dim, latent_dim, label_dim)
decoder = build_decoder(latent_dim, input_dim, label_dim)

# 定义输入
inputs = Input(shape=(input_dim,))
labels = Input(shape=(label_dim,))

# 编码
z_mean, z_log_var = encoder([inputs, labels])
z = Lambda(sampling)([z_mean, z_log_var])

# 解码
outputs = decoder([z, labels])

# 定义CVAE模型
cvae = Model([inputs, labels], outputs, name='cvae')

# 添加KL散度损失
reconstruction_loss = tf.keras.losses.mse(inputs, outputs)
reconstruction_loss *= input_dim
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
cvae_loss = K.mean(reconstruction_loss + kl_loss)

cvae.add_loss(cvae_loss)
cvae.compile(optimizer='adam')

2.3 训练模型

# 准备标签数据
y_reshaped = y.reshape(-1, 1)

# 训练模型
history = cvae.fit(
    [X_processed.toarray(), y_reshaped],
    epochs=100,
    batch_size=64,
    validation_split=0.2,
    verbose=1
)

2.4 生成新样本

def generate_samples(num_samples, label_value):
    # 从潜在空间随机采样
    z_samples = np.random.normal(size=(num_samples, latent_dim))
    
    # 创建标签数组
    labels = np.full((num_samples, 1), label_value)
    
    # 解码生成样本
    generated_data = decoder.predict([z_samples, labels])
    
    # 逆变换回原始特征空间
    generated_df = pd.DataFrame(
        data=generated_data,
        columns=preprocessor.get_feature_names_out()
    )
    
    # 对数值特征进行逆标准化
    num_cols = [f'num__{col}' for col in numeric_features]
    generated_df[num_cols] = preprocessor.named_transformers_['num'].inverse_transform(
        generated_df[num_cols]
    )
    
    # 对类别特征进行逆变换(取最大概率的类别)
    cat_cols = [col for col in generated_df.columns if col.startswith('cat__')]
    for orig_col in categorical_features:
        # 获取该原始列的所有one-hot列
        cols = [c for c in cat_cols if c.startswith(f'cat__{orig_col}_')]
        if cols:
            # 取概率最大的类别
            max_idx = generated_df[cols].values.argmax(axis=1)
            generated_df[orig_col] = [cols[i].split('_')[-1] for i in max_idx]
    
    # 只保留原始列名
    final_cols = numeric_features + categorical_features
    generated_df = generated_df[final_cols]
    generated_df['is_fraud'] = label_value
    
    return generated_df

# 生成欺诈和非欺诈样本各1000个
generated_fraud = generate_samples(1000, 1)
generated_non_fraud = generate_samples(1000, 0)

# 合并生成的数据
augmented_data = pd.concat([df, generated_fraud, generated_non_fraud], ignore_index=True)

3 关键技术与优化

3 .1 条件控制

通过将标签作为条件输入,可以控制生成特定类别的样本,解决类别不平衡问题。

3.2 特征关系保持

数值字段的统计特性通过标准化/逆标准化保持

类别字段的关系通过one-hot编码和argmax保持

3.3 数据验证机制

def validate_generated_data(original, generated):
    # 比较统计特性
    for col in numeric_features:
        print(f"\n{col} 统计比较:")
        print("原始数据:", original[col].describe())
        print("生成数据:", generated[col].describe())
    
    # 比较类别分布
    for col in categorical_features:
        print(f"\n{col} 分布比较:")
        print("原始数据:\n", original[col].value_counts(normalize=True))
        print("生成数据:\n", generated[col].value_counts(normalize=True))

validate_generated_data(df, augmented_data)

3.4 边界控制:在生成后可添加业务规则验证

def apply_business_rules(df):
    # 例如:年龄不能为负
    df['age'] = df['age'].clip(lower=18, upper=100)
    # 交易金额不能超过收入的一定比例
    df['amount'] = np.where(df['amount'] > df['income']*0.5, 
                           df['income']*0.5, 
                           df['amount'])
    return df

4 评估指标

统计相似性:比较原始数据和生成数据的统计特性

机器学习效用:使用原始数据、增强数据分别训练模型,比较性能

多样性指标:计算生成样本之间的平均距离

Novelty检测:确保生成样本不是简单复制原始样本

5 扩展应用

这种结构化数据增强方法可以应用于:

金融风控中的欺诈检测

医疗诊断中的罕见病例数据增强

制造业中的异常检测

客户流失预测中的小类别增强

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值