Caffe中的多类别分类

15

我认为我们可以编写一份关于如何执行多类别分类的Caffe描述。

所谓多类别分类是指:输入数据包含多个模型输出类别的表示,或者仅可归类到多个模型输出类别中的其中一个。

例如:包含猫和狗的图像应该对猫和狗预测类别都输出(理想情况下)约1的概率,并且对其它类别全部输出约0的概率。

  1. 基于这篇论文这个失效并关闭了的PR以及这个开放的PR,看起来Caffe完全能够接受标签。这是正确的吗?

  2. 构建这样的网络是否需要使用多个神经元(内积->ReLU->内积)和softmax层,就像这篇论文第13页所示;或者Caffe的ip和softmax目前支持多个标签维度?

  3. 当我将标签传递给网络时,哪个例子说明了正确的方法(如果不是同时)?:

    例如:猫吃苹果 注意:这里使用了Python语法,但我使用的是c++源代码。

    第0列 - 类在输入中; 第1列 - 类不在输入中

[[1,0],  # Apple
 [0,1],  # Baseball
 [1,0],  # Cat
 [0,1]]  # Dog

第0列 - 类别在输入中

[[1],  # Apple
 [0],  # Baseball
 [1],  # Cat
 [0]]  # Dog

如果有任何不清楚的地方,请告诉我,我会提供示意图以阐明我要问的问题。


1
你是指每张图像固定数量的标签,还是每张图像的标签数量不同?也就是说,你是否总是期望获得比如说2个标签,或者你是否期望对于某些图像有2个标签,而对于其他图像有更多的标签? - Shai
2
@Shai 后者听起来像一个非常有趣的问题!但在我的情况下,标签的尺寸将是固定的。 - Aidan Gomez
2个回答

9
很好的问题。我相信这里没有单一的“规范”答案,你可能会发现几种不同的方法来解决这个问题。我将尽力展示一种可能的方法。它略有不同于你提出的问题,因此我将重新陈述问题并提出一个解决方案。 问题:给定一个输入图像和一组C类,对于每个类别,指示它是否在图像中呈现。 输入:在训练时,输入是图像对和一个C维二进制向量,表示C类中的每个类别是否在图像中存在。 输出:给定一张图像,输出一个C维二进制向量(与你在问题中提出的第二种形式相同)。 让Caffe胜任这项工作:为了使此项工作正常运行,我们需要使用不同的损失函数修改网络的顶层。
但首先,让我们了解一下通常使用Caffe的方式,然后再看看需要进行的更改。
现在的情况:图像被输入到网络中,经过卷积/池化/...层,最终通过一个具有C个输出的"InnerProduct"层。这些C个预测值进入"Softmax"层,抑制除最主导的类之外的所有类别。一旦突出显示单个类别,"SoftmaxWithLoss"层检查突出显示的预测类别是否与实际类别相匹配。 < p > 你需要什么:现有方法的问题在于"Softmax"层,它基本上只选择一个类。我建议你用"Sigmoid"替换它,将C输出中的每个类映射为指示器,表示图像中是否存在该特定类。对于训练,你应该使用"SigmoidCrossEntropyLoss"代替"SoftmaxWithloss"层。


@mintaka,你提供的多标签softmax与本例中允许多个类别的情况不同。 - Shai
@mintaka 这里的情况是一个单一输入可以被标记为多个类别。在这个答案中,标记是每像素进行的:也就是说,每个输入都是一张图像,图像中的每个像素都应该得到一个标签,但仍然是一个像素对应一个标签,没有像素可以被标记为多个类别。你看到区别了吗? - Shai
谢谢,Shai。我理解这篇文章在讨论多标签分类(即一张图片属于多个类别)。抱歉我之前的回复没有表述清楚。我之前认为 SoftmaxWithLossLayer 没有多标签实现,直到看到上次回复中提到的那篇文章。所以我想知道现在 caffe 中的 SoftmaxWithLossLayer 是否支持多标签分类? - mintaka
2
@user570593 在训练时使用sigmoidcrossentropyloss,部署时使用sigmoid。 - Shai
你能给我一个使用sigmoidcrossentropyloss进行二元分类的prototxt文件示例吗?你可以回复http://stackoverflow.com/questions/36795427/how-to-use-sigmoidcrossentropyloss-in-caffe-for-binary-class-classification? - user570593
显示剩余3条评论

0

由于一张图像可以有多个标签,最直观的方法是将此问题视为C个独立的二元分类问题,其中C是不同类别的总数。因此,很容易理解@Shai所说的内容

添加一个“Sigmoid”层,将每个C输出映射到指示器,表示该特定类别是否存在于图像中,并应使用“SigmoidCrossEntropyLoss”而不是“SoftmaxWithloss”层。损失是这些C SigmoidCrossEntropyLoss的总和。


当你说要添加 Sigmoid 层时,你是指首先添加一个 Sigmoid 层,然后再添加一个 SigmoidCrossEntropyLoss 层吗?这与 train_val.prototxt 有关。@Shai @kli_nlpr - user4911648

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接