当只有几个正样本,你如何分类无标签数据

假设您有一个交易业务数据集。有些交易被标记为欺诈,其余交易被标记为真实交易,因此您需要设计一个模型来区分欺诈交易和真实交易。 假设您有足够的数据和良好的特征,这似乎是一项简单的分类任务。 但是,假设数据集中只有15%的数据被标记,并且标记的样本仅属于一类,即训练集15%的样本标记为真实交易,而其余样本未标记,可能是真实交易样本,也可能是欺诈样本。您将如何对其进行分类? 样本不均衡问题是否使这项任务变成了无监督学习问题? 好吧,不一定。

此问题通常被称为PU(正样本和未标记)分类问题,首先要将该问题与两个相似且常见的“标签问题”相区别,这两个问题使许多分类任务复杂化。第一个也是最常见的标签问题是小训练集问题。当您有大量数据但实际上只有一小部分被标记时,就会出现这种情况。这个问题有很多种类和许多特定的训练方法。另一个常见的标签问题(通常与PU问题混为一谈)是,训练的数据集是被完全标记的但只有一个类别。例如,假设我们拥有的只是一个非欺诈性交易的数据集,并且我们需要使用该数据集来训练一个模型,以区分非欺诈性交易和欺诈性交易。这也是一个常见问题,通常被视为无监督的离群点检测问题,在机器学习领域中也有很多工具专门用于处理这些情况(OneClassSVM可能是最著名的)。

相比之下,PU分类问题涉及的训练集,其中仅部分数据被标记为正,而其余数据未标记,可能为正或负。 例如,假设您在银行工作,可以获得很多交易数据,但只能确认其中一部分是100%真实的。 我将要举的例子将与伪钞相关。这个例子包含一个1200张钞票的数据集,其中大部分未标记,只有一部分被确认为真钞。 尽管PU问题也很普遍,但是与前面提到的两个分类问题相比,这个问题被讨论的次数通常要少得多,而且很少有实际的示例或库可供使用。

这篇文章的目的是提出一种可行的办法来解决PU问题,这个方法我最近在一个分类项目中使用过。 它基于Charles Elkan和Keith Noto的论文《Learning classifiers from only positive and unlabeled data》(2008年),以及Alexandre Drouin撰写的一些代码。 尽管在科学出版物中有更多的PU学习方法(我打算在以后的文章中讨论另一种颇受欢迎的方法),但是Elkan和Noto(E&N)的方法非常简单,并且可以在Python中轻松实现。

一点点理论


E&N方法本质上认为,在给定一个具有正样本和未标记样本的数据集的情况下,某个样本为正的概率[P(y = 1 | x)]等于一个样本被标记的概率[P(s = 1 | x)]除以一个正样本被标记的概率[P(s = 1 | y = 1)]。
如果这个说法是正确的(我并不会去证明或反驳它-您可以阅读论文本身的证明并验证代码),那么实现起来似乎相对容易。 之所以这样,是因为尽管我们没有足够的标记数据来训练分类器来告诉我们样本是正还是负,但在PU问题中,我们有足够的标记数据来告诉我们一个正样本是否可能被标记。根据E&N的方法,这足以估算一个样本是否是正样本
更正式地讲,给定一个未标记的数据集,其中只有一组样本被标记为正样本。幸运的是,如果我们可以估计P(s = 1 | x)/ P(s = 1 | y = 1),那么就可以根据以下步骤使用任何基于sklearn的分类器进行估算:
(1)将分类器使用在包含标签和无标签样本的数据集上,同时使用已标记的指示器作为目标y,以这种方式拟合分类器对其进行训练,以预测给定样本x被标记的概率P(s = 1 | x)。
(2)使用分类器来预测数据集中已知正样本被标记的概率,使用预测的结果表示对正样本被标记的概率— P(s = 1 | y = 1 | x)
计算这些预测概率的均值,得到P(s=1|y=1).
在估计了P(s = 1 | y = 1)之后,为了根据E&N方法预测数据点k为正样本的概率,我们要做的就是估计P(s = 1 | k)或K被标记的概率,这正是分类器(1)所做的。
(3)使用我们训练的分类器(1)来估计K被标记的概率或者P(s=1|k)
(4)一旦我们估计了P(s = 1 | k),我们就可以通过将k除以在步骤(2)中估计的P(s = 1 | y = 1)来对k进行分类,然后获得它属于这两个类的实际概率。

现在编写代码并进行测试

上述1-4可按如下方式实施:

# prepare data
x_data = the training set
y_data = target var (1for the positives and not-1for the rest)
# fit the classifier and estimate P(s=1|y=1)
classifier, ps1y1 =
fit_PU_estimator(x_data, y_data, 0.2, Estimator())
# estimate the prob that x_data is labeled P(s=1|X)
predicted_s = classifier.predict_proba(x_data)
# estimate the actual probabilities that X is positive# by calculating P(s=1|X) / P(s=1|y=1)
predicted_y = estimated_s / ps1y1

