标签: 半监督学习


作者:炼己者

欢迎大家访问 我的简书 以及 我的博客

本博客所有内容以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,并且是非商业用途,谢谢!

摘要:半监督学习很重要,为什么呢?因为人工标注数据成本太高,现在大家参加比赛的数据都是标注好的了,那么如果老板给你一份没有标注的数据,而且有几百万条,让你做个分类什么的,你怎么办?不可能等标注好数据再去训练模型吧,所以你得会半监督学习算法。

不过我在这里先打击大家一下,用sklearn的包做不了大数据量的半监督学习,我用的数据量大概在15000条以上就要报MemoryError错误了,这个是我最讨厌的错误。暂时我还没有解决的办法,如果同志们是小数据量,那就用这个做着玩玩吧。大家如果有兴趣也可以看一下这篇文章——用半监督算法做文本分类

报MemoryError错误怎么办?sklearn提供这么全的文档当然会有这部分的考虑啦。看这里——sklearn 中的模型对于大数据集的处理。可以用partial_fit增量式计算,可惜只针对部分算法,对于半监督学习没有办法。

好了,该说正题了,最近看了sklearn关于半监督学习的例子,它里面有三个例子,在这里我主要想分享一下第三个例子——用半监督学习算法做数字识别


一. 数据集的解读

首先我们来看一下这份数据集的特点

二. 代码的解读

sklearn官方例子——用半监督学习做数字识别

我们来看一下操作流程

  • 一共330个点,都是已经标注好的了,我们把其中的320个点赋值为-1,这样就可以假装这320个点都是没有标注的了
  • 训练一个只有10个标记点的标签传播模型
  • 然后从所有数据中选择要标记的前五个最不确定的点,把它们(带有正确标签)放到原来的10个点中
  • 接下来可以训练15个标记点(原始10个 + 5个新点)
  • 重复这个过程四次,就可以使用30个标记好的点来训练模型
  • 可以通过改变max_iterations将这个值增加到30以上

以上是sklearn的操作流程,大家可能会有点糊涂

实际任务应该是这样的。假设我们有一份数据集,共330个数字,其中前十个是已知的,已经标注好了,后320个是未知的,需要我们预测出来的。

  • 首先把这330个数据全部都放到半监督学习算法里,训练模型,预测那320个标签
  • 然后用某种方法(看下面代码的操作)得知这320个数据里最不确定的前5个数据,对它进行人工标注,然后把它放到之前的10个数据里,现在就有15个已知数据了
  • 这样循环个几次,已标注的数据就变多了,那么分类器的效果肯定也就变好了

1.导入各种数据包

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
from sklearn import datasets
from sklearn.semi_supervised import label_propagation
from sklearn.metrics import classification_report,confusion_matrix # 再加下面这个,不然会报错
from scipy.sparse.csgraph import *

2.读取数据集

digits = datasets.load_digits()
rng = np.random.RandomState(0)
# indices是随机产生的0-1796个数字,且打乱
indices = np.arange(len(digits.data))
rng.shuffle(indices) # 取前330个数字来玩
X = digits.data[indices[:330]]
y = digits.target[indices[:330]]
images = digits.images[indices[:330]] n_total_samples = len(y) # 330
n_labeled_points = 10 # 标注好的数据共10条
max_iterations = 5 # 迭代5次 unlabeled_indices = np.arange(n_total_samples)[n_labeled_points:] # 未标注的数据320条
f = plt.figure() # 画图用的

3. 训练模型且画图

建议大家把自己不懂的地方打印出来看看是啥意思,比如下面

for i in range(max_iterations):
if len(unlabeled_indices) == 0:
print("no unlabeled items left to label") # 没有未标记的标签了,全部标注好了
break
y_train = np.copy(y)
y_train[unlabeled_indices] = -1 #把未标注的数据全部标记为-1,也就是后320条数据 lp_model = label_propagation.LabelSpreading(gamma=0.25,max_iter=5) # 训练模型
lp_model.fit(X,y_train) predicted_labels = lp_model.transduction_[unlabeled_indices] # 预测的标签
true_labels = y[unlabeled_indices] # 真实的标签 cm = confusion_matrix(true_labels,predicted_labels,
labels = lp_model.classes_) print("预测标签")
print(predicted_labels)
print("真实标签")
print(true_labels)
print('----------------------------------------------')

经对比发现预测的标签只有7个类,而非10个类

  • 原因就是我们一开始训练的那10个数据只有7个类,所以预测其他320条数据的时候只能预测出这7个类
