InfogainLoss层

时间:2014-12-24 06:20:32

标签: numpy neural-network protocol-buffers deep-learning caffe

我希望在我的模型中使用InfogainLoss类型的丢失层。但我在定义它时遇到了困难。

  1. 是否有关于INFOGAIN_LOSS图层使用的教程/示例?

  2. 此层的输入,类概率,应该是SOFTMAX图层的输出,还是足以输入" top"完全连接的层?

  3. INFOGAIN_LOSS需要三个输入:类概率,标签和矩阵H。 矩阵H可以作为图层参数infogain_loss_param { source: "fiename" }提供 假设我有一个python脚本,使用Hnumpy.array计算为(L,L)形状dtype='f4'(其中L是我模型中的标签数)。

    1. 如何将numpy.array转换为binproto文件,该文件可作为infogain_loss_param { source }提供给模型?

    2. 假设我希望H作为第三个输入(底部)提供给损失层(而不是作为模型参数)。我怎么能这样做?
      我是否定义了一个新的数据层" top"是H?如果是这样,那么每次训练迭代都不会增加该层的数据,就像训练数据增加一样? 如何定义多个不相关的输入"数据"层,以及咖啡如何知道从培训/测试中读取数据"一批又一批,而来自H"数据"它知道在所有培训过程中只读一次吗?

3 个答案:

答案 0 :(得分:10)

1。是否有关于 InfogainLoss 图层使用的教程/示例?
可以找到一个很好的例子here:使用 InfogainLoss 来解决类不平衡问题。


2。该层的输入(类概率)应该是 Softmax 层的输出吗?
从历史上看,根据Yair's answer,答案过去是 YES "InfogainLoss"的旧实现需要是"Softmax"图层或任何其他图层的输出,以确保输入值在[0..1]范围内。

OP注意到在"InfogainLoss"图层上使用"Softmax"会导致数值不稳定。 His pull request,将这两个层组合成一个层(很像"SoftmaxWithLoss"层),于2017年4月14日被接受并合并到官方Caffe存储库中。该组合层的数学给出here

升级后的图层"外观和感觉"除了不再需要通过"Softmax"层明确传递输入之外,它与旧版本完全相同。


3。如何将numpy.array转换为binproto文件

在python中

H = np.eye( L, dtype = 'f4' ) 
import caffe
blob = caffe.io.array_to_blobproto( H.reshape( (1,1,L,L) ) )
with open( 'infogainH.binaryproto', 'wb' ) as f :
    f.write( blob.SerializeToString() )

现在,您可以使用INFOGAIN_LOSS作为参数将H图层添加到模型原型文本中:

layer {
  bottom: "topOfPrevLayer"
  bottom: "label"
  top: "infoGainLoss"
  name: "infoGainLoss"
  type: "InfogainLoss"
  infogain_loss_param {
    source: "infogainH.binaryproto"
  }
}

4。如何加载H作为数据层的一部分

引用Evan Shelhamer's post

  

目前还没有办法让数据层以不同的速率加载输入。每个前向传递所有数据层都将前进。但是,常量H输入可以通过使输入lmdb / leveldb / hdf5文件仅为H来完成,因为数据层将循环并继续加载相同的H.这显然浪费了磁盘IO。

答案 1 :(得分:2)

该图层正在总结

-log(p_i)

所以p_i需要在(0,1)中作为损失函数才有意义(否则更高的置信度得分会产生更高的损失)。请参阅下面的曲线,了解log的值(p )。

enter image description here

我认为他们不得不总结为1,但是通过Softmax图层传递它们将实现这两​​个属性。

答案 2 :(得分:1)

因为我不得不搜索许多网站才能迷惑整个网站 代码,我以为我分享我的实现:

用于计算每个类别的权重的H矩阵的Python层:

import numpy as np
import caffe


class ComputeH(caffe.Layer):
    def __init__(self, p_object, *args, **kwargs):
        super(ComputeH, self).__init__(p_object, *args, **kwargs)
        self.n_classes = -1

    def setup(self, bottom, top):
        if len(bottom) != 1:
            raise Exception("Need (only) one input to compute H matrix.")

        params = eval(self.param_str)
        if 'n_classes' in params:
            self.n_classes = int(params['n_classes'])
        else:
            raise Exception('The number of classes (n_classes) must be specified.')

    def reshape(self, bottom, top):
        top[0].reshape(1, 1, self.n_classes, self.n_classes)

    def forward(self, bottom, top):
        classes, cls_num = np.unique(bottom[0].data, return_counts=True)

        if np.size(classes) != self.n_classes or self.n_classes == -1:
            raise Exception("Invalid number of classes")

        cls_num = cls_num.astype(float)

        cls_num = cls_num.max() / cls_num
        weights = cls_num / np.sum(cls_num)

        top[0].data[...] = np.diag(weights)

    def backward(self, top, propagate_down, bottom):
        pass

和来自train_val.prototxt的相关部分:

layer {
    name: "computeH"
    bottom: "label"
    top: "H"
    type: "Python"
    python_param {
        module: "digits_python_layers"
        layer: "ComputeH"
        param_str: '{"n_classes": 7}'
    }
    exclude { stage: "deploy" }
}
layer {
  name: "loss"
  type: "InfogainLoss"
  bottom: "score"
  bottom: "label"
  bottom: "H"
  top: "loss"
  infogain_loss_param {
    axis: 1  # compute loss and probability along axis
  }
  loss_param {
      normalization: 0
  }
  exclude {
    stage: "deploy"
  }
}