让我们从这里的主要方法开始:fit_PU_estimator()方法。
fit_PU_estimator()方法完成了2个主要任务:它适合您在正样本和未标记样本的数据集中选择合适的分类器,然后估计正样本被标记的概率。相应地,它返回一个拟合的分类器(已学会估计给定样本被标记的概率)和估计概率P(s = 1 | y = 1)。 之后,我们要做的就是找到P(s = 1 | x)或x被标记的概率。因为分类器被这样训练过,所以我们只需要调用其predict_proba()方法即可。最后,为了对样本x进行实际分类,我们只需要将结果除以已经得到的P(s = 1 | y = 1)。
用代码表示为:

pu_estimator, probs1y1 = fit_PU_estimator(
x_train,
y_train,
0.2,
xgb.XGBClassifier()) predicted_s = pu_estimator.predict_proba(x_train)
predicted_s = predicted_s[:,1]
predicted_y = predicted_s / probs1y1

fit_PU_estimator()方法本身的实现是非常简单的

deffit_PU_estimator(X,y, hold_out_ratio, estimator):# The training set will be divided into a fitting-set that will be used # to fit the estimator in order to estimate P(s=1|X) and a held-out set of positive samples# that will be used to estimate P(s=1|y=1)# --------# find the indices of the positive/labeled elementsassert (type(y) == np.ndarray), "Must pass np.ndarray rather than list as y"
positives = np.where(y == 1.)[0]
# hold_out_size = the *number* of positives/labeled samples # that we will use later to estimate P(s=1|y=1)
hold_out_size = int(np.ceil(len(positives) * hold_out_ratio))
np.random.shuffle(positives)
# hold_out = the *indices* of the positive elements # that we will later use to estimate P(s=1|y=1)
hold_out = positives[:hold_out_size]
# the actual positive *elements* that we will keep aside
X_hold_out = X[hold_out]
# remove the held out elements from X and y
X = np.delete(X, hold_out,0)
y = np.delete(y, hold_out)
# We fit the estimator on the unlabeled samples + (part of the) positive and labeled ones.# In order to estimate P(s=1|X) or what is the probablity that an element is *labeled*
estimator.fit(X, y)
# We then use the estimator for prediction of the positive held-out set # in order to estimate P(s=1|y=1)
hold_out_predictions = estimator.predict_proba(X_hold_out)
#take the probability that it is 1
hold_out_predictions = hold_out_predictions[:,1]
# save the mean probability
c = np.mean(hold_out_predictions)
return estimator, c defpredict_PU_prob(X, estimator, prob_s1y1):
prob_pred = estimator.predict_proba(X)
prob_pred = prob_pred[:,1]
return prob_pred / prob_s1y1

为了对此进行测试,我使用了钞票数据集,该数据集基于从真实和伪造钞票的图像中提取的4个数据点。 我首先在标记的数据集上使用分类器以设置基线,然后删除75%的样本的标签以测试其在P&U数据集上的表现。如输出所示,确实该数据集并不是最难分类的数据集,但是您可以看到,尽管PU分类器仅了解约153个正样本,而其余所有1219均未标记,但与全标签分类器相比,它的表现相当出色 。 但是,它确实损失了大约17%的召回率,因此损失了很多正样本。但是,我相信与其他方案相比,这个结果是令人相当满意的。

===>> load data set <<===data size: (1372, 5)Target variable (fraud or not):
07621610===>> create baseline classification results <<===Classification results:f1: 99.57%
roc: 99.57%
recall: 99.15%
precision: 100.00%===>> classify on all the data set <<===Target variable (labeled or not):
-112191153Classification results:f1: 90.24%
roc: 91.11%
recall: 82.62%

几个要点

首先,这种方法的性能很大程度上取决于数据集的大小。 在此示例中,我使用了大约150个正样本和大约1200个未标记的样本。 这远不是该方法的理想数据集。 例如,如果我们只有100个样本,则分类器的效果会非常差。 其次,如随附的笔记所示,有一些变量需要调整(例如要设置的样本大小,用于分类的概率阈值等),但是最重要的可能是选择的分类器及其参数。 我之所以选择使用XGBoost,是因为它在特征少的小型数据集上的性能相对较好,但是需要注意的是,它并非在每种情况下都表现得很好,并且测试正确的分类器也很重要。

作者:Alon Agmon
Deephub翻译组:gkkkkkk

原文地址:https://imba.deephub.ai/p/8819f7f0709611ea90cd05de3860c663

