精华内容
下载资源
问答
  • 多输出分类
    千次阅读
    2020-06-15 20:15:24

    本篇教程基于 PyTorch 1.5版本

    直接上代码!

    import torch
    import torch.nn as nn
    from torch.autograd import Variable
    import torch.distributed as dist
    import torch.utils.data as data_utils
    
    
    class Net(nn.Module):
        def __init__(self, n_input, n_hidden, n_output):
    
            super(Net, self).__init__()
            self.hidden1 = nn.Linear(n_input, n_hidden)
            self.hidden2 = nn.Linear(n_hidden, n_hidden)
    
            self.predict1 = nn.Linear(n_hidden*2, n_output)
            self.predict2 = nn.Linear(n_hidden*2, n_output)
    
        def forward(self, input1, input2): # 多输入!!!
            out01 = self.hidden1(input1)
            out02 = torch.relu(out01)
            out03 = self.hidden2(out02)
            out04 = torch.sigmoid(out03)
    
            out11 = self.hidden1(input2)
            out12 = torch.relu(out11)
            out13 = self.hidden2(out12)
            out14 = torch.sigmoid(out13)
    
            out = torch.cat((out04, out14), dim=1) #
    更多相关内容
  • 选自pyimagesearch,作者:Adrian ...已经推出了两个图像搜索引擎(ID My Pill 和 Chic Engine)的 Adrian Rosebrock 近日发布了一份教程,介绍了使用 Keras 和 TensorFlow 实现「服装种类+颜色」多输出分类的...

    选自pyimagesearch,作者:Adrian Rosebrock,机器之心编译,参与:Panda。

    如何让一个网络同时分类一张图像的两个独立标签?多输出分类可能是你的答案。已经推出了两个图像搜索引擎(ID My Pill 和 Chic Engine)的 Adrian Rosebrock 近日发布了一份教程,介绍了使用 Keras 和 TensorFlow 实现「服装种类+颜色」多输出分类的详细过程。机器之心编译介绍了该教程。

    之前我们介绍了使用 Keras 和深度学习的多标签分类(multi-label classification),参阅 https://goo.gl/e8RXtV。今天我们将讨论一种更为先进的技术——多输出分类(multi-output classification)。

    所以,这两者之间有何不同?你怎样才能跟得上这各项技术?

    尽管这两者有些混淆不清(尤其是当你刚入门深度学习时),但下面的解释能帮你区分它们:

    在多标签分类中,你的网络仅有一组全连接层(即「头」),它们位于网络末端,负责分类。但在多输出分类中,你的网络至少会分支两次(有时候会更多),从而在网络末端创建出多组全连接头——然后你的网络的每个头都会预测一组类别标签,使其有可能学习到不相交的标签组合。

    你甚至可以将多标签分类和多输出分类结合起来,这样每个全连接头都能预测多个输出了!

    如果这开始让你感到头晕了,不要担心——这篇教程将引导你通过 Keras 透彻了解多输出分类。实际做起来会比预想的更轻松。

    话虽如此,这项深度学习技术还是比之前介绍的多标签分类技术更先进。如果你还没有阅读那篇文章,一定要先看看。

    读完那篇文章之后,你应该就已经能使用多个损失函数训练你的网络并从该网络获取多个输出了。接下来我们介绍如何通过 Keras 使用多个输出和多个损失。

     

    我们可以使用 Keras 执行多输出分类,其中多组全连接头使其有可能学习到不相交的标签组合。该动画展示了几个多输出分类的结果。

    在这篇文章中,我们将了解如何通过 Keras 深度学习库使用:

    多个损失函数多个输出

    正如前面提到的,多标签预测和多输出预测之间存在区别。

    使用多标签分类时,我们使用一个全连接头来预测多个类别标签。

    但使用多输出分类时,我们至少有两个全连接头——每个头都负责执行一项特定的分类任务。

    我们甚至可以将多输出分类与多标签分类结合起来——在这种情况下,每个多输出头也会负责计算多个标签!

    你可能已经开始觉得有些难以理解了,所以我们不再继续讨论多输出分类和多标签分类的差异。接下来走进项目里看看吧!我相信本文中所给出的代码能帮你理清这两个概念。

    首先我们将介绍数据集的情况,我们将使用这个数据集来构建我们的多输出 Keras 分类器。

    然后,我们将实现并训练我们的 Keras 架构 FashionNet,其可使用该架构中两个独立的分支来分类服装/时装:

    一个分支用于分类给定输入图像的服装种类(比如衬衫、裙子、牛仔裤、鞋子等);另一个分支负责分类该服装的颜色(黑色、红色、蓝色等)。

    最后,我们将使用训练后的网络来分类示例图像,得到多输出分类结果。

    下面就开始吧!

    多输出深度学习数据集

    图 2:我们的多输出分类数据集是使用这篇文章所讨论的技术创建的:https://goo.gl/3C8xyK。注意我们的数据集中不包含红色/蓝色鞋子或黑色裙子/衬衫,但本文所介绍的 Keras 多输出分类方法依然能正确预测这些组合。

    在本 Keras 多输出分类教程中,我们将使用的数据集基于之前的多标签分类文章的数据集,但也有一个例外——我增加了一个包含 358 张「黑色鞋子」图像的文件夹。

    总体而言,我们的数据集由 2525 张图像构成,分为 7 种「颜色+类别」组合,包括:

    黑色牛仔裤(344 张图像)黑色鞋子(358 张图像)蓝色裙子(386 张图像)蓝色牛仔裤(356 张图像)蓝色衬衫(369 张图像)红色裙子(380 张图像)红色衬衫(332 张图像)

    我使用我之前写的教程《如何(快速)创建一个深度学习图像数据集》中描述的方法创建了该数据集,参阅:https://goo.gl/3C8xyK。

    下载图像和人工移除 7 个组合中的无关图像的整个过程大约耗时 30 分钟。在构建你自己的深度学习图像数据集时,要确保你遵循了上述链接的教程——这能为你开始构建自己的数据集提供很大帮助。

    我们的目标是能够同时预测颜色和服装种类,这和上次一样;但不同之处是我们这一次的网络要能够预测之前未训练过的「服装种类+颜色」组合。

    比如,给定下列「黑色裙子」图像(我们的网络没使用过这样的训练数据):

    图 3:尽管我们的数据集不包含「黑色裙子」图像,但我们仍然可以通过 Keras 和深度学习使用多输出分类来得到正确的分类结果。

    我们的目标是正确预测出该图像的「黑色」+「裙子」。

    我们的 Keras + 深度学习项目结构

    如果你想在你自己的图像上操作这些代码,可以访问原文结尾处的下载板块,下载与本文关联的 .zip 文件。

    然后,unzip 这个文件并按下列方式修改目录(cd)。然后使用 tree 命令,你就可以看到组织好的文件和文件夹。

    上面你可以看到我们的项目结构,但在我们继续之前,首先让我们概览一下其中的内容。

    其中有 3 个值得关注的 Python 文件:

    pyimagesearch/fashionnet.py:我们的多输出分类网络文件包含由三种方法组成的 FashionNet 架构类:build_category_branch、build_color_branch 和 build。我们将在下一节详细介绍这些方法。train.py:这个脚本会训练 FashionNet 模型,并在这一过程中在输出文件夹生成所有文件。classify.py:这个脚本会加载训练后的网络,然后使用多输出分类来分类示例图像。

    我们还有 4 个顶级目录:

    dataset/:我们的时装数据集,这是使用 Bing 图片搜索的 API 收集到的。我们在前一节中介绍了这个数据集。你可以参考前面提到的教程来创建自己的数据集。examples/:我们有一些示例图像,我们将在本文最后一节与我们的 classify.py 脚本一起使用。output/:我们的 train.py 脚本会生成一些输出文件:fashion.model:我们的序列化的 Keras 模型category_lb.pickle:由 scikit-learn 生成的服装类别的序列化 LabelBinarizer 对象。这个文件可被我们的 classify.py 脚本加载(而且标签会被调用)color_lb.pickle:颜色的 LabelBinarizer 对象output_accs.png:准确度的训练图表output_losses.png:损失的训练图表pyimageseach/:这是一个包含 FashionNet 类的 Python 模块

    快速概览我们的多输出 Keras 架构

    要使用 Keras 执行多输出预测,我们要实现一种特殊的网络架构(这是我专为这篇文章创造的),我称之为 FashionNet。

    FashionNet 架构包含两个特殊组件,包括:

    一个网络的早期分支,之后会分成两个「子网络」——一个负责服装种类分类,另一个负责颜色分类。在网络末端的两个(不相交的)全连接头,每一个都负责各自的分类任务。

    在我们开始实现 FashionNet 之前,我们先可视化地看看每个组分,首先是分支:

    图 4:我们的多输出分类网络的顶层是用 Keras 编码的。可以看到,左边是服装种类分支,右边是颜色分支。每个分支都有一个全连接头。

    在这个网络架构图中可以看到,我们的网络接收的输入图像是 96x96x3 大小。

    接下来我们就创建两个分支:

    左边的分支负责分类服装种类。右边的分支负责分类颜色。

    每个分支都执行各自的卷积、激活、批归一化、池化和 dropout 操作组合,直到我们得到最终输出:

    图 5:我们的深度学习 Keras 多输出分类网络有可能学习到不相交的标签组合。

    注意这些全连接(FC)头组合看起来就像是本博客介绍过的其它架构的全连接层——但现在这里有两个全连接头了,其中每一个都负责一个给定的分类任务。

    可以看到,该网络的右边分支比左边分支要浅很多,这是因为预测颜色比预测服装类别容易多了。

    下一节我们将介绍如何实现这样的架构。

    实现我们的 FashionNet 架构

    图 6:Keras 深度学习库拥有执行多输出分类所需的所有功能。

    因为使用多个损失函数训练带有多个输出的网络是一项相当先进的技术,所以我假定你已经知道 CNN 的基础知识,我们将主要关注实现多输出/多损失训练的元素。

    如果你还是深度学习和图像分类领域的新手,你可以考虑看看我的书《Deep Learning for Computer Vision with Python》,这能帮你快速赶上来。

    我相信你已经照前文说的方法下载好了那些文件和数据。现在让我们打开 fashionnet.py 看一看:

    我们先从 Keras 库导入模块并导入 TensorFlow 本身。

    因为我们的网络由两个子网络构成,所以我们将定义两个函数,分别负责构建每个分支。

    第一个分支 build_category_branch 负责分类服装种类,定义如下:

    第 16 和 17 行定义了 build_category_branch,它具有三个值得提及的参数:

    inputs:输入类别分支子网络的输入量numCategories:裙子、鞋子、牛仔裤、衬衫等类别的数量finalAct:最后的激活层的类型,默认是一个 softmax 分类器。如果你要既要执行多输出分类,也要执行多标签分类,你应该将这个激活换成 sigmoid。

    看一下第 20 行,这里我们使用了一个 lambda 层将我们的图像从 RGB 转换成了灰度图像。

    为什么要这样做?

    因为不管是红、蓝、绿还是紫,裙子始终都是裙子。所以我们决定丢弃颜色信息,仅关注图像中的实际结构成分,以确保我们的网络没有在学习中将特定的颜色与服装种类关联起来。

    注:lambda 在 Python 3.5 和 Python 3.6 中的工作方式不一样。我训练这个模型使用的是 Python 3.5,所以如果你想用 Python 3.6 运行这个 classify.py 脚本来进行测试,你可能会遇到麻烦。如果你在 lambda 层遇到了报错,我建议你 (a) 尝试 Python 3.5 或 (b) 在 Python 3.6 上训练然后分类。不需要修改代码。

    第 23-27 行,我们继续构建带有 dropout 的 CONV => RELU => POOL 代码块。

    我们的第一个 CONV 层有 32 个带有 3x3 卷积核和 RELU(修正线性单元)激活的过滤器。我们应用了批归一化、最大池化和 25% 的 dropout。

    dropout 是一种随机断开当前层节点与下一层节点之间的连接的过程。这一随机断开连接过程本质上有助于减少过拟合,因为该层中不会有什么单独的节点负责预测一个特定的类别、物体、边缘或角。

    接下来是两组 (CONV => RELU) * 2 => POOL 代码块:

    在这个代码块中对过滤器、卷积核和池化大小的修改是联合进行的,以在逐步降低空间尺寸的同时增加深度。

    让我们再使用一个 FC => RELU 层将其归总到一处:

    最后一个激活层是全连接的,并且有与我们的 numCategories 同样数量的神经元/输出。

    要注意,我们在第 57 行将我们最后的激活层命名为了 category_output。这很重要,因为我们之后将在 train.py 中通过名字引用这一层。

    让我们定义第二个用于构建我们的多输出分类网络的函数。我们将其命名为 build_color_branch,顾名思义,其负责分类图像中的颜色。

    build_color_branch 的参数与 build_category_branch 的参数基本一样。我们使用 numColors 作为其最后一层激活的数量(不同于 numCategories)。

    这时候我们不再使用 lambda 灰度转换层,因为网络这个部分实际上关心的就是颜色。如果转换成灰度图像,我们就会丢失所有的颜色信息!

    网络的这个分支比分类服装种类的分支浅很多,很多分类颜色的任务要简单很多。这个子网络需要做的只是分类颜色,不需要太深。

    类似于服装种类分支,我们也有一个全连接头。让我们构建 FC =>RELU 代码块来完成:

    为了区分颜色分支的最终激活层,我在第 94 行提供了 name="color_output" 关键词参数。我们将在训练脚本中引用它。

    构建 FashionNet 的最后一步是将我们的两个分支合并到一起,build 最终架构:

    我们的 build 函数是在第 100 行定义的,其有 5 个一看就懂的参数。

    这个 build 函数假设我们正在使用 TensorFlow 和通道最后排序(channels last ordering)。这使得第 105 行中的 inputShape 元组有清晰明确的排序 (height, width, 3),其中 3 是指 RGB 这 3 个通道。

    如果你更愿意使用不同于 TensorFlow 的后端,你需要对代码进行修改:(1)你的后端应该有适当的通道排序,(2)实现一个定制层来处理 RGB 到灰度的转换。

    之后,我们定义该网络的两个分支(第 110-113 行),然后将它们组合到一个 model 中(第 118-121 行)。

    其中的关键思想是我们的分支有一个共有输入,但有两个不同的输出(服装种类和颜色分类结果)。

    实现多输出和多损失训练脚本

    现在我们已经实现了我们的 FashionNet 架构,开始训练它吧!

    准备好了吗?让我们打开 train.py 继续深入:

    我们首先导入该脚本必需的软件包。

    然后我们解析我们的命令行参数:

    我们很快就会看到如何运行训练脚本了。目前,只需要知道 --dataset 是我们的数据集的输入文件路径,--model、--categorybin、--colorbin 是三个输出文件的路径。

    还有个可选操作。你可以使用 --plot 参数指定一个用于生成的准确度/损失图表的基本文件名。我会在脚本中遇到它们时指出这些命令行参数。如果第 21-32 行对你而言有些难以理解,请参阅这篇文章:https://goo.gl/uG5mo9。

    现在,让我们确定 4 个重要的训练变量:

    我们在第 36-39 行设置了以下变量:

    EPOCHS:epoch 数量设置为 50。我通过实验发现 50 epoch 能得到低损失同时又不会过拟合训练集(或者尽我们所能不过拟合)的模型。INIT_LR:我们的初始学习率设置为 0.001。学习率控制着我们沿梯度前进的「步伐」。值越小说明步伐越小,值越大说明步伐越大。我们很快就将看到我们会使用 Adam 优化算法,随时间逐步降低学习率。。BS:我们将以 32 的批大小训练我们的网络。IMAGE_DIMS:所有输入图像的尺寸都会调整为 96x96,外加 3 个通道(RGB)。我们使用这样的维度进行训练,我们的网络架构输入维度也反映了这一点。当我们在之后一节使用示例图像测试我们的网络时,测试图像的维度也必须调整得和训练图像一样。

    接下来是抓取我们的图像路径并随机打乱顺序。我们还将初始化分别用于保存图像本身以及服装种类和颜色的列表。

    接下来,我们将在 imagePaths 上循环,预处理图像并填充 data、categoryLabels 和 colorLabels 列表。

    这个在 imagePaths 上的循环是从第 54 行开始的。

    在该循环内部,我们加载图像并将其尺寸调整为 IMAGE_DIMS。我们也将图像颜色通道的顺序从 BGR 转换成 RGB。为什么要做这样的转换?回想一下 build_category_branch 函数中的 FashionNet 类,其中我们在 lambda 函数/层中使用了 TensorFlow 的 rgb_to_grayscale 转换。因此,我们首先在第 58 行将图像转换成 RGB,最后将预处理后的图像加到 data 列表里。

    接下来,依然在循环内,我们从当前图像所在的目录名称中提取颜色和类别标签(第 64 行)。

    如果你想实际看看操作情况,只需要在你的终端启动 Python,然后按如下方式提供了一个样本 imagePath 来实验即可:

    当然,你可以按照你想要的任何方式组织你的目录结构(但你必须相应地修改代码)。我最喜欢的两种方法包括:(1)为每个标签使用子目录,(2)将所有图像存储在同一个目录中,然后创建一个 CSV 或 JSON 文件将图像文件名映射到它们的标签。

    然后将这三个列表转换成 NumPy 数组,将标签二值化,并将数据分成训练部分和测试部分。

    我们的最后一个预处理步骤(转换成一个 NumPy 数组并将原始像素强度调整到 [0, 1] 区间)可以一步完成,见第 70 行。

    我们也将 categoryLabels 和 colorLabels 转换成 NumPy 数组(第 75-76 行)。这很有必要,因为接下来我们将使用 scikit-learn 的 LabelBinarizer 来将这些标签二值化(第 80-83 行),这是我们之前导入的工具。因为我们的网络有两个独立的分支,所以我们可以使用两个独立的标签 LabelBinarizer——这不同于多标签分类的情况,其中我们使用了 MultiLabelBinarizer(这同样来自于 scikit-learn)。

    接下来,我们对我们的数据集执行一次典型的分割:80% 训练数据和 20% 的测试数据(第 87-96 行)。

    接下来构建网络,定义独立的损失,并编译我们的模型:

    在第 93-96 行,我们实例化了我们的多输出 FashionNet 模型。我们在创建 FashionNet 类和其中的 build 函数时解释过这些参数,但你还是要看看这里我们实际提供的值。

    接下来,我们需要为每个全连接头定义两个 losses(第 101-104 行)。

    定义多个损失是使用一个词典完成的,其使用了每个分支激活层的名称——这就是我们在 FashionNet 实现中给我们的输出层命名的原因!每个损失都使用类别交叉熵,这是分类类别大于 2 时训练网络使用的标准损失方法。

    在第 105 行,我们还在另一个词典中定义了一个等值的 lossWeights(同样的名称键值具有相同的值)。在你的特定应用中,你可能希望某些损失的权重大于其它损失。

    现在我们已经实例化了我们的模型并创建了我们的 losses + lossWeights 词典,接下来我们用学习率延迟实例化 Adam 优化器并 compile 我们的 model(第 110-111 行)。

    接下来的代码就是启动训练过程:

    回想一下第 87-90 行,我们将我们的数据分成了训练部分(trainX)和测试部分(testX)。在第 114-119 行,我们在提供数据的同时启动了训练过程。注意第 115 行我们以词典的形式传递标签。第 116 行和 117 行也是一样,我们为验证数据传递了一个二元组。以这种方式传递训练和验证标签是使用 Keras 执行多输出分类的要求。我们需要指示 Keras 明白哪些目标标签集合对应于网络的哪些输出分支。

    使用我们的命名行参数(args["model"]),我们可以将序列化的模型保存到磁盘以备之后调用。

    我们也能通过同样的操作将我们的标签二值化器保存为序列化的 pickle 文件:

    使用命令行参数路径(args["categorybin"] 和 args["colorbin"]),我们将两个标签二值化器(categoryLB 和 colorLB)都以序列化 pickle 文件形式保存到了磁盘。

    然后就是使用这个脚本绘制结果图表:

    上面的代码块负责绘制每个损失函数的损失历史图表,它们是分别绘制的,但叠放在一起,包括:

    总体损失类别输出的损失颜色输出的损失

    类似地,我们将准确度绘制成另一个图像文件:

    我们的类别准确度和颜色准确度图最好分开看,所以它们是分开的,但放在同一个图片中。

    训练多输出/多损失 Keras 模型

    请确保你下载了本文附带的代码和数据集。

    不要忘了:在本教程给出的下载内容中,我使用的是 Python 3.5 训练该网络。只要你保持一致(一直都用 Python 3.5 或 Python 3.6),你应该不会遇到 lambda 实现不一致的问题。你甚至可以运行 Python 2.7(尚未测试)。

    打开终端。然后将下列命令粘贴进去,开始训练过程(如果你没有 GPU,你可能就得等一段时间,也许抽空喝杯啤酒?):

    对于我们的类别输出,我们得到:

    在训练集上准确度为 99.31%在测试集上准确度为 93.47%

    对于颜色输出,结果为:

    在训练集上准确度为 99.31%在测试集上准确度为 97.82%

    下面是每个损失的图表:

    图 7:使用 matplotlib 绘制的我们的 Keras 深度学习多输出分类训练损失图。为了便于分析,我们的总损失(上图)、服装类别损失(中图)和颜色损失(下图)是分开绘制的。

    还有我们的准确度图表:

    图 8:FashionNet 是一个用 Keras 训练的多输出分类网络。为了分析训练情况,最好是分开呈现准确度图表。上图为服装种类训练准确度图,下图为颜色训练准确度图。

    应用数据增强可以实现更高的准确度。

    实现多输出分类脚本

    现在我们已经训练好了我们的网络,接下来看一下如何将其应用于不属于我们的训练集的输入图像。

    打开 classify.py,插入以下代码:

    首先,我们导入所需的软件包,然后解析命令行参数:

    我们有 4 个命令行参数,你需要这些参数来在你的终端上运行这个脚本:

    --model:我们刚刚训练好的序列化模型文件的路径(我们之前脚本的一个输出)--categorybin:种类标签二值化器的路径(之前脚本的一个输出)--colorbin:颜色标签二值化器的路径(之前脚本的一个输出)--image:测试图像文件的路径——这个图像来自我们的 examples/ 目录

    然后我们载入图像并对其进行预处理:

    在运行推理前,我们需要预处理图像。在上面的代码块中,我们加载了图像,为输出调整了图像大小,然后转换了颜色通道(第 24-26 行),这样我们就可以在 FashionNet 的 lambda 层中使用 TensorFlow 的 RGB 转灰度函数了。然后我们重新调整 RGB 图像的大小(再次调用我们训练脚本中的 IMAGE_DIMS),将其范围调整到 [0,1],将其转换成一个 NumPy 数组,并为该批增加一个维度(第 29-32 行)。

    这里的预处理步骤应该遵照训练脚本的预处理步骤,这是很重要的。

    接下来,加载我们的序列化模型和两个标签二值化器:

    在第 37-39 行,我们使用了 4 个命令行参数中的 3 个,加载了 model、categoryLB 和 colorLB。

    现在(1)多输出 Keras 模型和(2)标签二值化器都已经放入了内存,我们可以分类图像了:

    我们在第 43 行执行多输出分类,得到服装种类和颜色的概率(分别为 categoryProba 和 colorProba)。

    注意:我没有把 include 代码包含进来,因为这样会显得很冗长,但你可以通过检查输出张量的名称来确定你的 TensorFlow + Keras 模型返回多个输出的顺序。参阅 StackOverflow 上的这个讨论了解更多详情:https://goo.gl/F2KChX。

    然后,我们会为类别和颜色提取最高概率的索引(第 48-49 行)。

    使用这些高概率索引,我们可以提取出类别名称(第 50-51 行)。

    看起来有点太简单了,对不对?但应用使用 Keras 的多输出分类到新图像上就这么简单!

    让我们给出结果来证明这一点:

    我们在输出图像上显示结果(第 54-61 行)。结果在图像左上角以绿色文本显示。如果我们遇到了「红色裙子」,结果可能是:

    category: dress (89.04%)color: red (95.07%)

    第 64-65 行也会将结果信息显示在终端上,之后输出图像显示在屏幕上(第 68 行)。

    执行使用 Keras 的多输出分类

    有趣的部分来了!

    在这一节,我们将为我们的网络提供 5 张不属于训练集样本目录的图像。

    按道理,我们的网络应该只能识别其中 2 张(黑色牛仔裤和红色衬衫)。我们的网络应该能轻松处理这样的种类和颜色搭配。

    其余三张图像则是我们的模型从未见过的搭配——我们没使用红色鞋子、蓝色鞋子或黑色裙子训练过;但我们将试试多输出分类的效果。

    首先从「黑色牛仔裤」开始——这个应该很简单,因为训练数据集中有很多类似图像。请确保以这样的方式使用 4 个命令行参数:

    图 9:深度学习多输出分类可以识别不相交标签的组合,比如服装种类和服装颜色。我们的网络正确分类了这张图像:牛仔裤+黑色。

    和预计一样,我们的网络正确分类了这张图像:牛仔裤+黑色。

    再来试试「红色衬衫」:

    图 10:这张「红色衬衫」图像是一张不在我们的深度学习图像数据集中的测试图像。但我们的 Keras 多输出网络见过其它红色衬衫。它能轻松以 100% 的置信度分类这两个标签。

    结果在这两个类别标签上都达到了 100% 的置信度,我们的图像确实包含一件「红色衬衫」。请记住,我们的网络在训练过程中见过其它「红色衬衫」。

    现在让我们回头想想。我们的数据集中原来没有「红色鞋子」,但却有「红色」的「裙子」和「衬衫」,还有「黑色」的「鞋子」。

    那么我们的模型能不能看懂之前从未见过的同时包含「鞋子」和「红色」的图像呢?

    来看结果:

    图 11:我们的深度学习多输出分类网络之前从未见过「红色」与「鞋子」的组合。在训练过程中,模型确实看到过鞋子(但是黑色的);也看到过红色(但是衬衫和裙子)。让人惊喜的是,我们的网络能得到正确的多输出标签,将这张图像分类为「红色鞋子」。成功!

    正确!

    看看图像中的结果,我们成功了。

    我们已经有一个好开始了,虽然这个多输出组合是之前从未出现过的。我们的网络设计+训练是有效的,我们可以以很高的准确度识别「红色鞋子」。

    接下来看看我们的网络能正确分类「黑色裙子」吗?记得吗,在之前的多标签分类教程中,当时的网络并没有得到正确的结果。

    我认为这一次我们很可能成功,将以下代码输入终端:

    图 12:尽管「黑色裙子」图像并不包含在今天的数据集中,但我们仍然可以通过 Keras 和深度学习使用多输出分类来正确分类它们。

    看看这张图左上角的标签类别!

    我们在种类和颜色上都得到了超过 98% 准确度的正确分类。我们已经实现了目标!

    不要激动,让我们再试试另一个未见过的组合:「蓝色鞋子」。在终端输入同样的命令,只是将 --image 参数改为 examples/blue_shoes.jpg:

    图 13:尽管多标签分类可能无法分类不熟悉的标签组合,但多输出分类能很好地应对这样的任务。

    结果同样很好——我们的网络没在「蓝色鞋子」图像上训练过,但还是能使用多输出和多损失分类的两个子网络正确分类它们。

    总结

    在这篇文章中,我们学习了如何使用 Keras 深度学习库中的多输出和多损失函数。

    为了完成我们的任务,我们定义了一个用于时装/服装分类的 Keras 架构 FashionNet。

    FashionNet 架构包含两个分支:

    一个分支负责分类给定输入图像的服装种类(比如衬衫、裙子、牛仔裤、鞋子等)另一个分支负责分类该服装的颜色(黑色、红色、蓝色等)

    分支在网络早期产生,实际上在同一个网络中创造了两个「子网络」,它们分别负责各自的分类任务。

    最值得一提的是,多输出分类让我们可以解决之前的多标签分类的遗留问题,即:我们在 6 种类别(黑色牛仔裤、蓝色裙子、蓝色牛仔裤、蓝色衬衫、红色裙子、红色衬衫)上训练了我们的网络,但得到的网络却无法分类「黑色裙子」,因为该网络之前从未见过这样的数据组合!

    通过创建两个全连接头和相关的子网络(如有必要),我们可以训练一个头分类服装种类,另一个头负责识别颜色——最终得到的网络可以分类「黑色裙子」,即使它之前从未在这样的数据上训练过!

    但还是要记住,你应该尽力提供你想要识别的每个类别的样本训练数据——深度神经网络虽然很强大,但可不是「魔法」!

    你应该尽力保证适当的训练方式,其中首先应该收集合适的训练数据。

    这就是我们的多输出分类文章,希望你喜欢!

    代码下载链接:https://www.getdrip.com/forms/749437062/submissions

    展开全文
  • Multiclass classification 分类: 意味着一个分类任务需要对多于两个类的数据进行分类。比如,对一系列的橘子,苹果或者梨的图片进行分类分类假设每一个样本有且仅有一个标签:一个水果可以被归类为苹果...

    分享一个朋友的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!大家可以看看是否对自己有帮助:点击打开


    全栈工程师开发手册 (作者:栾鹏)
    python数据挖掘系列教程

    Multiclass classification 多类分类: 意味着一个分类任务需要对多于两个类的数据进行分类。比如,对一系列的橘子,苹果或者梨的图片进行分类。多类分类假设每一个样本有且仅有一个标签:一个水果可以被归类为苹果,也可以 是梨,但不能同时被归类为两类。

    Multilabel classification 多标签分类: 给每一个样本分配一系列标签。这可以被认为是预测不相互排斥的数据点的属性,例如与文档类型相关的主题。一个文本可以归类为任意类别,例如可以同时为政治、金融、 教育相关或者不属于以上任何类别。

    Multioutput regression 多输出分类: 为每个样本分配一组目标值。这可以认为是预测每一个样本的多个属性,比如说一个具体地点的风的方向和大小。

    固有的多类分类器:

    • sklearn.naive_bayes.BernoulliNB
    • sklearn.tree.DecisionTreeClassifier
    • sklearn.tree.ExtraTreeClassifier
    • sklearn.ensemble.ExtraTreesClassifier
    • sklearn.naive_bayes.GaussianNB
    • sklearn.neighbors.KNeighborsClassifier
    • sklearn.semi_supervised.LabelPropagation
    • sklearn.semi_supervised.LabelSpreading
    • sklearn.discriminant_analysis.LinearDiscriminantAnalysis
    • sklearn.svm.LinearSVC (setting multi_class=”crammer_singer”)
    • sklearn.linear_model.LogisticRegression (setting multi_class=”multinomial”)
    • sklearn.linear_model.LogisticRegressionCV (setting multi_class=”multinomial”)
    • sklearn.neural_network.MLPClassifier
    • sklearn.neighbors.NearestCentroid
    • sklearn.discriminant_analysis.QuadraticDiscriminantAnalysis
    • sklearn.neighbors.RadiusNeighborsClassifier
    • sklearn.ensemble.RandomForestClassifier
    • sklearn.linear_model.RidgeClassifier
    • sklearn.linear_model.RidgeClassifierCV

    1对1的多类分类器:

    • sklearn.svm.NuSVC
    • sklearn.svm.SVC.
    • sklearn.gaussian_process.GaussianProcessClassifier (setting multi_class = “one_vs_one”)

    1对多的多类分类器:

    • sklearn.ensemble.GradientBoostingClassifier
    • sklearn.gaussian_process.GaussianProcessClassifier (setting multi_class = “one_vs_rest”)
    • sklearn.svm.LinearSVC (setting multi_class=”ovr”)
    • sklearn.linear_model.LogisticRegression (setting multi_class=”ovr”)
    • sklearn.linear_model.LogisticRegressionCV (setting multi_class=”ovr”)
    • sklearn.linear_model.SGDClassifier
    • sklearn.linear_model.Perceptron
    • sklearn.linear_model.PassiveAggressiveClassifier

    支持多标签分类的分类器:

    • sklearn.tree.DecisionTreeClassifier
    • sklearn.tree.ExtraTreeClassifier
    • sklearn.ensemble.ExtraTreesClassifier
    • sklearn.neighbors.KNeighborsClassifier
    • sklearn.neural_network.MLPClassifier
    • sklearn.neighbors.RadiusNeighborsClassifier
    • sklearn.ensemble.RandomForestClassifier
    • sklearn.linear_model.RidgeClassifierCV

    支持多类-多输出分类的分类器:

    • sklearn.tree.DecisionTreeClassifier
    • sklearn.tree.ExtraTreeClassifier
    • sklearn.ensemble.ExtraTreesClassifier
    • sklearn.neighbors.KNeighborsClassifier
    • sklearn.neighbors.RadiusNeighborsClassifier
    • sklearn.ensemble.RandomForestClassifier

    格式转换

    在 multilabel learning 中,二元分类任务的合集表示为二进制数组:每一个样本是大小为 (n_samples, n_classes) 的二维数组中的一行二进制值,比如非0元素,表示为对应标签的 子集。 一个数组 np.array([[1, 0, 0], [0, 1, 1], [0, 0, 0]]) 表示第一个样本属于第 0 个标签,第二个样本属于第一个和第二个标签,第三个样本不属于任何标签。

    # 多标签分类格式。将多分类转换为二分类的格式,类似于one-hot编码
    from sklearn.preprocessing import MultiLabelBinarizer
    y = [[2, 3, 4], [2], [0, 1, 3], [0, 1, 2, 3, 4], [0, 1, 2]]
    y_new = MultiLabelBinarizer().fit_transform(y)
    print('新的输出格式:\n',y_new)
    
    

    1对其余

    这个方法也被称为 1对多, 在 OneVsRestClassifier 模块中执行。

    # =========1对其余的多分类构造方式================
    from sklearn import datasets
    from sklearn.multiclass import OneVsRestClassifier
    from sklearn.svm import LinearSVC
    
    iris = datasets.load_iris()
    X, y = iris.data, iris.target
    clf = LinearSVC(random_state=0)  # 构建二分类器
    clf = OneVsRestClassifier(clf)  # 根据二分类器构建多分类器
    clf.fit(X, y)  # 训练模型
    y_pred = clf.predict(X) # 预测样本
    print('预测正确的个数:%d,预测错误的个数:%d' %((y==y_pred).sum(),(y!=y_pred).sum()))
    

    1对1

    OneVsOneClassifier 1对1分类器 将会为每一对类别构造出一个分类器,在预测阶段,收到最多投票的类别将会被挑选出来。 当存在结时(两个类具有同样的票数的时候), 1对1分类器会选择总分类置信度最高的类,其中总分类置信度是由下层的二元分类器 计算出的成对置信等级累加而成。

    因为这需要训练出 n_classes * (n_classes - 1) / 2 个分类器, 由于复杂度为 O(n_classes^2),这个方法通常比 one-vs-the-rest 慢。然而,这个方法也有优点,比如说是在没有很好的缩放 n_samples 数据的核方法中。 这是由于每个单独的学习问题只涉及一小部分数据,而 one-vs-the-rest 将会使用 n_classes 次完整的数据。

    # =========1对1的多分类构造方式================
    from sklearn import datasets
    from sklearn.multiclass import OneVsOneClassifier
    from sklearn.svm import LinearSVC
    
    iris = datasets.load_iris()
    X, y = iris.data, iris.target
    clf = LinearSVC(random_state=0)  # 构建二分类器
    clf = OneVsOneClassifier(clf)  # 根据二分类器构建多分类器
    clf.fit(X, y)  # 训练模型
    y_pred = clf.predict(X) # 预测样本
    print('预测正确的个数:%d,预测错误的个数:%d' %((y==y_pred).sum(),(y!=y_pred).sum()))
    

    误差校正输出代码

    基于Output-code的方法不同于 one-vs-the-rest 和 one-vs-one。使用这些方法,每一个类将会被映射到欧几里得空间,每一个维度上的值只能为0或者1。另一种解释它的方法是,每一个类被表示为二进制 码(一个 由0 和 1 组成的数组)。保存 location (位置)/ 每一个类的编码的矩阵被称为 code book。编码的大小是前面提到的欧几里得空间的纬度。直观上来说,每一个类应该使用一个唯一的编码,同时,好的 code book 应该能够优化分类的精度。 在实现上,我们使用随机产生的 code book

    # =========误差校正输出代码================
    from sklearn import datasets
    from sklearn.multiclass import OutputCodeClassifier
    from sklearn.svm import LinearSVC
    
    iris = datasets.load_iris()
    X, y = iris.data, iris.target
    clf = LinearSVC(random_state=0)  # 构建二分类器
    clf = OutputCodeClassifier(clf,code_size=2, random_state=0)  # 根据二分类器构建多分类器
    clf.fit(X, y)  # 训练模型
    y_pred = clf.predict(X) # 预测样本
    print('预测正确的个数:%d,预测错误的个数:%d' %((y==y_pred).sum(),(y!=y_pred).sum()))
    

    多输出回归

    多输出回归支持 MultiOutputRegressor 可以被添加到任何回归器中。这个策略包括对每个目标拟合一个回归器。因为每一个目标可以被一个回归器精确地表示,通过检查对应的回归器,可以获取关于目标的信息。 因为 MultiOutputRegressor 对于每一个目标可以训练出一个回归器,所以它无法利用目标之间的相关度信息。

    # =========多输出回归================
    from sklearn.datasets import make_regression
    from sklearn.multioutput import MultiOutputRegressor
    from sklearn.ensemble import GradientBoostingRegressor
    from sklearn import metrics
    X, y = make_regression(n_samples=10, n_targets=3, random_state=1)  # 产生10个样本,每个样本100个属性,每个样本3个输出值
    print('样本特征维度',X.shape)
    print('样本输出维度',y.shape)
    clf = GradientBoostingRegressor(random_state=0)
    clf =MultiOutputRegressor(clf)
    clf.fit(X, y)
    y_pred = clf.predict(X) # 预测样本
    print('均方误差:',metrics.mean_squared_error(y, y_pred))  # 均方误差
    
    

    多输出分类

    Multioutput classification 支持能够被添加到任何带有 MultiOutputClassifier 标志的分类器中. 这种方法为每一个目标训练一个分类器。 这就允许产生多目标变量分类器。这种类的目的是扩展评估器用于评估一系列目标函数 (f1,f2,f3…,fn) ,这些函数在一个单独的预测矩阵上进行训练以此来预测一系列的响应 (y1,y2,y3…,yn)。

    # =========多输出分类================
    from sklearn.datasets import make_classification
    from sklearn.multioutput import MultiOutputClassifier
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.utils import shuffle
    import numpy as np
    X, y1 = make_classification(n_samples=10, n_features=100, n_informative=30, n_classes=3, random_state=1) # 生成分类数据集,10个样本,100个特征,30个有效特征,3种分类
    y2 = shuffle(y1, random_state=1)  # 分类结果随机排序
    y3 = shuffle(y1, random_state=2)  # 分类结果随机排序
    Y = np.vstack((y1, y2, y3)).T  # 多种分类结果组合成
    print('多输出多分类器真实输出分类:\n',Y)
    n_samples, n_features = X.shape # 10,100
    n_outputs = Y.shape[1] # 3个输出
    n_classes = 3 # 每种输出有3种分类
    forest = RandomForestClassifier(n_estimators=100, random_state=1)  # 生成随机森林多分类器
    multi_target_forest = MultiOutputClassifier(forest)  # 构建多输出多分类器
    y_pred = multi_target_forest.fit(X, Y).predict(X)
    print('多输出多分类器预测输出分类:\n',y_pred)
    
    展开全文
  • sklearn例程:多分类输出概率

    千次阅读 2020-12-24 09:51:33
    我们在拥有3个类别的数据集上,使用如下分类模型进行多分类:支持向量分类器(SVM Classification, 简称SVC)线性SVC在默认情况下不是概率分类器,但在此示例中启用了内置校准选项(probability=True)逻辑回归(Logistic...

    示例简介

    本示例介绍如何绘制不同分类器的分类概率。我们在拥有3个类别的数据集上,使用如下分类模型进行多分类:

    支持向量分类器(SVM Classification, 简称SVC)

    线性SVC在默认情况下不是概率分类器,但在此示例中启用了内置校准选项(probability=True)

    逻辑回归(LogisticRegression,简称LR),尝试了3种参数配置:

    采用L1正则化

    采用L2正则化和One-Vs-Rest模式,One-Vs-Rest简称OvR,即做多分类时,将1个类的样本作为正例,其他类的样本作为负例。

    使用One-Vs-Rest的逻辑回归不是开箱即用的多类分类器。在下文中可用看到,与其他模型估计量相比,在将第2类和第3类分离时会有一些问题。

    采用L2正则化和multinomial模式,multinomial即直接做多分类。

    高斯过程分类(GaussianProcessClassifier,简称GPC)。

    代码实现[Python]

    # -*- coding: utf-8 -*-

    print(__doc__)

    # Author: Alexandre Gramfort

    # License: BSD 3 clause

    import matplotlib.pyplot as plt

    import numpy as np

    from sklearn.metrics import accuracy_score

    from sklearn.linear_model import LogisticRegression

    from sklearn.svm import SVC

    from skle

    展开全文
  • 使用Pytorch完成多分类问题

    万次阅读 2021-11-06 16:33:46
    多分类问题在最后的输出层采用的Softmax Layer,其具有两个特点:1.每个输出的值都是在(0,1);2.所有值加起来和为1. 假设是最后线性层的输出,则对应的Softmax function为: 输出经过sigmoid运算即可是西安输出...
  • 前言虽然不是搞分类的,但是还是看看标签和多分类的区别。当然是选择原谅他啊…….找正规文档看哇. 分别来自scikit-learn.org和 维基 喂鸡百科国际惯例,贴上来源:Multiclass and multilabel algorithmsMulti-...
  • 使用深度学习进行“序列到序列”分类 此示例说明如何使用长短期记忆 (LSTM) 网络对序列数据的每个时间步进行分类。 要训练深度神经网络以对序列数据的每个时间步进行分类,可以使用“序列到序列”LSTM 网络。通过...
  • 回归预测 | MATLAB实现CNN(卷积神经网络)输入单输出 目录回归预测 | MATLAB实现CNN(卷积神经网络)输入单输出基本介绍模型背景程序设计拓展学习发展历程主要节点参考资料致谢 基本介绍 MATLAB实现CNN(卷积神经...
  • sigmoid和softmax是神经网络输出层使用的激活函数,分别用于两类判别和类判别。 binary cross-entropy和categorical cross-entropy是相对应的损失函数。 对应的激活函数和损失函数相匹配,可以使得error ...
  • 关于多分类神经网络的输出

    千次阅读 2019-03-21 21:45:50
    这与之前逻辑回归中的分类表示不同,在逻辑回归中,输出y属于类似于{1, 2, 3, 4}中的某个值,而这里输出的是一个向量。因此,神经网络解决分类问题的本质是把原分类问题分解为一类对其他类(one-vs-all)的...
  • 实例说明如何使用深度网络设计器创建简单的长短期记忆 (LSTM) 分类网络。 要训练深度神经网络以对序列数据进行分类,可以使用 LSTM 网络。LSTM 网络是一种循环神经网络 (RNN),可学习序列数据的时间步之间的长期...
  • 详解sigmoid与softmax, 多分类标签分类

    万次阅读 多人点赞 2018-09-19 21:35:50
    详解sigmoid与softmax, 多分类标签分类激活函数介绍sigmoid激活函数sigmoid激活函数的性质sigmoid激活函数的使用 激活函数介绍 对于熟悉机器学习或神经网络的读者来说,sigmoid与softmax两个激活函数并不陌生,...
  • 针对二分类问题,最后一层的输出可以采用不同的设置方式,关键是取决于目标值y_target的数据处理形式。 目录目标输出 (0 or 1)方案一方案二from_logits设置结果比较方案一方案二无概率处理结果目标输出 one_hot ...
  • pytorch分类模型输出预测

    千次阅读 2020-12-07 17:02:28
    output = model(inp) probs = F.softmax(output).detach().numpy()[0] pred = np.argmax(probs) 得到分类输出结果 c++ 使用torchscript 加载训练好的pytorch模型
  • 使用钩子函数hook() feat_act={} def get_activationb(name): def hook(model,input,output): feat_act[name]=output.detach() return hook model.avgpool.register_forward hook(get_activation('avgpool')) ...
  • 多任务学习可以运用到许多的场景。 首先,多任务学习可以学到多个任务的共享表示,这个共享表示具有较强的抽象能力,能够适应多个不同但相关的目标,通常...``相关任务多任务学习二分类多分类多标签分类相关关系 相关
  • 网络输出层处理 在二分类的时候, 输出层只有一个通道, 多分类就需要有 class_num(类别数, 包括背景) 个通道, 所以最后一个卷积时需要有 class_num 个 Filer, 还要修改激活函数为 softmax . 修改如下 # Keras 实现 ...
  • 多分类任务通常转化为个二分类任务,再对预测结果进行集成得出最终分类结果。 拆分为二分类任务通常有3种:一对一(OvO),一对其余(OvR)和(MvM)。 OvO: 将N个类别两两配对,共N(N-1)/2个分类任务,每...
  • softmax 回归(softmax regression)其实是 logistic 回归的一般形式,logistic 回归用于二分类,而 softmax 回归用于多分类,关于 logistic 回归可以看我的这篇博客????机器学习笔记九——线性模型原理以及python实现...
  • sklearn 多分类多标签算法

    万次阅读 2018-11-26 10:58:10
    转至元数据结尾 创建: 片刻,最新修改于: 2017-09-27 转至元数据起始   标签分类格式 One-Vs-The-Rest ... 多输出分类   原文链接 : http://scikit-learn.org/stable/modules/multicla...
  • 分类模型的最后一层输出是什么?

    千次阅读 2020-04-06 18:19:28
    下面用keras说明问题, 输出的都是0.11665422, 0.5079881 , 0.37535766 都是和为1的结果,现在很少见到不是这样的结果了吧(除非用sigmoid,这个一般用在二分类吧)。 待续吧。。。 另外有相关问题可以加入QQ群讨论...
  • 第1章sigmoid与二分类 [人工智能-深度学习-10]:神经网络基础 - 激活函数之sigmoid与二元逻辑分类的神经元模型_文火冰糖(王文兵)...sigmoid除了用于单分类,还可用于多分类。 2.1sigmoid与独立分类 在上...
  • 分类一般分为三种情况:二分类多分类标签分类标签分类比较直观的理解是,一个样本可以同时拥有几个类别标签,比如一首歌的标签可以是流行、轻快,一部电影的标签可以是动作、喜剧、搞笑,一本书的标签可以...
  • 应用XGboost实现多分类模型实践

    万次阅读 热门讨论 2019-04-04 16:44:45
    本文把XGBoost集成算法模型,应用在工业生产中,分析生产过程数据,提高...实验学习目标采用XGBoost多分类multi:softprob输出概率,在8000个样本条件下,训练模型,达到62%准确率。本文分享了实验中关键点和填过的坑。
  • 1.对一,就是直接输出分类结果,但是分类结果是怎么计算来的?和lstm的输出单元h与最后的分类结果有什么关系? 2.,就是输出每个类别的概率,比如3个类别做分类,输出一个3个元素的概率向量,那么这个...
  • 把问题转化为一个或个单目标分类问题,或是回归问题。2)算法适应。修改学习算法使得能直接处理multilabel的数据。问题转化方法 dubbed PTx法。包括PT1 对有标签的数据随机选取一个标签 PT2 直接把标签数大于1...
  • YOLOv5实战垃圾分类目标检测

    千人学习 2021-06-13 23:16:02
    垃圾分类是一项利国利民的民生工程,需要全社会的共同参与。YOLOv5是目前流行的强悍的目标检测技术。本项目采用YOLOv5实现垃圾分类目标检测。利用超万张已标注目标检测数据集进行训练,对居民生活垃圾图片进行检测,...
  • 神经网络输出个神经元

    千次阅读 2019-05-02 22:15:38
    由于matlab升级,已经不能想以前一样直接在newff函数里面规定好隐含层多少个,或者几层,还可以有个神经元的输出层。改版后需要输出层变成矩阵的形式,神经网络工具箱可以自动识别输出层有几个神经元。详细代码...
  • 支持向量机分类器能够输出测试实例与决策边界之间的距离,你可以将其用作信心分数。但是这个分数不能直接转化成类别概率的估算。如果创建SVM时,在Scikit-Learn中设置probability=True,那么训练完成后,算法将使用...
  •   今天晚上,笔者接到客户的一个需要,那就是:对多分类结果的每个类别进行指标评价,也就是需要输出每个类型的精确率(precision),召回率(recall)以及F1值(F1-score)。   对于这个需求,我们可以用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 693,361
精华内容 277,344
关键字:

多输出分类