pu-learning 方式实现半监督分类

代码基于 keras 和 sklearn

pu-learning 方式实现半监督分类

概述

使用 1-DNF 加 Logistic Regression 实现 PU-Learning

此实现参考论文 https://pdfs.semanticscholar.org/9181/bd6d6c3332ed5ad8ebd941eb9c9d9f7739fe.pdf

PU-Learning 可以用于解决只含有正标签数据和无标签数据的二分类问题,P 即 positive,U 即 Unlabeled

PU-Learning 分两步

  • 从无标签数据中选出一个可靠的负数据集合 RN (Reliable Negative)

    我这里使用的方法是 1-DNF

  • 使用 P (Positive) 和 RN (Reliable Negative) 训练一个分类器,使用该分类器对 U (Unlabeled) 进行分类,将被判定为负数据的部分 W 合并到 RN 中,循环直至 W 为空集。

    每次循环都会得到一个分类器,通过设定规则选出最终的分类器。

    我这里用的分类器是逻辑回归模型分类器

1-DNF

使用 1-DNF 选出一个可靠的负标签数据集

描述

  • 获取 P, U 中的所有特征 (all features)

  • 对于每个特征,若它在 P 中出现的频率高于在 U 中出现的频率,则将它归入正特征集 PF (Positive Features) 中

  • 对于 U 中的每条数据,若它不包含 PF 中的特征,则将它归入可靠的负数据集 RN (Reliable Negative) 中,否则归入集合 Q 中

训练分类器

训练 Logistic Regression 分类器

描述:

  • P 和 RN 组成训练集 X_train

  • P 给定标签 1,RN 给定标签 0,组成训练集标签 y_train

  • 用 X_train 和 y_train 训练逻辑回归模型 model

model.fit(X_train, y_train)
  • 用 model 对 Q 进行预测(分类)得到结果 result
result = model.predict(Q)
  • 找出 Q 中被判定为负的数据组成集合 W
result = np.where(result<0.5, 0, 1).T[0]
negative_index = np.where(result == 0)
W = Q[negative_index]
  • 将 W 和 RN 合并作为新的 RN,同时将 W 从 Q 中排除
RN = np.concatenate((RN, W))  # RN = RN + W
Q = np.delete(Q, negative_index, axis=0)  # Q = Q - W 
  • 用新的 RN 和 P 组成新的 X_train,对应生成新的 y_train

  • 继续训练模型,扩充 RN,直至 W 为空集,循环结束。其中每次循环都会得到一个分类器

选择一个最终分类器

从每次循环生成的分类器中选出一个最终的分类器

这里有两种方式,一种是直接选用最后一次循环的分类器,另一种是设置规则选出一个最佳分类器。

  • 直接选用最后一次循环得到的分类器:
final_model = models[-1]
  • 利用规则选出一个最佳分类器:

    用最后一次循环得到的分类器 S-last 对 P 进行分类,若分类结果中有超过 8% 条数据被判定为负,则选用第一次循环的分类器 S-1 作为最终分类器,否则继续选用 S-last 作为最终分类器

neg_predict = models[-1].predict(P)
neg_predict = np.where(neg_predict<0.5, 0, 1).T[0]
if list(neg_predict).count(0)/neg_predict.shape[0] > 0.08:
    final_model = models[0]
else:
    final_model = models[-1]

对测试数据集进行分类

得到最终的分类器就可以对测试数据进行分类了,然后得到测试数据的分类结果

result = final_model.predict(X_test)