PU Learning简介:对无标签数据进行半监督分类的更多相关文章

  1. Mahout贝叶斯算法拓展篇3---分类无标签数据

    代码測试环境:Hadoop2.4+Mahout1.0 前面博客:mahout贝叶斯算法开发思路(拓展篇)1和mahout贝叶斯算法开发思路(拓展篇)2 分析了Mahout中贝叶斯算法针对数值型数据的处 ...

  2. Coursera《machine learning》--(14)数据降维

    本笔记为Coursera在线课程<Machine Learning>中的数据降维章节的笔记. 十四.降维 (Dimensionality Reduction) 14.1 动机一:数据压缩 ...

  3. positive-unlabeled (PU) learning

    PULearning的应用场景是,我们可以清晰地确定正样本,但是不能确定负样本,因为它有可能是正样本,只是我们还没有证明. 这时我们可以把这部分不确定的样本称为无标签样本U,加上正样本P来建立模型. ...

  4. LUSE: 无监督数据预训练短文本编码模型

    LUSE: 无监督数据预训练短文本编码模型 1 前言 本博文本应写之前立的Flag:基于加密技术编译一个自己的Python解释器,经过半个多月尝试已经成功,但考虑到安全性问题就不公开了,有兴趣的朋友私 ...

  5. 返回标签数据示例 (PHP)

    标签接口函数 获取标签数据 array uc_tag_get(string tagname [, array nums]) 函数参数 参数 含义 string tagname 标签名称 array n ...

  6. hive表多种存储格式的文件大小差异,无重复数据

    -- 重点,目标表无重复数据 -- dbName.num_result 无重复记录 -- 插入数据 CREATE TABLE dbName.test_textfile( `key` string, ` ...

  7. 代码文件编码unicode 无标签, 导入vs项目编译不过的问题

    很多人经常需要把代码分别在linux.windows上编译.在linux中gcc编译的时候,文件格式为utf-8无bom格式,可是如果将文件拿到windows上,用vs编译的时候,发现各种报错,且都是 ...

  8. 少标签数据学习:宾夕法尼亚大学Learning with Few Labeled Data

    目录 Few-shot image classification Three regimes of image classification Problem formulation A flavor ...

  9. HTML(简介及常用标签)

    一.HTML简介 1.1 html是什么? 超文本标记语言(Hypertext Markup Language,HTML)通过标签语言来标记要显示的网页中的各个部分.一套规则,浏览器认识的规则. 浏览 ...

随机推荐

  1. 剑指CopyOnWriteArrayList

    上期回顾 之前的一篇 剑指ConcurrentHashMap[基于JDK1.8] 给大家详细分析了一波JUC的ConcurrentHashMap,它在线程安全的基础上提供了更好的写并发能力.那么既然有 ...

  2. jQuery2.0.0版本以后不再支持ie8的原因

    在引用jQuery时,引用高版本的Jq会在IE8下报错,在网上查了一下,jq在2.0+的版本就已经放弃对ie8的支持了.之前没有仔细研究过jq版本,借此机会去看了一下jq版本的知识.一.如何查看jq的 ...

  3. 从头认识js-函数表达式

    定义函数的方式有两种: 1.函数声明(特征:函数声明提升,在执行代码之前会先读取函数声明,这就意味着可以把函数声明放在调用它的语句之后) 2.函数表达式(函数表达式与其他表达式一样,使用之前必须先声明 ...

  4. PHP压缩文件夹 php

    $path = PUBLIC_DIR.'/images/'; //待压缩文件夹父目录 $zipPath = PUBLIC_DIR.'/images_zip/'; //压缩文件保存目录 !is_dir( ...

  5. 小白学 Python 数据分析(13):Pandas (十二)数据表拼接

    人生苦短,我用 Python 前文传送门: 小白学 Python 数据分析(1):数据分析基础 小白学 Python 数据分析(2):Pandas (一)概述 小白学 Python 数据分析(3):P ...

  6. css布局中的各种FC(BFC、IFC、GFC、FFC)

    什么是FC?FC(Formatting Context)格式化上下文,其实指的是一个渲染区域,拥有一套渲染规则,它决定了其子元素如何定位,以及与其他元素之间的关系和相互作用. 什么是BFC? BFC( ...

  7. 微信小程序学习简介

    如何向微信小程序导入DEMO源码: 参考方法 参考学习小程序官方文档 小程序官方文档 小程序目录简介 app.json :设置一些工程全局的量.js : 写一些函数逻辑.wxml: 调用.js中写的函 ...

  8. 使用tf serving-gpu时,没有安装NVIDIA时报的错?

    当部署tf serving-gpu时,出现上述的错误,有两种情况: 1.服务器中已经安装NVIDIA驱动了,只是版本比较低了,需要升级一下比较新的nvidia驱动: 2.就是服务器中没有安装NVIDI ...

  9. Data Vault 简介

    Data Vault 简介 Data Vault 2.0 不仅是建模技术,也提供了一整套数据仓库项目的方法论.它能提供一套非常可行的方案来满足数据仓库项目中对于历史轨迹和审核两个方面的需求. 多年来, ...

  10. 日常破解---XCTF_APP1获取flag记录

    日常破解---XCTF_APP1获取flag记录 一.题目来源   来源:XCTF社区安卓题目app1 二.解题记录     1.首先安装到模拟器中运行一下,如下图所示,点击一下按钮,弹出提示年轻人不 ...