精华内容
下载资源
问答
  • 全球分区 这段代码是我博士研究的一部分。 目的是建立,验证和测试用于多标签分类的全局分区。
  • 深度学习---多标签分类问题

    万次阅读 多人点赞 2018-05-06 11:18:10
    由于本项目既有涉及multi-class(分类),也有涉及multi-label(标记分类)的部分,multi-class分类网上已经很相关的文章了。这里就说一说multi-label的搭建网络的部分。之后如果有时间的时候,再说一说...

    补充:

    (1)、Guide To Multi-Class Multi-Label Classification With Neural Networks In Python

    (2)、多标签分类(multilabel classification )

    1、使用caffe训练一个多标签分类/回归模型

    2、keras解决多标签分类问题

    3、keras: multi-label神经网络

    前沿

    本篇记录一下自己项目中用到的keras相关的部分。由于本项目既有涉及multi-class(多类分类),也有涉及multi-label(多标记分类)的部分,multi-class分类网上已经很多相关的文章了。这里就说一说multi-label的搭建网络的部分。之后如果有时间的时候,再说一说cross validation(交叉验证)和在epoch的callback函数中处理一些多标签度量metric的问题。

    multi-label多标记监督学习

    其实我个人比较喜欢把label翻译为标签。那可能学术上翻译multi-label多翻译为多标记。其实和多标签一个意思。

    multi-class 和 multi-label的区别

    multi-class是相对于binary二分类来说的,意思是需要分类的东西不止有两个类别,可能是3个类别取一个(如iris分类),或者是10个类别取一个(如手写数字识别mnist)。

    而multi-label是更加general的一种情况了,它说为什么一个sample的标签只能有1个呢。为什么一张图片不是猫就是狗呢?难道我不能训练一个人工智能,它能告诉我这张图片既有猫又有狗呢?

    其实关于多标签学习的研究,已经有很多成果了。 
    主要解法是 
    * 不扩展基础分类器的本来算法,只通过转换原始问题来解决多标签问题。如BR, LP等。 
    * 扩展基础分类器的本来算法来适配多标签问题。如ML-kNN, BP-MLL等。 
    这里不展开了。有兴趣的同学可以自己去研究一下。

    keras的multi-label

    废话不多说,直接上代码。这里假设大家是有keras的基础知识的,所以关键代码之外的代码请大家自行脑补。

    def __create_model(self):
        from keras.models import Sequential
        from keras.layers import Dense
        model = Sequential()
        print("create model. feature_dim = %s, label_dim = %s" % (self.feature_dim, self.label_dim))
        model.add(Dense(500, activation='relu', input_dim=self.feature_dim))
        model.add(Dense(100, activation='relu'))
        model.add(Dense(self.label_dim, activation='sigmoid'))
        model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
        return model

    稍微解说一下: 
    * 整个网络是fully connected全连接网络。 
    * 网络结构是输入层=你的特征的维度 
    * 隐藏层是500*100,激励函数都是relu。隐藏层的节点数量和深度请根据自己的数量来自行调整,这里只是举例。 
    * 输出层是你的label的维度。使用sigmoid作为激励,使输出值介于0-1之间。 
    * 训练数据的label请用0和1的向量来表示。0代表这条数据没有这个位的label,1代表这条数据有这个位的label。假设3个label的向量[天空,人,大海]的向量值是[1,1,0]的编码的意思是这张图片有天空,有人,但是没有大海。 
    * 使用binary_crossentropy来进行损失函数的评价,从而在训练过程中不断降低交叉商。实际变相的使1的label的节点的输出值更靠近1,0的label的节点的输出值更靠近0。

    结语

    有了这个结构,就可以run起来一个multi label的神经网络了。这个只是基础中的基础,关于multi-label的度量代码才是我们研究一个机器学习问题的核心。


    4、解决多标签分类问题(包括案例研究)


    一、

    由于某些原因,回归和分类问题总会引起机器学习领域的大部分关注。多标签分类在数据科学中是一个比较令人头疼的问题。在这篇文章中,我将给你一个直观的解释,说明什么是多标签分类,以及如何解决这个问题。

    1.多标签分类是什么?

    让我们来看看下面的图片。

    如果我问你这幅图中有一栋房子,你会怎样回答? 选项为“Yes”或“No”。

    或者这样问,所有的东西(或标签)与这幅图有什么关系?

    在这些类型的问题中,我们有一组目标变量,被称为多标签分类问题。那么,这两种情况有什么不同吗? 很明显,有很大的不同,因为在第二种情况下,任何图像都可能包含不同图像的多个不同的标签。

    但在深入讲解多标签之前,我想解释一下它与多分类问题有何不同,让我们试着去理解这两组问题的不同之处。

    2.多标签vs多分类

    用一个例子来理解这两者之间的区别。

    对于任何一部电影,电影的中央委员会会根据电影的内容颁发证书。例如,如果你看上面的图片,这部电影被评为“UA”(意思是“12岁以下儿童需在父母陪同下观看”)。还有其他类型的证书类,如“A”(仅限于成人)或“U”(不受限制的公开放映),但可以肯定的是,每部电影只能在这三种类型的证书中进行分类。简而言之,有多个类别,但每个实例只分配一个,因此这些问题被称为多类分类问题。

    同时,你回顾一下这张图片,这部电影被归类为喜剧和浪漫类型。但不同的是,这一次,每部电影都有可能被分成一个或多个不同的类别。

    所以每个实例都可以使用多个类别进行分配。因此,这些类型的问题被称为多标签分类问题。

    现在你应该可以区分多标签和多分类问题了。那么,让我们开始处理多标签这种类型的问题。

    3.加载和生成多标签数据集

    Scikit-learn提供了一个独立的库scikit-multilearn,用于多种标签分类。为了更好的理解,让我们开始在一个多标签的数据集上进行练习。scikit-multilearn库地址:http://scikit.ml/api/datasets.html

    你可以从MULAN package提供的存储库中找到实际的数据集。这些数据集以ARFF格式呈现。存储库地址:http://mulan.sourceforge.net/datasets-mlc.html

    因此,为了开始使用这些数据集,请查看下面的Python代码,将其加载到你的计算机上。在这里,我已经从存储库中下载了酵母(yeast)数据集。

    import scipy
    from scipy.io import arff
    data, meta = scipy.io.arff.loadarff('/Users/shubhamjain/Documents/yeast/yeast-train.arff')
    df = pd.DataFrame(data)

    这就是数据集的样子。

    在这里,Att表示属性或独立变量,class表示目标变量。

    出于实践目的,我们有另一个选项来生成一个人工的多标签数据集。

    from sklearn.datasets import make_multilabel_classification
    
    # this will generate a random multi-label dataset
    X, y = make_multilabel_classification(sparse = True, n_labels = 20,
    return_indicator = 'sparse', allow_unlabeled = False)

    让我们了解一下上面所使用的参数。

    sparse(稀疏):如果是True,返回一个稀疏矩阵,稀疏矩阵表示一个有大量零元素的矩阵。

    n_labels:每个实例的标签的平均数量。

    return_indicator:“sparse”在稀疏的二进制指示器格式中返回Y。

    allow_unlabeled:如果是True,有些实例可能不属于任何类。

    你一定会注意到,我们到处都使用了稀疏矩阵,而scikit-multilearn也建议使用稀疏格式的数据,因为在实际数据集中非常罕见。一般来说,分配给每个实例的标签的数量要少得多。

    好了,现在我们已经准备好了数据集,让我们快速学习解决多标签问题的技术。

    4.解决多标签分类问题的技术

    基本上,有三种方法来解决一个多标签分类问题,即:

    1. 问题转换
    2. 改编算法
    3. 集成方法

    4.1问题转换

    在这个方法中,我们将尝试把多标签问题转换为单标签问题。这种方法可以用三种不同的方式进行:

    1. 二元关联(Binary Relevance)
    2. 分类器链(Classifier Chains)
    3. 标签Powerset(Label Powerset)

    4.4.1二元关联(Binary Relevance)

    这是最简单的技术,它基本上把每个标签当作单独的一个类分类问题。例如,让我们考虑如下所示的一个案例。我们有这样的数据集,X是独立的特征,Y是目标变量。

    在二元关联中,这个问题被分解成4个不同的类分类问题,如下图所示。

    我们不需要手动操作,multi-learn库在python中提供了它的实现。那么,让我们看看它在随机生成的数据上的实现。

    # using binary relevance
    from skmultilearn.problem_transform import BinaryRelevance
    from sklearn.naive_bayes import GaussianNB
    
    # initialize binary relevance multi-label classifier
    # with a gaussian naive bayes base classifier
    classifier = BinaryRelevance(GaussianNB())
    
    # train
    classifier.fit(X_train, y_train)
    
    # predict
    predictions = classifier.predict(X_test)

    注意:在这里,我们使用了Naive Bayes的算法,你也可以使用任何其他的分类算法。

    现在,在一个多标签分类问题中,我们不能简单地用我们的标准来计算我们的预测的准确性。所以,我们将使用accuracy score。这个函数计算子集的精度,这意味着预测的标签集应该与真正的标签集完全匹配。

    那么,让我们计算一下预测的准确性。

    from sklearn.metrics import accuracy_score
    accuracy_score(y_test,predictions)
    0.45454545454545453

    我们的准确率达到了45%,还不算太糟。它是最简单和有效的方法,但是这种方法的惟一缺点是它不考虑标签的相关性,因为它单独处理每个目标变量。

    4.1.2分类器链(Classifier Chains)

    在这种情况下,第一个分类器只在输入数据上进行训练,然后每个分类器都在输入空间和链上的所有之前的分类器上进行训练。
    让我们试着通过一个例子来理解这个问题。在下面给出的数据集里,我们将X作为输入空间,而Y作为标签。

    在分类器链中,这个问题将被转换成4个不同的标签问题,就像下面所示。黄色部分是输入空间,白色部分代表目标变量。

    这与二元关联非常相似,唯一的区别在于它是为了保持标签相关性而形成的。那么,让我们尝试使用multi-learn库来实现它。

    # using classifier chains
    from skmultilearn.problem_transform import ClassifierChain
    from sklearn.naive_bayes import GaussianNB
    
    # initialize classifier chains multi-label classifier
    # with a gaussian naive bayes base classifier
    classifier = ClassifierChain(GaussianNB())
    
    # train
    classifier.fit(X_train, y_train)
    
    # predict
    predictions = classifier.predict(X_test)
    
    accuracy_score(y_test,predictions)
    0.21212121212121213

    我们可以看到,使用这个我们得到了21%的准确率,这比二元关联要低得多。可能是因为没有标签相关性,因为我们已经随机生成了数据。

    4.1.3标签Powerset(Label Powerset)

    在这方面,我们将问题转化为一个多类问题,一个多类分类器在训练数据中发现的所有唯一的标签组合上被训练。让我们通过一个例子来理解它。

    在这一点上,我们发现x1和x4有相同的标签。同样的,x3和x6有相同的标签。因此,标签powerset将这个问题转换为一个单一的多类问题,如下所示。

    因此,标签powerset给训练集中的每一个可能的标签组合提供了一个独特的类。让我们看看它在Python中的实现。

    # using Label Powerset
    from skmultilearn.problem_transform import LabelPowerset
    from sklearn.naive_bayes import GaussianNB
    
    # initialize Label Powerset multi-label classifier
    # with a gaussian naive bayes base classifier
    classifier = LabelPowerset(GaussianNB())
    
    # train
    classifier.fit(X_train, y_train)
    
    # predict
    predictions = classifier.predict(X_test)
    
    accuracy_score(y_test,predictions)
    0.5757575757575758

    这使我们在之前讨论过的三个问题中得到了最高的准确性,57%。唯一的缺点是随着训练数据的增加,类的数量也会增加。因此,增加了模型的复杂性,并降低了精确度。

    现在,让我们看一下解决多标签分类问题的第二种方法。

    4.2改编算法

    改编算法来直接执行多标签分类,而不是将问题转化为不同的问题子集。例如,kNN的多标签版本是由MLkNN表示的。那么,让我们快速地在我们的随机生成的数据集上实现这个。

    from skmultilearn.adapt import MLkNN
    
    classifier = MLkNN(k=20)
    
    # train
    classifier.fit(X_train, y_train)
    
    # predict
    predictions = classifier.predict(X_test)
    
    accuracy_score(y_test,predictions)
    0.69

    很好,你的测试数据已经达到了69%的准确率。

    在一些算法中,例如随机森林(Random Forest)和岭回归(Ridge regression),Sci-kit learn提供了多标签分类的内置支持。因此,你可以直接调用它们并预测输出。

    如果你想了解更多关于其他类型的改编算法,你可以查看multi-learn库。地址:http://scikit.ml/api/api/skmultilearn.adapt.html#module-skmultilearn.adapt

    4.3集成方法

    集成总是能产生更好的效果。Scikit-Multilearn库提供不同的组合分类功能,你可以使用它来获得更好的结果。

    对于直接实现,你可以查看:http://scikit.ml/api/classify.html#ensemble-approaches

    5.案例研究

    在现实世界中,多标签分类问题非常普遍。所以,来看看我们能在哪些领域找到它们。

    5.1音频分类

    我们知道歌曲会被分类为不同的流派。他们也被分类为,如“放松的平静”,或“悲伤的孤独”等等情感或情绪的基础。

    来源:http://lpis.csd.auth.gr/publications/tsoumakas-ismir08.pdf

    5.2图像分类

    使用图像的多标签分类也有广泛的应用。图像可以被标记为不同的对象、人或概念。

    5.3生物信息学

    多标签分类在生物信息学领域有很多用途,例如,在酵母数据集中的基因分类。它还被用来使用几个未标记的蛋白质来预测蛋白质的多重功能。

    5.4文本分类

    谷歌新闻所做的是,将每条新闻都标记为一个或多个类别,这样它就会显示在不同的类别之下。
    例如,看看下面的图片。

    图片来源:https://news.google.com/news/headlines/section/topic/TECHNOLOGY.en_in/Technology?ned=in&hl=en-IN

    同样的新闻出现在“Technology”,“Latest” 等类别中,因为它已经被分类为不同的标签。从而使其成为一个多标签分类问题。

     

    二、

    多标记分类和传统的分类问题相比较,主要难点在于以下两个方面

    (1)类标数量不确定,有些样本可能只有一个类标,有些样本的类标可能高达几十甚至上百个。

    (2)类标之间相互依赖,例如包含蓝天类标的样本很大概率上包含白云,如何解决类标之间的依赖性问题也是一大难点。

    对于多标记学习领域的研究,国外起步较早,起源于2000年Schapire R E等人提出的基于boost方法的文本多分类,著名的学者有G Tsoumakas、Eyke Hüllermeier、Jesse Read,Saso Dzeroski等等。在国内,南京大学的周志华和张敏灵和哈工大的叶允明等等学者在这一领域较都有很好研究成果。

    目前有很多关于多标签的学习算法,依据解决问题的角度,这些算法可以分为两大类:一是基于问题转化(Problem Transformation)的方法,二是基于算法适应的方法和算法适应方法(Algorithm Adaptation)。基于问题转化的多标记分类是转化问题数据,使之适用现有算法;基于算法适应的方法是指针对某一特定的算法进行扩展,从而能够直接处理多标记数据,改进算法,适应数据。基于这两种思想,目前已经有多种相对成熟的算法被提出,如下图所示:



    问题转化方法(Problem Transformation):该类方法的基本思想是通过对多标记训练样本进行处理,将多标记学习问题转换为其它已知的学习问题进行求解。代表性学习算法LP[[1]],Binary Relevance[[2]],Calibrated Label Ranking[[3]], Random k-labelsets[[4]]。总体来说,这类方法有考虑类标之间的联系,但是对于类标较多、数据量较大的数据集,这类方法的计算复杂度是一个很明显的缺陷。

    算法适应方法与问题转化方法不同,问题转化方法是将多标记问题转化成一个或者多个单类标问题,算法适应方法是在多标记的基础上研究算法。近年来,用于多标记的算法适应的算法越来越多,代表性学习算法ML-kNN[[5]],Rank-SVM[[6]],LEAD[[7]],CML。

    对于分类策略,基于考察标记之间相关性的不同方式,已有的多标记学习算法的策略思路大致可以分为以下三类[[8]]:

    a) “一阶(first-order)”策略:该类策略通过逐一考察单个标记而忽略标记之间的相关性,如将多标记学习问题分解为个独立的二类分类问题,从而构造多标记学习系统。该类方法效率较高且实现简单,但由于其完全忽略标记之间可能存在的相关性,其系统的泛化性能往往较低。

    b) “二阶(second-order)”策略:该类策略通过考察两两标记之间的相关性,如相关标记与无关标记之间的排序关系,两两标记之间的交互关系等等,从而构造多标记学习系统。该类方法由于在一定程度上考察了标记之间的相关性,因此其系统泛化性能较优。

    c) “高阶(high-order)”策略:该类策略通过考察高阶的标记相关性,如处理任一标记对其它所有标记的影响,处理一组随机标记集合的相关性等等,从而构造多标记学习系统。该类方法虽然可以较好地反映真实世界问题的标记相关性,但其模型复杂度往往过高,难以处理大规模学习问题。

    [[1]] Madjarov G, Kocev D, Gjorgjevikj D, et al. An extensive experimental comparison of methods for multi-label learning[J]. Pattern Recognition, 2012, 45(9): 3084-3104.


    [[2]] Boutell M R, Luo J, Shen X, Brown C M. Learning multi-label scene classification. Pattern Recognition, 2004, 37(9): 1757-1771.


    [[3]] Fürnkranz J, Hüllermeier E, Loza Mencía E, Brinker K. Multilabel classification via calibrated label ranking. Machine Learning, 2008, 73(2): 133-153.


    [[4]] Tsoumakas G, Vlahavas I. Random k-labelsets: An ensemble method for multilabel classification. In: Kok J N, Koronacki J, de Mantaras R L, Matwin S, Mladenič D, Skowron A, eds. Lecture Notes in Artificial Intelligence 4701, Berlin: Springer, 2007, 406-417.


    [[5]] Zhang M-L, Zhou Z-H. ML-kNN: A lazy learning approach to multi-label learning. Pattern Recognition, 2007, 40(7): 2038-2048.


    [[6]] Elisseeff A, Weston J. A kernel method for multi-labelled classification. In: Dietterich T G, Becker S, Ghahramani Z, eds. Advances in Neural Information Processing Systems 14 (NIPS’01), Cambridge, MA: MIT Press, 2002, 681-687.


    [[7]] Zhang M-L, Zhang K. Multi-label learning by exploiting label dependency. In: Pro ceedings of the 16th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining (KDD’10), Washington, D. C., 2010, 999-1007.


    [[8]] Zhang M L, Zhang K. Multi-label learning by exploiting label dependency[C]// ACM SIGKDD International Conference on Knowledge Discovery and Data Mining. ACM, 2010:999-1008.





    展开全文
  • 多分类: 训练集中每个样本只有一个标签,该标签...令为训练样本集,为标签集合,给定一组形式为的训练样本,,,目的是学习求出合适的误差低的函数(中的unique values)。 大多数情况下,多标签的方法会涉及到...

    \Chi多分类:

    训练集中每个样本只有一个标签,该标签来自于一个不重合的标签集合L,|L| > 1。

    当|L|=2 时,这是一个二分类问题。当|L| > 2 时,这是一个多分类问题。

     

    单标签与多标签:

    多标签:

    \chi为训练样本集,y=\{1,\cdots,k\}为标签集合,给定一组形式为<x_i,Y_i>的训练样本,x_i \in \chiY_i \in 2^{|y|},目的是学习求出合适的误差低的函数f(x)2^{|y|}中的unique values)。

    大多数情况下,多标签的方法会涉及到一个给定样本可能有的标签的排序问题,因此这个学习算法可以看成函数f:\chi \times y \rightarrow R。并按照f(x,.)来对标签进行排序。

    rank_f(x,l)f规则下样本x所对应的标签l的排序。其中,rank是一个到\{1,\cdots,k\}上的一对一的映射,且如果f(x,l_1) \leq f(x,l_2),那么rank_f(x,l_1) \leq rank_f(x,l_2)

     

    多标签分类的方法:

    多标签分类的方法可以从 Algorithm Independent 和 Algorithm Dependent 的角度讲,也可以从 Problem Transformation Method 和 Algorithm Adaptation Method 的角度讲。Algorithm Dependent 和 Algorithm Adaptation Method 一样,也有很多方法是 Problem Transformation Method 和 Algorithm Adaptation Method 的结合。

    Problem Transformation Method 问题转化

    将多标签问题转化为单标签问题。改变data来适应算法。

    At training time, with D:

    1 Transform the multi-label training data to single-label data

    2 Learn from the single-label transformed data

    At testing time, for \tilde{x}:

    1 Make single-label predictions

    2 Translate these into multi-label predictions

    e.g.

    Binary Relevance (BR): L binary problems (one vs. all)

    缺点:不能model标签的dependency关系;分类不均衡

    改进:Stacked BR (2BR) [Godbole and Sarawagi, 2004],Chain Classifier (CC) [Cheng et al., 2010, Read et al., 2011]

    2 Label Powerset (LP): one multi-class problem of 2^L class-values 二进制

    缺点:类标签多而复杂;不均衡(每个类别标签对应的实例不多);过拟合(预测新值)

    改进:Ensembles of RAndom k-labEL subsets (RAkEL) [Tsoumakas and Vlahavas, 2007],Ensembles of Pruned Sets (EPS) [Read et al., 2008] 二者都通过投票机制进行预测

    3 Pairwise (PW): \frac{L(L-1)}{2} binary problems (all vs. all)

    Each model is trained based on examples annotated by at least one of the labels, but not both.

    缺点:生成的是PW的Rankings,要得到标签集;找过拟合标签的decision boundary无意义;分类器数量大\frac{L(L-1)}{2}

    改进:Calibrated Label Ranking CLR ([Fürnkranz et al., 2008]),

    4 Copy-Weight (CW): one multi-class problem of L class values

    Make a single multi-class problem with L possible class values.Each example duplicated |Y^{(i)})|times, weighted as\frac{1}{|Y^{(i)}|}.

    缺点:同一实例 / 不同标签的decision boundary;标签基数大导致数据集增长大;没有可以直观地对dependency进行model的方法

     

     Algorithm Independent 独立于算法

    分为基于标签和基于实例的两种转化方式。

     

    Label-based Transformation 基于标签的转化

    Instance-based Transformation 基于实例的转化

    Instance Elimination

    去除多标签实例

    Label Creation

    把多个标签变成一个新的标签

    Conversion

    把多标签的实例变成单标签的实例。简化或分解(加、乘)。

    Label Elimination (Simplification)

    保留一个最可能为true的或者随机选择一个标签。

    Labels Decomposition

    Additive

    如下图,分类器数量1+1=2。

    Multiplicative

    如下图,分类器数量2×1×2×1×1×1=4

     Algorithm Independent Method总结

     

    Algorithm Adaptation / Dependent Method 算法适应

    改变单标签算法生成多标签的输出。

    e.g.,

    k-Nearest Neighbours (KNN)

    MLkNN [Zhang and Zhou, 2007] 

    Decision Trees (DT)

    Multi-label C4.5 [Clare and King, 2001]

    基于AdaBoost [Freund Y. & Schapire, R. E., 1995], ADTBoost [Freund Y. & Mason, L. , 1999]的de Comite, F., Gilleron, R. & and Tommasi, M. (2003) Learning Multi-label Alternating Decision Trees from Texts and Data. 和Adaboost.MH and Adaboost.MR (Schapire & Singer, 2000) 

    Support Vector Machines (SVM)

    RankSVM, a Maximum Margin approach [Elisseeff and Weston, 2002]

    Godbole and Sarawagi (2004) 结合PT4

    Aiolli, F. & Sperduti, A. (2005) Multiclass Classification with Multi-Prototype Support Vector Machines.

    Neural Networks (NN)

    BPMLL [Zhang and Zhou, 2006]

    其他方法可参见 A Tutorial on Multi-Label Classification Techniques 和 Multi-Label Classification: An Overview 等文献。

    具体选哪种方法比较好取决于具体问题是什么,效率和速度:Decision Tree-based;灵活性:problem transformation methods, esp. BR-based;预测能力: ensembles (most modern methods)。

     

    An extensive empirical study by [Madjarov et al., 2012] recommends:
                RT-PCT: Random Forest of Predictive Clustering Trees (Algorithm Adaptation, Decision Tree based)
                HOMER: Hierarchy Of Multilabel ClassifiERs (Problem Transformation, LP-based (original presentation))
                CC: Classifier Chains (Problem Transformation, BR-based)

     

    参考资料:
    https://blog.csdn.net/qq_27009517/article/details/80264919

    Multi-label Classification-Part 01, Jesse Read

    André C. P. L. F. de Carvalho, Freitas A A. A Tutorial on Multi-label Classification Techniques[M]// Foundations of Computational Intelligence Volume 5. Springer Berlin Heidelberg, 2009:177-195.

    Li T, Zhang C, Zhu S. Empirical Studies on Multi-label Classification.[C]// IEEE International Conference on TOOLS with Artificial Intelligence. IEEE Computer Society, 2006:86-92.

    Multi-Label Classification: An Overview

    展开全文
  • 详尽分区 这段代码是我博士研究的一部分。 目的是为多标签分类构建,验证和测试分区。
  • 多标签分类任务

    千次阅读 2019-12-05 17:02:11
    参考链接:https://blog.csdn.net/tMb8Z9Vdm66wH68VX1/article/details/81090757
    展开全文
  • RandomPartitionsVersion2 这段代码是我博士研究的一部分。 目的是建立,验证和测试版本2的随机分区,以进行多标签分类
  • 目的: 训练一个分类器来将物品分到不同的类别中,比如一件衣服:可以安照服饰...首先讨论多标签分类数据集(以及如何快速构建自己的数据集)。 之后简要讨论SmallerVGGNet,我们将实现的Keras神经网络架构,并...

    目的:

          训练一个分类器来将物品分到不同的类别中,比如一件衣服:可以安照服饰类别、颜色、质地打上“衬衫”、“蓝色”、“棉”的标签

    服饰类别:衬衫、裙子、裤子、鞋类等

    颜色:红、蓝、黑等

    质地:棉、羊毛、丝、麻等

    整个工程的步骤如下:

    1. 首先讨论多标签分类数据集(以及如何快速构建自己的数据集)。
    2. 之后简要讨论SmallerVGGNet,我们将实现的Keras神经网络架构,并用于多标签分类。
    3. 然后我们将实施SmallerVGGNet并使用我们的多标签分类数据集对其进行训练。
    4. 最后,我们将通过在示例图像上测试我们的网络,并讨论何时适合多标签分类,包括需要注意的一些注意事项。

    这里给出的是项目的文件结构 

    ├── classify.py
    ├── dataset
    │   ├── black_jeans [344 entries
    │   ├── blue_dress [386 entries]
    │   ├── blue_jeans [356 entries]
    │   ├── blue_shirt [369 entries]
    │   ├── red_dress [380 entries]
    │   └── red_shirt [332 entries]
    ├── examples
    │   ├── example_01.jpg
    │   ├── example_02.jpg
    │   ├── example_03.jpg
    │   ├── example_04.jpg
    │   ├── example_05.jpg
    │   ├── example_06.jpg
    │   └── example_07.jpg
    ├── fashion.model
    ├── mlb.pickle
    ├── plot.png
    ├── pyimagesearch
    │   ├── __init__.py
    │   └── smallervggnet.py
    ├── search_bing_api.py
    └── train.py

    我们将用到的重要文件(基于它们本文出现的大致顺序)包括:

    • search_bing_api.py:此脚本使我们能够快速构建深度学习图像数据集。你不需要运行这段脚本因为图片数据集已经囊括在zip文件中。我附上这段脚本仅为保证(代码的)完整性。
    • train.py:一旦我们拥有了数据,我们将应用train.py训练我们的分类器。
    • fashion.model:我们的train.py脚本将会将我们的Keras模型保存到磁盘中。我们将在之后的classify.py脚本中用到它。
    • mlb.pickle:一个由train.py创建的scikit-learn MultiLabelBinarizer pickle文件——该文件以顺序数据结构存储了各类别名称。
    • plot.png:训练脚本会生成一个名为plot.png的图片文件。如果你在你自己的数据集上训练,你便需要查看这张图片以获得正确率/风险函数损失及过拟合情况。
    • classify.py:为了测试我们的分类器,我写了classify.py。在你将模型部署于其他地方(如一个iphone的深度学习app或是树莓派深度学习项目)之前,你应该始终在本地测试你的分类器。

    本项目中的三个文件夹为:

    • dataset:该文件夹包含了我们的图片数据集。每个类别拥有它自己的子文件夹。我们这样做以保证(1)我们的数据在结构上工整有序(2)在给定图片路径后能更容易地提取类别标签名称。
    • pyimagesearch:这是装有我们的Keras神经网络的模块。由于这是一个模块,它包含了固定格式的__init__.py。另外一个文件smallervggnet.py,它包含组装神经网络本身的代码。
    • examples:该文件夹包含了7个样例图片。我们将基于keras,应用classify.py对每一个样例图片执行多标签分类。

    一、数据集准备

    数据集包含六个类别的2,167个图像,包括:

    黑色牛仔裤(344图像)
    蓝色连衣裙(386图像)
    蓝色牛仔裤(356图像)
    蓝色衬衫(369图像)
    红色连衣裙(380图像)
    红色衬衫(332图像)

    6类图像数据可以通过python爬虫在网站上抓取得到。

                                  

            为了方便起见,可以通过使用Bing图像搜索API(Microsoft’s Bing Image Search API)建立图像数据,具体配置过程见这里(需要在线注册获得api key,使用key进行图像搜索),创建图片搜索文件search_bing_api.py,代码:

    # import the necessary packages
    from requests import exceptions
    import argparse
    import requests
    import cv2
    import os
     
    # construct the argument parser and parse the arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-q", "--query", required=True,
    	help="search query to search Bing Image API for")
    ap.add_argument("-o", "--output", required=True,
    	help="path to output directory of images")
    args = vars(ap.parse_args())
     
    # set your Microsoft Cognitive Services API key along with (1) the
    # maximum number of results for a given search and (2) the group size
    # for results (maximum of 50 per request)
    API_KEY = "YOUR_API_KEY_GOES_HERE"
    MAX_RESULTS = 250
    GROUP_SIZE = 50
     
    # set the endpoint API URL
    URL = "https://api.cognitive.microsoft.com/bing/v7.0/images/search"
     
    # when attempting to download images from the web both the Python
    # programming language and the requests library have a number of
    # exceptions that can be thrown so let's build a list of them now
    # so we can filter on them
    EXCEPTIONS = set([IOError, FileNotFoundError,
    	exceptions.RequestException, exceptions.HTTPError,
    	exceptions.ConnectionError, exceptions.Timeout])
     
    # store the search term in a convenience variable then set the
    # headers and search parameters
    term = args["query"]
    headers = {"Ocp-Apim-Subscription-Key" : API_KEY}
    params = {"q": term, "offset": 0, "count": GROUP_SIZE}
     
    # make the search
    print("[INFO] searching Bing API for '{}'".format(term))
    search = requests.get(URL, headers=headers, params=params)
    search.raise_for_status()
     
    # grab the results from the search, including the total number of
    # estimated results returned by the Bing API
    results = search.json()
    estNumResults = min(results["totalEstimatedMatches"], MAX_RESULTS)
    print("[INFO] {} total results for '{}'".format(estNumResults,
    	term))
     
    # initialize the total number of images downloaded thus far
    total = 0
     
    # loop over the estimated number of results in `GROUP_SIZE` groups
    for offset in range(0, estNumResults, GROUP_SIZE):
    	# update the search parameters using the current offset, then
    	# make the request to fetch the results
    	print("[INFO] making request for group {}-{} of {}...".format(
    		offset, offset + GROUP_SIZE, estNumResults))
    	params["offset"] = offset
    	search = requests.get(URL, headers=headers, params=params)
    	search.raise_for_status()
    	results = search.json()
    	print("[INFO] saving images for group {}-{} of {}...".format(
    		offset, offset + GROUP_SIZE, estNumResults))
     
        # loop over the results
    	for v in results["value"]:
    		# try to download the image
    		try:
    			# make a request to download the image
    			print("[INFO] fetching: {}".format(v["contentUrl"]))
    			r = requests.get(v["contentUrl"], timeout=30)
     
    			# build the path to the output image
    			ext = v["contentUrl"][v["contentUrl"].rfind("."):]
    			p = os.path.sep.join([args["output"], "{}{}".format(
    				str(total).zfill(8), ext)])
     
    			# write the image to disk
    			f = open(p, "wb")
    			f.write(r.content)
    			f.close()
     
    		# catch any errors that would not unable us to download the
    		# image
    		except Exception as e:
    			# check to see if our exception is in our list of
    			# exceptions to check for
    			if type(e) in EXCEPTIONS:
    				print("[INFO] skipping: {}".format(v["contentUrl"]))
    				continue
     
            # try to load the image from disk
    		image = cv2.imread(p)
     
    		# if the image is `None` then we could not properly load the
    		# image from disk (so it should be ignored)
    		if image is None:
    			print("[INFO] deleting: {}".format(p))
    			os.remove(p)
    			continue
     
    		# update the counter
    		total += 1
     
    

    新建一个文件夹dataset:mkdir dataset。然后收集各类图片

    mkdir dataset/charmander #换成待收集的图片名,其它的不变
    python search_bing_api.py --query "charmander" --output dataset/charmander

    [INFO] searching Bing API for 'charmander'
    [INFO] 250 total results for 'charmander'
    [INFO] making request for group 0-50 of 250...
    [INFO] saving images for group 0-50 of 250...
    [INFO] fetching: http://fc06.deviantart.net/fs70/i/2012/355/8/2/0004_c___charmander_by_gaghiel1987-d5oqbts.png
    [INFO] fetching: http://th03.deviantart.net/fs71/PRE/f/2010/067/5/d/Charmander_by_Woodsman819.jpg
    [INFO] fetching: http://fc05.deviantart.net/fs70/f/2011/120/8/6/pokemon___charmander_by_lilnutta10-d2vr4ov.jpg
    ...
    [INFO] making request for group 50-100 of 250...
    [INFO] saving images for group 50-100 of 250...
    ...
    [INFO] fetching: http://38.media.tumblr.com/f0fdd67a86bc3eee31a5fd16a44c07af/tumblr_nbhf2vTtSH1qc9mvbo1_500.gif
    [INFO] deleting: dataset/charmander/00000174.gif
    ...
    

    有几类图片执行几遍上面的操作,然后使用find方法得到下载的图像数据数目

    find . -type d -print0 | while read -d '' -r dir; do
    > files=("$dir"/*)
    > printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
    > done
        2 files in directory .
        5 files in directory ./dataset
      235 files in directory ./dataset/bulbasaur
      245 files in directory ./dataset/charmander
      245 files in directory ./dataset/mewtwo
      238 files in directory ./dataset/pikachu
      230 files in directory ./dataset/squirtle
    

    之后打开下载的数据,进行一些手工剔除不相关的数据。数据制作over。



    二、定义多标签分类网络架构smallervggnet

            多标签分类网络采用smallervggnet,

                                   

             图片2:被我称为“SmallerVGGNet”的类VGGNet神经网络,我们将用它基于Keras训练一个多标签深度学习分类器

          其原理见论文传送门。有关架构/代码的长篇大论转移至我之前的一篇文章《Keras and Convolutional Neural Networks (CNNs)》,如果你有任何关于架构的问题或是想要了解更多细节,请参阅参阅该文章。如果你希望设计你自己的模型,可以看:《Deep Learning for Computer Vision with Python》(ps:SCDN上有该资源)

    在工程目录下创建python文件,命名为smallervggnet.py

    # import the necessary packages
    from keras.models import Sequential
    from keras.layers.normalization import BatchNormalization
    from keras.layers.convolutional import Conv2D
    from keras.layers.convolutional import MaxPooling2D
    from keras.layers.core import Activation
    from keras.layers.core import Flatten
    from keras.layers.core import Dropout
    from keras.layers.core import Dense
    from keras import backend as K
    
    #引入了Keras模块并于此开始建立我们的SmallerVGGNet类 
    class SmallerVGGNet:
    	@staticmethod
    	def build(width, height, depth, classes, finalAct="softmax"): #定义构建函数,用于组装卷积神经网络。
            #width指定一张输入图片的通道(channels)数量,classes是种类(并不是他们所属的标签)数量(整数)。
            #可选参数finalAct(默认值为“softmax”)将会在神经网络底部被应用。将这个值由softmax改为sigmoid将允许我们基于Keras执行多标签分类。
    		# initialize the model along with the input shape to be
    		# "channels last" and the channels dimension itself
    		model = Sequential()
    		inputShape = (height, width, depth)
    		chanDim = -1
     
    		# if we are using "channels first", update the input shape
    		# and channels dimension
    		if K.image_data_format() == "channels_first":
    			inputShape = (depth, height, width)
    			chanDim = 1
     
    		# CONV => RELU => POOL
    		model.add(Conv2D(32, (3, 3), padding="same",
    			input_shape=inputShape))
    		model.add(Activation("relu"))
    		model.add(BatchNormalization(axis=chanDim))
    		model.add(MaxPooling2D(pool_size=(3, 3)))
    		model.add(Dropout(0.25))
     
    		# CONV => RELU => POOL
    		model.add(Conv2D(32, (3, 3), padding="same",
    			input_shape=inputShape))
    		model.add(Activation("relu"))
    		model.add(BatchNormalization(axis=chanDim))
    		model.add(MaxPooling2D(pool_size=(3, 3)))
    		model.add(Dropout(0.25))
     
    	    # (CONV => RELU) * 2 => POOL
    		model.add(Conv2D(64, (3, 3), padding="same"))
    		model.add(Activation("relu"))
    		model.add(BatchNormalization(axis=chanDim))
    		model.add(Conv2D(64, (3, 3), padding="same"))
    		model.add(Activation("relu"))
    		model.add(BatchNormalization(axis=chanDim))
    		model.add(MaxPooling2D(pool_size=(2, 2)))
    		model.add(Dropout(0.25))
     
    		# (CONV => RELU) * 2 => POOL
    		model.add(Conv2D(128, (3, 3), padding="same"))
    		model.add(Activation("relu"))
    		model.add(BatchNormalization(axis=chanDim))
    		model.add(Conv2D(128, (3, 3), padding="same"))
    		model.add(Activation("relu"))
    		model.add(BatchNormalization(axis=chanDim))
    		model.add(MaxPooling2D(pool_size=(2, 2)))
    		model.add(Dropout(0.25))
     
    	    # first (and only) set of FC => RELU layers
    		model.add(Flatten())
    		model.add(Dense(1024))
    		model.add(Activation("relu"))
    		model.add(BatchNormalization())
    		model.add(Dropout(0.5))
     
    		# use a *softmax* activation for single-label classification
    		# and *sigmoid* activation for multi-label classification
    		model.add(Dense(classes))
    		model.add(Activation(finalAct))
     
    		# return the constructed network architecture
    		return model

    代码说明:

    构建第一个CONV ==> RELU ==> POOL模块:

    我们的CONV层拥有32个卷积核大小为3×3的滤波器以及RELU(Rectified Linear Unit)激活函数。我们在这之后使用批标准化,最大池化,以及25%的遗忘率(Dropout)。

                                   

          Dropout是一个随机切断当前神经网络层节点与下一神经网络层节点间链接的过程。这个随机断开的过程自然地帮助神经网络降低了过拟合的可能性,得益于没有任何一个节点会被分配以预测某个特定的类别、对象、边缘或是角落。

    紧接着我们有两组(CONV ==> RELU)*2 ==> POOL模块:

                                    

    请注意本模块中过滤器、卷积核以及池化大小的变化,这些变化将会共同运作从而逐渐减少空间大小但提升深度(depth)。

    这些模块之后是我们唯一的FC ==> RELU层:

                                    
           全连接层被放置在神经网络的最末端(在第57-64行由Dense声明)。

           第65行对于我们的多标签分类非常重要——finalAct指明我们使用的是针对于单标签分类的“softmax”激活函数,还是针对于今天我们提出的多标签分类的sigmoid激活函数。请参考本脚本smallervggnet.py的第14行以及train.py的第95行。

    三、实现多标签分类Keras模型

          既然我们已经实现了SmallerVGGNet,接下来让我们创建train.py,我们用于训练多标签Keras神经网络的脚本。

          我强烈建议你重温一下先前的博文,今天的train.py脚本便是基于该文章。实际上你可能会想要在屏幕上并行查看它们以观测它们之间区别并阅读关于代码的详细解释。今天回顾将简洁明了

    打开train.py并插入下述代码:

                                        

    在第2至第19行,我们导入了该脚本所需要的包和模块。第三行指定了一个matplotlib后端,基于此我们可以在后台保存我们所绘制的图片。

    我将假定你已经安装了Keras,scikit-learn,matplotlib,imutils以及OpenCV。

    如果这是你的深度学习首秀,你有两个选择来确保你拥有正确的库和包:

    • 已配置好的环境(你将在5分钟内准备就绪并执行代码,训练今天的这个神经网络的花费将少于一杯星巴克咖啡的价格)。
    • 建立你自己的环境(需要时间,耐性以及持久性)。

    我更喜欢在云端预先配置好的环境,你能够在云上启动、上传文件、训练+获取数据以及在几分钟之内终止程序。我推荐的两个预先配置好的环境:

    如果你坚持要建立你自己的环境(而且你有时间来调试及问题修复),我建议你遵循下列博文中的一个:

    既然你的环境已经准备就绪,而且你已经导入了相关包,那么让我们解析命令行参数:

                                 

    命令行参数之于脚本犹如参数之于函数——如果你不理解这个类比,你需要参阅命令行参数。

    我们今天将会处理4个命令行参数:

    • --dataset:输入的数据集路径。
    • --model:输出的Keras序列模型路径。
    • --labelbin:输出的多标签二值化对象路径。
    • --plot:输出的训练损失及正确率图像路径。

    如果你需要关于这些参数的结束,请务必参阅之前的博文。

    让我们进一步讨论一些在我们训练过程中起到至关重要的作用的参数:

                                     

    在第35-38行的这些参数定义了:

    • 我们的神经网络将会训练75轮(epoch),通过反向传播不断提升模型表现从而学习数据背后的模式。
    • 我们设置初始学习率为1e-3(Adam优化器的默认值)。
    • Batch size是32。如果你拥有GPU,你应该根据你的GPU能力调整这个值,但我发现设置batch size为32能使这个项目执行的非常好。
    • 如之前所言,我们的图片大小是96×96并包含3个通道。

    之前的博文提供了更多细节。

    紧接着,接下来的两个代码模块用于加载及预处理我们的训练数据:

                                       

    在这里我们获取imagePaths并将它们的顺序随机打乱,随后初始化data和labels数组。

    然后我们将循环遍历imagePaths,预处理图像数据并解析多类标签。

                                     

                                                                             注:该代码的行号出现问题

          首先我们将每张图片加载至内存。其次,我们在第54和第55行代码执行预处理(深度学习流水线中的重要一环)。我们将image添加在data的末尾。

          第60和第61行针对我们的多标签分类问题将图片路径切分为多个标签。在第60的代码执行之后,一个拥有2个元素的数组被创建,随后在第61行中被添加至labels数据中。如下是一个在终端中经过分解的例子,你能从中了解多标签分词的过程:

                                      640?wx_fmt=png

          如你所见,labels数组是一个“包含数组的数组”——labels中的每个元素都是一个包含两个元素的数组。每个数组对应两个标签这种架构是基于输入图片的文件路径构建的。

    继续完成预处理:

                                      640?wx_fmt=png

          我们的data数据由利用Numpy数组存储的图片组成。在每一行代码中,我们将Python数组转换为Numpy数组并将像素值缩放于范围 [0,1] 之中。

    我们也将标签转换为Numpy数组。

    随后,然我们将标签二值化——下述模块对于本周的多类分类概念十分重要:

                                       640?wx_fmt=png

          为了能够针对多类分类将标签二值化,我们需要运用scikit-learn库中的MultiLabelBinarizer类。你不能在多类分类问题上用标准的LabelBinarizer类。

    第72和第73行代码将人可读的标签转换为包含各类对应编码的向量,该向量根据某类是否在图片中出现来决定对应类的具体值。

    这里是一个展现MultiLabelBinarizer如何将(“red”,“dress”)元组转换为一个有6个类别的向量的例子:

                                        

    One-hot编码将分类标签由一个整数转换为一个向量。同样的概念可以应用在第16和第17行代码上,除非这是一个two-hot编码。

          请注意在Python命令行(为了不与train.py中的代码块混淆)中的第17行,有两个分类标签是“hot”(在数组中用一个“1”表示),表明这各个标签的出现。在本例中,“dress”和“red”在数组中是“hot”(第14至第17行)。其他所有标签的值为“0”。

    我们将数据分为训练集和测试集并初始化数据增强器。

                                      

    在机器学习实战中,将数据分为训练和测试集是一种很常见的做法——我把80%的图片分配为训练数据,20%为测试数据。这一过程在第81和82行中由scikit-learn进行处理。

    我们的数据增强器对象在第85至第87中被初始化。当你的没类数据少于1000张图像时,数据增强是一个最好的实践也或许是一个“必须”的实践。

    接下来,让我们建立模型并初始化Adam优化器:

                                     

    在第92至第95行中,我们构建SmallerVGGNet模型,finalAct=”sigmoid”这个参数指明我们将执行多标签分类。

    随后,我们将编译模型并开始训练(取决于你的硬件,这可能会需要一段时间):

                                    640?wx_fmt=png

    在第105行和第106行中,我们编译模型并使用二元交叉熵而不是类别交叉熵。

    对于多标签分类问题,这可能看起来有些违背了直觉;然而,目标是将每个输出标签视作一个独立伯努利分布,而且我们需要独立地惩罚每个输出节点。

    随后我们启动运用了数据增强生成器的训练过程(第110-114行)。

    在完成训练之后我们可以将模型和标签二值化器储存至磁盘:

                                      640?wx_fmt=png

    随后,我们绘制正确率及损失:

                                     640?wx_fmt=png

    训练和验证的准确率+损失在第127-137行代码中绘画。该图片在第138行中被保存为一个图片文件。

    在我看来,训练图像的绘制就跟模型本身一样重要。在我们满意并在博客上与你们分享之前,我通常会执行训练的几个迭代周期并查看图像是否无误。

    在迭代过程中我喜欢讲图片存至硬盘上出于几个原因:

    • 我在一个无界面的后台服务器上运行代码,也并不想依赖于X-forwarding
    • 我不想忘记保存图片(即使我正在使用X-forwarding或是我正使用一个拥有图形化界面的机器)。

    回想我们在上面将脚本的第三行改变了matplotlib的后端,就是为了帮助我们将图片储存至硬盘上。

    train.py

    # set the matplotlib backend so figures can be saved in the background
    import matplotlib
    matplotlib.use("Agg")
     
    # import the necessary packages
    from keras.preprocessing.image import ImageDataGenerator
    from keras.optimizers import Adam
    from keras.preprocessing.image import img_to_array
    from sklearn.preprocessing import MultiLabelBinarizer
    from sklearn.model_selection import train_test_split
    from pyimagesearch.smallervggnet import SmallerVGGNet
    import matplotlib.pyplot as plt
    from imutils import paths
    import numpy as np
    import argparse
    import random
    import pickle
    import cv2
    import os
     
    # construct the argument parse and parse the arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-d", "--dataset", required=True,
    	help="path to input dataset (i.e., directory of images)")
    ap.add_argument("-m", "--model", required=True,
    	help="path to output model")
    ap.add_argument("-l", "--labelbin", required=True,
    	help="path to output label binarizer")
    ap.add_argument("-p", "--plot", type=str, default="plot.png",
    	help="path to output accuracy/loss plot")
    args = vars(ap.parse_args())
     
    # initialize the number of epochs to train for, initial learning rate,
    # batch size, and image dimensions
    EPOCHS = 75
    INIT_LR = 1e-3
    BS = 32
    IMAGE_DIMS = (96, 96, 3)
     
    # grab the image paths and randomly shuffle them
    print("[INFO] loading images...")
    imagePaths = sorted(list(paths.list_images(args["dataset"])))
    random.seed(42)
    random.shuffle(imagePaths)
     
    # initialize the data and labels
    data = []
    labels = []
     
    # loop over the input images
    for imagePath in imagePaths:
    	# load the image, pre-process it, and store it in the data list
    	image = cv2.imread(imagePath)
    	image = cv2.resize(image, (IMAGE_DIMS[1], IMAGE_DIMS[0]))
    	image = img_to_array(image)
    	data.append(image)
     
    	# extract set of class labels from the image path and update the
    	# labels list
    	l = label = imagePath.split(os.path.sep)[-2].split("_")
    	labels.append(l)
    

    四、训练模型

    打开终端。在那里,打开项目路径并执行如下命令:

    python train.py --dataset dataset --model fashion.model --labelbin mlb.pickle

    出现下图

             

    如你所见,我们将模型训练了75个epoch,实现了:

    • 98.57% 训练集上的多标签分类正确率
    • 98.42% 测试集上的多标签分类正确率

    训练图在图3中展示:

                              640?wx_fmt=png

                                                   图3:Keras深度学习多标签分类在训练集和测试集中的正确率/损失。


    五、使用训练完成的模型预测新的图像 

    创建名为classify.py的文件并加入如下代码

    # import the necessary packages
    from keras.preprocessing.image import img_to_array
    from keras.models import load_model
    import numpy as np
    import argparse
    import imutils
    import pickle
    import cv2
    import os
     
    # construct the argument parse and parse the arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-m", "--model", required=True,
    	help="path to trained model model")
    ap.add_argument("-l", "--labelbin", required=True,
    	help="path to label binarizer")
    ap.add_argument("-i", "--image", required=True,
    	help="path to input image")
    args = vars(ap.parse_args())
     
    # 加载图片
    image = cv2.imread(args["image"])
    output = imutils.resize(image, width=400)
     
    # 预处理输入图片(使用与训练数据相同的标准)
    image = cv2.resize(image, (96, 96))
    image = image.astype("float") / 255.0
    image = img_to_array(image)
    image = np.expand_dims(image, axis=0)
     
    # 加载模型+多标签二值化器并将图片分类。从磁盘将模型和多标签二值化器加载至内存中。
    print("[INFO] loading network...")
    model = load_model(args["model"])
    mlb = pickle.loads(open(args["labelbin"], "rb").read())
     
    # 分类(经过预处理的)图片并通过
    #(1)基于相关概率将数组索引按降序排序
    #(2)获取前两个类标签的索引,这便是我们的神经网络所作出的最好的两个预测
    #方式解析出相关性最大的前两个类的标签索引:
    #可以通过修改这段代码以返回更多的类标签。我也建议你对概率设置阈值,并且只返回那些置信程度 > N%的标签。
    print("[INFO] classifying image...")
    proba = model.predict(image)[0]
    idxs = np.argsort(proba)[::-1][:2]
     
    # 对每一个输出图像准备类标签+相关的置信值,该for循环将可能性最大的两个多标签预测及相应的置信值绘制在输出图片上
    for (i, j) in enumerate(idxs):
    	# build the label and draw the label on the image
    	label = "{}: {:.2f}%".format(mlb.classes_[j], proba[j] * 100)
    	cv2.putText(output, label, (10, (i * 30) + 25), 
    		cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
     
    #将所有的预测打印在终端上。这对于调试过程非常有用
    for (label, p) in zip(mlb.classes_, proba):
    	print("{}: {:.2f}%".format(label, p * 100))
     
    # 在屏幕上显示输出图片
    cv2.imshow("Output", output)
    cv2.waitKey(0)
     
    

    用命令行运行测试文件,最终显示出预测的分类结果

    python classify.py --model fashion.model --labelbin mlb.pickle --image examples/example_01.jpg

    结果:

                                                     

                                                                                       

                         图片4:这张红色裙子的照片被我们的Keras多标签分类深度学习脚本由分类器正确分为“红色”和“裙子”。


    总结:

    使用Keras执行多标签分类非常简单,包括两个主要步骤:

    • 1.使用sigmoid激活替换网络末端的softmax激活
    • 2.二值交叉熵作为分类交叉熵损失函数

    shortcomings:

            网络无法预测没有在训练集中出现过的数据样品,如果出现的次数过少,预测的效果也不会很好,解决办法是增大数据集,这样可能非常不容易,还有一种用的已经很多的方法用在大的数据集上训练得到的权重数据对网络做初始化,提高模型的泛化能力。
     


    参考:

    【1】Multi-label classification with Keras(原文)

    【2】手把手教你用Keras进行多标签分类(附代码)(原文翻译)

    【3】基于keras实现多标签分类(multi-label classification)(完整代码)

    展开全文
  • 补充:(1)、Guide To Multi-Class Multi-Label Classification With Neural Networks In Python(2)、多标签分类(multilabel classification )1、使用caffe训练一个多标签分类/回归模型2、keras解决...
  • 解决多标签分类问题(包括案例研究)

    千次阅读 2018-04-19 15:18:14
    多标签分类在数据科学中是一个比较令人头疼的问题。在这篇文章中,我将给你一个直观的解释,说明什么是多标签分类,以及如何解决这个问题。1.多标签分类是什么?让我们来看看下面的图片。如果我问你这幅图中有一栋...
  • 前言 ...不同的是,上篇博客讲的单标签图像分类问题,顾名思义,其输入和输出都是单标签或者可以说是单类别的,而此篇则把重点放在如何处理多标签分类/回归问题的输入和输出上。多标签分类/回归问
  • 关于图片的多标签分类(1)

    千次阅读 2019-04-23 14:33:01
    multi-label分类,常见一张图片中可以存在个目标,如猫,狗,人。这样这张图片就有三个标签; 2)multi-label分类和multi-class 分类? multi-class 分类,就是将多种类别的图片进行类别分类,与multi-la...
  • sklearn 多分类多标签算法

    千次阅读 2018-11-26 10:58:10
    多标签分类格式 One-Vs-The-Rest 类学习 标签学习 One-Vs-One 类学习 错误校正输出代码  类学习 输出回归 输出分类   原文链接 : ...
  • 为了捕获和探索这种重要的依赖关系,我们提出了一种基于图卷积网络(Graph Convolutional Network GCN)的多标签分类模型。该模型在对象标签上构建了一个有向图,其中每个节点(标签)用标签的单词嵌入表示,GCN学习了...
  • 该项目的主要目的是解决基于深度神经网络的多标签文本分类问题。 因此,根据这种问题的特征,数据标签的格式类似于[0、1、0,...,1、1]。 要求 Python 3.6 Tensorflow 1.15.0 Tensorboard 1.15.0 斯克莱恩...
  • 这个例子模拟了多标签文档分类问题。基于以下过程随机生成数据集: pick the number of labels: n ~ Poisson(n_labels) 提取的标签的数量:n~泊松(n_labels) n times, choose a class c: c ~ Multinomial(theta)...
  • keras multi-label classification 多标签分类 问题:一个数据又个标签,一个样本数据个类别中的某几类;比如一个病人的数据有个疾病,一个文本有多种题材,所以标签就是: [1,0,0,0,1,0,1] 这种高维稀疏...
  • 具有区域潜在语义相关性的多标签图像分类   来自2017年的CVPR 摘要   深度卷积神经网络(CNN)在单标签图像分类方面表现出了先进的性能,在多标签图像分类方面也取得了长足的进展。多标签图像分类需要在一个镜头...
  •   虽然深度卷积神经网络(CNNs)在单标签图像分类方面取得了巨大成功,但需要注意的是,现实世界的图像通常包含标签,这些标签可以对应于一幅图像中不同的物体、场景、动作和属性,传统的多标签图像分类方法是对...
  • 目录 MNIST 训练一个二分类器 使用交叉验证测量精度 混淆矩阵 精度和召回率 精度/召回率权衡 ROC曲线 类别分类器 错误分析 多标签分类 输出分类 MNIST MNIST数据集,这是一组由美国高中生和人口调查局员工手写...
  • 分类多分类多标签的基本概念 二分类:表示分类任务中有两个类别,比如我们想识别一幅图片是不是猫。也就是说,训练一个分类器,输入一幅图片,用特征向量x表示,输出是不是猫,用y=0或1表示。二类分类是假设...
  • 分类多分类多标签问题及对应损失函数的选择 之前只是了解了一些图像分类的知识,知道它大概的意思,因为笔者的研究最终也可以叫做分类,所以今天有时间来一起整理下图像分类以及对应的损失函数。开始学习~????...
  • 多标签文本分类多标签文本分类简介三种神经网络结构网络模型文本分类网络模型多标签文本分类网络模型 多标签文本分类简介 NLP(自然语言处理),即让计算机去理解人类的自然语言(文本、语音等),进而完成各种各样...
  • 使用Pytorch和BERT进行多标签文本分类

    千次阅读 2021-04-02 09:23:27
    NLP解决了分类、主题建模、文本生成、问答、推荐等业务问题。虽然TF/IDF矢量化或其他高级词嵌入(如GLOVE和Word2Vec)在此类NLP业务问题上表现出了良好的性能,但这些模型存在局限性就是使用一个向量对词进行编码而不...
  • 互联网分类标签

    千次阅读 2018-08-24 13:21:04
    在使用博客的时候,常常看到分类和标签,容易产生困惑的...在我的博客中,管理方式是“内容——标签——分类”,即先写内容,在提炼标签,然后把标签分类。 读者也可以跟着我的思路进行查阅,一起思考,留下思考分享。
  • 【MachineLearning】多分类多标签算法(Multiclass and multilabel algorithms)的定义与区别 @(Machine Learning) 本文基于Sk-learn的官方文档: ...本文总结下该文档,并给出自己...
  • 二分类、分类与多标签分类问题使用不同的激活函数和损失函数,结论见文末总结(如果你赶时间可以直接看结论,但建议有时间时回过头来看看分析更有助于理解)。 更人工智能基础知识见 望江小车车的博客 二分类、...
  • 2017知乎看山杯总结(多标签文本分类)

    万次阅读 多人点赞 2017-08-31 21:59:53
    基于:python 2.7, TensorFlow 1.2.1任务描述:参赛者需要根据知乎给出的问题及话题标签的绑定关系的训练数据,训练出对未标注数据自动标注的模型。标注数据中包含 300 万个问题,每个问题有 1 个或个标

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 92,559
精华内容 37,023
关键字:

多标签分类的目的