预测标签
[2 8 6 6 6 6 1 9 5 8 8 2 8 7 7 6 7 9 2 9 7 7 6 8 9 1 8 1 9 1 1 6 7 7 9 9 7
6 2 1 9 6 7 9 9 9 9 1 6 9 9 2 8 7 2 9 2 6 9 1 8 9 5 1 2 1 2 2 9 7 2 8 6 9
9 8 7 5 1 2 9 9 8 1 7 7 1 1 6 1 5 9 2 6 8 9 2 1 7 7 9 7 8 9 7 5 8 2 1 9 2
9 8 1 1 7 9 6 1 5 8 9 9 6 9 9 5 7 9 6 2 8 6 9 6 1 5 1 5 9 9 1 8 9 6 1 8 9
1 7 6 7 6 5 6 9 8 8 9 8 6 1 9 7 2 6 8 8 6 7 1 9 6 9 9 8 9 8 9 7 7 9 7 8 9
7 8 9 6 7 5 9 1 7 6 1 9 8 9 9 9 9 2 1 1 2 1 1 1 9 2 1 9 8 7 6 1 8 8 1 6 9
9 6 9 2 2 9 7 6 1 1 9 7 2 7 8 6 6 7 5 2 8 7 2 7 9 5 7 9 9 2 6 5 9 7 1 8 8
9 8 6 7 6 9 2 6 1 8 8 1 6 7 5 2 1 5 8 2 1 6 9 1 5 7 9 1 6 2 9 9 1 2 2 9 9
6 9 7 2 9 7 5 8 6 7 8 2 8 7 9 7 2 6 5 1 5 1 9 8]
真实标签
[2 8 6 6 6 6 1 0 5 8 8 7 8 4 7 5 4 9 2 9 4 7 6 8 9 4 3 1 0 1 8 6 7 7 1 0 7
6 2 1 9 6 7 9 0 0 5 1 6 3 0 2 3 4 1 9 2 6 9 1 8 3 5 1 2 8 2 2 9 7 2 3 6 0
5 3 7 5 1 2 9 9 3 1 7 7 4 8 5 8 5 5 2 5 9 0 7 1 4 7 3 4 8 9 7 9 8 2 6 5 2
5 8 4 8 7 0 6 1 5 9 9 9 5 9 9 5 7 5 6 2 8 6 9 6 1 5 1 5 9 9 1 5 3 6 1 8 9
8 7 6 7 6 5 6 0 8 8 9 8 6 1 0 4 1 6 3 8 6 7 4 5 6 3 0 3 3 3 0 7 7 5 7 8 0
7 8 9 6 4 5 0 1 4 6 4 3 3 0 9 5 9 2 1 4 2 1 6 8 9 2 4 9 3 7 6 2 3 3 1 6 9
3 6 3 2 2 0 7 6 1 1 9 7 2 7 8 5 5 7 5 2 3 7 2 7 5 5 7 0 9 1 6 5 9 7 4 3 8
0 3 6 4 6 3 2 6 8 8 8 4 6 7 5 2 4 5 3 2 4 6 9 4 5 4 3 4 6 2 9 0 1 7 2 0 9
6 0 4 2 0 7 9 8 5 4 8 2 8 4 3 7 2 6 9 1 5 1 0 8]
----------------------------------------------

3.1 完整代码

