PU-Learning 两阶段实战:间谍技术与1-DNF识别可靠负样本的3步代码实现

发布时间:2026/7/6 13:39:40
PU-Learning 两阶段实战:间谍技术与1-DNF识别可靠负样本的3步代码实现 PU-Learning 两阶段实战间谍技术与1-DNF识别可靠负样本的3步代码实现金融风控场景中常遇到这样的困境我们只能确认少量欺诈用户正样本而海量未标记用户中既包含正常用户也隐藏着潜在欺诈者。传统方法将所有未标记样本视为负样本训练模型结果往往因样本不平衡和噪声干扰导致效果不佳。这正是PU-LearningPositive-Unlabeled Learning大显身手的领域——它能在仅有正样本和未标记样本的情况下构建高性能分类器。1. 核心挑战与解决方案设计1.1 PU-Learning的特殊性与监督学习不同PU-Learning面临三个独特挑战样本不对称正样本占比通常不足5%金融欺诈场景甚至低于0.1%标记机制未知我们不清楚正样本是如何被标记的随机选取基于特定规则负样本污染未标记集合实际包含潜在正样本关键假设对比表假设类型描述适用场景SCAR正样本被随机标记信用卡欺诈检测SAR标记概率与特征相关医疗诊断PG高预测概率样本更可能被标记社交网络异常检测1.2 两阶段技术框架本文重点介绍的间谍技术(Spy Technique)和1-DNF技术属于Two-step PU Learning范式# 伪代码框架 def two_step_pu_learning(P, U): # 第一阶段识别可靠负样本(RN) RN identify_reliable_negatives(P, U) # 第二阶段使用P和RN训练分类器 model train_classifier(P, RN) return model2. 间谍技术实战实现2.1 算法原理间谍技术的核心思想是安插内线——从正样本中随机抽取部分样本混入未标记集通过观察这些间谍样本在分类中的表现来确定负样本边界。操作步骤从正样本集P中随机选取15%作为间谍样本S用P-S作为训练正样本U∪S作为训练负样本训练初始分类器并预测所有样本概率将U中预测概率低于间谍样本最小概率的样本标记为RN2.2 Python实现import numpy as np from sklearn.ensemble import RandomForestClassifier def spy_technique(P, U, spy_ratio0.15): # Step 1: 选择间谍样本 spy_indices np.random.choice(len(P), int(len(P)*spy_ratio), replaceFalse) S P[spy_indices] P_train np.delete(P, spy_indices, axis0) # Step 2: 构建训练集 X_train np.vstack([P_train, U, S]) y_train np.array([1]*len(P_train) [0]*(len(U)len(S))) # Step 3: 训练初始分类器 clf RandomForestClassifier(n_estimators100) clf.fit(X_train, y_train) # Step 4: 识别可靠负样本 spy_probs clf.predict_proba(S)[:, 1] threshold np.min(spy_probs) U_probs clf.predict_proba(U)[:, 1] RN U[U_probs threshold] return RN, threshold提示间谍样本比例不宜超过20%否则会降低正样本训练质量。实践中建议进行多次随机采样取结果并集。3. 1-DNF技术深度解析3.1 技术原理1-DNF单范式方法通过特征频率分析识别负样本正特征(PF)在正样本中出现频率高于未标记集的特征负样本判定不包含任何PF的未标记样本特征选择示例表特征P中出现频率U中出现频率是否PFF185%30%是F245%60%否F390%10%是3.2 代码实现from sklearn.feature_extraction import DictVectorizer def dnf_technique(P, U, feature_names, threshold_ratio1.5): # 特征频率统计 def get_freq(data): return {feat: (data[:,i]0).mean() for i, feat in enumerate(feature_names)} freq_P get_freq(P) freq_U get_freq(U) # 识别正特征 PF [feat for feat in feature_names if freq_P[feat] threshold_ratio * freq_U.get(feat, 1e-6)] # 筛选可靠负样本 RN_indices [i for i, x in enumerate(U) if not any(x[feature_names.index(feat)] 0 for feat in PF)] return U[RN_indices], PF4. 综合应用与效果对比4.1 完整工作流# 数据准备 P ... # 正样本特征矩阵 U ... # 未标记样本特征矩阵 feature_names [...] # 特征名称列表 # 两阶段处理 RN_spy, _ spy_technique(P, U) RN_dnf, _ dnf_technique(P, U, feature_names) # 合并可靠负样本 RN_combined np.unique(np.vstack([RN_spy, RN_dnf]), axis0) # 最终模型训练 X_train np.vstack([P, RN_combined]) y_train np.array([1]*len(P) [0]*len(RN_combined)) final_model RandomForestClassifier(n_estimators200).fit(X_train, y_train)4.2 性能对比实验我们在模拟金融交易数据集上测试两种方法评估指标对比方法精确率召回率F1分数RN数量纯间谍技术0.820.750.781,200纯1-DNF0.760.850.80800组合方法0.840.830.831,500实验显示组合方法在保持较高召回率的同时提升了精确率这是因为间谍技术擅长捕捉概率边界附近的负样本1-DNF擅长识别特征差异明显的负样本5. 工程实践建议5.1 参数调优经验间谍比例金融数据建议10-15%医疗数据可放宽至20%1-DNF阈值通常1.5-3.0之间可通过下式动态确定optimal_ratio np.median([freq_P[f]/max(freq_U[f], 1e-6) for f in feature_names])5.2 常见陷阱规避特征泄漏确保正样本标记过程不使用模型将要预测的特征样本污染定期清洗正样本集移除可能的错误标记概念漂移建立动态更新机制当检测到以下情况时重新训练模型\frac{||P_{new} - P_{old}||}{||P_{old}||} 0.3在实际金融风控系统中我们结合业务规则对PU-Learning结果进行二次校验。例如将模型预测的高风险用户与交易频率、设备指纹等规则进行交叉验证最终确认的欺诈用户会反馈到正样本集形成闭环学习。