首页 文章

InfogainLoss层

提问于
浏览
14

我希望在我的模型中使用InfogainLoss类型的丢失层 . 但我很难正确定义它 .

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

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

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

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

  • 假设我想将 H 作为损失层的第三个输入(底部)提供(而不是作为模型参数) . 我怎样才能做到这一点?
    我是否定义了一个新的数据层"top"是 H ?如果是这样,那么每次训练迭代都不会增加该层的数据,就像训练数据增加一样?如何定义多个不相关的输入"data"层,以及caffe如何知道从批次后批量读取培训/测试"data"层,而从 H "data"层知道只读一次所有培训过程?

3 回答

  • 8

    我仍然没有完整回答我的问题 . 这个答案仅涵盖我的第三和第四部分:
    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() )
    

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

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

    4.如何加载 H 作为DATA层的一部分

    引用Evan Shelhamer's post

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


    至于我问题的前两部分:
    1.是否有关于 InfogainLoss 图层使用的教程/示例?:
    一个很好的例子可以找到here:使用 InfogainLoss 来解决类不 balancer 问题 .

    2.此层的输入(类概率)应该是 Softmax 层的输出吗?
    根据Yair's answer答案是YES它应该是 Softmax 图层的输出(或确保输入值在[0..1]范围内的任何其他图层) .


    最近,我注意到在 "Softmax" 层上使用 "InfogainLoss" 会导致数值不稳定 . 因此,我建议将这两个层组合成一个层(很像 "SoftmaxWithLoss" 层) . 该组合层的数学给出here . 可以在this pull request中找到此"combined" infogainLoss Softmax的实现 .

  • 2

    该层正在总结

    -log(p_i)
    

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

    enter image description here

    我不认为他们必须总结为1,但是通过Softmax层传递它们将实现这两个属性 .

  • 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"
      }
    }
    

相关问题