for i in range(max_iterations):
if len(unlabeled_indices) == 0:
print("no unlabeled items left to label") # 没有未标记的标签了,全部标注好了
break
y_train = np.copy(y)
y_train[unlabeled_indices] = -1 #把未标注的数据全部标记为-1,也就是后320条数据 lp_model = label_propagation.LabelSpreading(gamma=0.25,max_iter=5) # 训练模型
lp_model.fit(X,y_train) predicted_labels = lp_model.transduction_[unlabeled_indices] # 预测的标签
true_labels = y[unlabeled_indices] # 真实的标签 cm = confusion_matrix(true_labels,predicted_labels,
labels = lp_model.classes_) print("iteration %i %s" % (i,70 * "_")) # 打印迭代次数
print("Label Spreading model: %d labeled & %d unlabeled (%d total)"
% (n_labeled_points,n_total_samples-n_labeled_points,n_total_samples)) print(classification_report(true_labels,predicted_labels)) print("Confusion matrix")
print(cm) # 计算转换标签分布的熵
# lp_model.label_distributions_作用是Categorical distribution for each item
pred_entropies = stats.distributions.entropy(
lp_model.label_distributions_.T) # 选择分类器最不确定的前5位数字的索引
# 首先计算出所有的熵,也就是不确定性,然后从320个中选择出前5个熵最大的
# numpy.argsort(A)提取排序后各元素在原来数组中的索引。具体情况可看下面
# np.in1d 用于测试一个数组中的值在另一个数组中的成员资格,返回一个布尔型数组。具体情况可看下面
uncertainty_index = np.argsort(pred_entropies)[::1]
uncertainty_index = uncertainty_index[
np.in1d(uncertainty_index,unlabeled_indices)][:5] # 这边可以确定每次选前几个作为不确定的数,最终都会加回到训练集 # 跟踪我们获得标签的索引
delete_indices = np.array([]) # 可视化前5次的结果
if i < 5:
f.text(.05,(1 - (i + 1) * .183),
'model %d\n\nfit with\n%d labels' %
((i + 1),i*5+10),size=10)
for index,image_index in enumerate(uncertainty_index):
# image_index是前5个不确定标签
# index就是0-4
image = images[image_index] # 可视化前5次的结果
if i < 5:
sub = f.add_subplot(5,5,index + 1 + (5*i))
sub.imshow(image,cmap=plt.cm.gray_r)
sub.set_title("predict:%i\ntrue: %i" % (
lp_model.transduction_[image_index],y[image_index]),size=10)
sub.axis('off') # 从320条里删除要那5个不确定的点
# np.where里面的参数是条件,返回的是满足条件的索引
delete_index, = np.where(unlabeled_indices == image_index)
delete_indices = np.concatenate((delete_indices,delete_index)) unlabeled_indices = np.delete(unlabeled_indices,delete_indices)
# n_labeled_points是前面不确定的点有多少个被标注了
n_labeled_points += len(uncertainty_index) f.suptitle("Active learning with label propagation.\nRows show 5 most"
"uncertain labels to learn with the next model")
plt.subplots_adjust(0.12,0.03,0.9,0.8,0.2,0.45)
plt.show()

3.2 numpy.argsort()函数

  • 提取排序后各元素在原来数组中的索引
import numpy as np
B=np.array([[4,2,3,55],[5,6,37,8],[-7,68,9,0]])
print('B:')
print(B) print('')
print('默认输出')
print(np.argsort(B))#默认的输出每行元素的索引值。这些索引值对应的元素是从小到大排序的。

看打印的结果

B:
[[ 4 2 3 55]
[ 5 6 37 8]
[-7 68 9 0]] 默认输出
[[1 2 0 3]
[0 1 3 2]
[0 3 2 1]]

3.3 np.in1d() 函数

  • 用于测试一个数组中的值在另一个数组中的成员资格,返回一个布尔型数组
values = np.array([6, 0, 0, 3, 2, 5, 6])
np.in1d(values, [2, 3, 6])

看打印的结果

array([ True, False, False,  True,  True, False,  True])

三. 总结

这次主要是想用半监督学习算法做NLP文本分类,看到sklearn库里正好有这个算法包,想拿来试一下,结果跑不了那么大的数据量,算是失败了。但是我觉得还是从中了解了很多,后面会写一篇关于它的博客,里面关于文本的处理让我学到了很多,走了很多的弯路。接下来我还会继续探索怎么用少标注的数据来做文本分类。

