PU Learning简介:对无标签数据进行半监督分类

简介: PU Learning简介:对无标签数据进行半监督分类

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

假设您有一个交易业务数据集。有些交易被标记为欺诈,其余交易被标记为真实交易,因此您需要设计一个模型来区分欺诈交易和真实交易。假设您有足够的数据和良好的特征,这似乎是一项简单的分类任务。但是,假设数据集中只有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中轻松实现。

一点点理论

image.png

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进行分类,然后获得它属于这两个类的实际概率。

12.png

现在编写代码并进行测试

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

# prepare data
x_data = the training set
y_data = target var (1 for the positives and not-1 for 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()方法本身的实现是非常简单的

def fit_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 elements
    assert (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
def predict_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):
0    762
1    610===>> 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):
-1    1219
1     153Classification results:f1: 90.24%
roc: 91.11%
recall: 82.62%

几个要点

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

目录
相关文章
|
8天前
|
编解码 并行计算 TensorFlow
垃圾分类模型想上maixpy(3)
1-5 对比Params与模型文件实际体积。 结果:模型实际大小与Params大小是可以对上的,参数应该是以float32存储。我把“字节”与“位”搞混了,应该是一个字节为8位。
46 0
|
8天前
|
vr&ar
垃圾分类模型想上maixpy(2)
1-1 关于模型部署,MaixPy文档的这一部分中可能有些有用的参考:部署模型到 Maix-I(M1) K210 系列开发板 - Sipeed Wiki 。 实际用数字图片进行测试时,手写数字识别的模型无法产生正确的输出。
78 1
|
6月前
lda模型和bert模型的文本主题情感分类实战
lda模型和bert模型的文本主题情感分类实战
121 0
|
9月前
|
数据挖掘
InsTag:大语言模型监督微调数据标签标注工具
魔搭社区发布了一个名为“InsTagger”的工具,用于分析LLM(大语言模型)中符合人类偏好的监督微调(SFT)数据。InsTagger 是基于 InsTag 方法训练的本地指令标签标注器,用于为符合人类偏好的监督微调数据集中的指令标注描述其意图和语义的标签,从而指导指令的分流或监督微调数据集的分析。
|
8天前
|
IDE TensorFlow 开发工具
垃圾分类模型想上maixpy(1)
maixpy笔记 Something 上下拉。应该就是强制高、低电平,可以避免不确定的状态。 模型区没有文件系统,模型之间烧录在指定地址。
51 0
|
机器学习/深度学习 算法 计算机视觉
【多标签文本分类】层次多标签文本分类方法
【多标签文本分类】层次多标签文本分类方法
535 0
【多标签文本分类】层次多标签文本分类方法
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
基于Milvus+ERNIE+SimCSE+In-batch Negatives样本策略的学术文献语义检索系统
基于Milvus+ERNIE+SimCSE+In-batch Negatives样本策略的学术文献语义检索系统
基于Milvus+ERNIE+SimCSE+In-batch Negatives样本策略的学术文献语义检索系统
|
10月前
|
自然语言处理
使用bert+lstm+crf做实体识别经验总结
使用bert+lstm+crf做实体识别经验总结
131 0
|
机器学习/深度学习 自然语言处理
(路透社数据集)新闻分类:多分类问题实战
(路透社数据集)新闻分类:多分类问题实战
|
JSON 自然语言处理 数据挖掘
4.基于Label studio的训练数据标注指南:情感分析任务观点词抽取、属性抽取
4.基于Label studio的训练数据标注指南:情感分析任务观点词抽取、属性抽取

热门文章

最新文章