sklearn半监督学习的更多相关文章

  1. python大战机器学习——半监督学习

    半监督学习:综合利用有类标的数据和没有类标的数据,来生成合适的分类函数.它是一类可以自动地利用未标记的数据来提升学习性能的算法 1.生成式半监督学习 优点:方法简单,容易实现.通常在有标记数据极少时, ...

  2. 吴裕雄 python 机器学习——半监督学习LabelSpreading模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import metrics from sklearn import d ...

  3. 吴裕雄 python 机器学习——半监督学习标准迭代式标记传播算法LabelPropagation模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import metrics from sklearn import d ...

  4. 基于PU-Learning的恶意URL检测——半监督学习的思路来进行正例和无标记样本学习

    PU learning问题描述 给定一个正例文档集合P和一个无标注文档集U(混合文档集),在无标注文档集中同时含有正例文档和反例文档.通过使用P和U建立一个分类器能够辨别U或测试集中的正例文档 [即想 ...

  5. 虚拟对抗训练(VAT):一种用于监督学习和半监督学习的正则化方法

    正则化 虚拟对抗训练是一种正则化方法,正则化在深度学习中是防止过拟合的一种方法.通常训练样本是有限的,而对于深度学习来说,搭设的深度网络是可以最大限度地拟合训练样本的分布的,从而导致模型与训练样本分布 ...

  6. 【半监督学习】MixMatch、UDA、ReMixMatch、FixMatch

    半监督学习(Semi-Supervised Learning,SSL)的 SOTA 一次次被 Google 刷新,从 MixMatch 开始,到同期的 UDA.ReMixMatch,再到 2020 年 ...

  7. 【论文解读】【半监督学习】【Google教你水论文】A Simple Semi-Supervised Learning Framework for Object Detection

    题记:最近在做LLL(Life Long Learning),接触到了SSL(Semi-Supervised Learning)正好读到了谷歌今年的论文,也是比较有点开创性的,浅显易懂,对比实验丰富, ...

  8. 利用DP-SSL对少量的标记样本进行有效的半监督学习

    作者 | Doreen 01 介绍 深度学习之所以能在图像分类.自然语言处理等方面取得巨大成功的原因在于大量的训练数据得到了高质量的标注. 然而在一些极其复杂的场景(例如:无人驾驶)中会产生海量的数据 ...

  9. AI之强化学习、无监督学习、半监督学习和对抗学习

    1.强化学习 @ 目录 1.强化学习 1.1 强化学习原理 1.2 强化学习与监督学习 2.无监督学习 3.半监督学习 4.对抗学习 强化学习(英语:Reinforcement Learning,简称 ...

随机推荐

  1. C/C++ 格式化读取和读取一行

    文件内容 23 21 4 1 1 0 114 1 1 1 8 112 5 0 0 0 114 1 0 0 0 115 52 4 1 0 1 134 4 0 1 12 131 4 1 1 0 133 5 ...

  2. Mac OS X文件系统的附加属性@如何彻底删除

    有时候在 Mac 系统下读写 NTFS 分区时,会发现一些文件不能打开. 显示错误为: 项目“XXX”已被 OS X 使用,不能打开. 如果再终端 ls -al 命令一下就可以看到: -rwxr-xr ...

  3. 推荐一个WPF仪表盘开源控件

    前段时间,做服务器端监控系统,为了界面好看,采用WPF.硬件相关监控,比如CPU.内存等,想用仪表盘控件.网上找了很多这种控件,基本上都是第三方商业控件(虽然很漂亮,不过得money...).最后在C ...

  4. 实际SQL案例解决方法整理_LEAD函数相关

    表结构及数据如下: 需求: 将记录按照时间顺序排列,每三条记录为一组,若第二条记录与第一条记录相差5分钟,则删除该记录,若第三条与第二条记录相差5分钟,则删除该记录, 第二组同理,遍历全表,按要求删除 ...

  5. Web—10-前端性能优化

    前端性能优化 从用户访问资源到资源完整的展现在用户面前的过程中,通过技术手段和优化策略,缩短每个步骤的处理时间从而提升整个资源的访问和呈现速度.网站的性能直接会影响到用户的数量,所有前端性能优化很重要 ...

  6. Web | JavaScript的引用数据类型强制转换类型

    我在这里主要的想提下的是JavaScript中的引用类型进行强制转换类型.因为对于基本数据类型的变换大多都是雷同的,很容易熟知,但是引用数据类型有一点小插曲. JavaScript的引用类型主要为对象 ...

  7. Java并发编程(六)原子性与易变性

    原子性 原子是最小单元.不可再分的意思.原子性是指某个操作在获取CPU时间时,要么就给它足够时间,让这个操作执行完,要么就不执行这个操作,执行时不能出现上下文切换(把CPU时间从一个线程分配到另一个线 ...

  8. Extjs 中callParent的作用

    callParent 是 Sencha 类系统提供的一个用于调用你父/祖先类中的方法. 这个通常用于当你 继承一个框架类 或者 覆写一个类中提供的方法(比如 onRender) 时. 当你在一个带参数 ...

  9. c# Reverse()的两点用法

    Rervese的基本用途是:反转数组中元素的顺序,常见的两种用法如下: 1.void Array.Reverse(Array array) static void Main(string[] args ...

  10. react 使用antd 按需加载

    使用 react-app-rewired 1. 安装react-app-rewired: 由于新的 react-app-rewired@2.x 版本的关系,你还需要安装 customize-cra. ...