使用caffe从图像回归年龄时如何设计损失层

How to design loss layer when regressing age from image using caffe

我正在尝试用 caffe 重现以下论文

Deep EXpectation

最后一层有100个输出,每一层都隐含着预测年龄的概率。最终预测年龄由以下等式计算:

所以我想使用带有标签和预测值的 EUCLIDEAN_LOSS 进行亏损。

我展示了最后一个输出层和损失层的原型文本。

layer {
    bottom: "pool5"
    top: "fc100"
    name: "fc100"
    type: "InnerProduct"
    inner_product_param {
        num_output: 100
    }
}

layer {
    bottom: "fc100"
    top: "prob"
    name: "prob"
    type: "Softmax"
}

layer {
    name: "loss"
    type: "SoftmaxWithLoss"
    bottom: "fc100"
    bottom: "label"
    top: "loss"
    loss_weight: 1
}

就目前而言,我正在尝试使用 SoftmaxWithLoss。然而,这种损失更适合于分类而不是回归。在这种情况下,我该如何设计损失层?

提前致谢。

TL;DR
我曾经完成过类似的任务,根据我的经验,训练离散标签和回归单个连续值之间几乎没有区别(就输出精度而言)。


有几种方法可以解决这个问题:

1。回归单个输出

由于您只需要预测一个标量值,因此您应该训练您的网络这样做:

layer {
    bottom: "pool5"
    top: "fc1"
    name: "fc1"
    type: "InnerProduct"
    inner_product_param {
        num_output: 1  # predict single output
    }
}

您需要确保预测值在 [0..99]:

范围内
layer {
  bottom: "fc1"
  top: "pred01"  # map to [0..1] range
  type: "Sigmoid"
  name: "pred01"
}
layer {
  bottom: "pred01"
  top: "pred_age"
  type: "Scale"
  name: "pred_age"
  param { lr_mult: 0 }  # do not learn this scale - it is fixed
  scale_param {
    bias_term: false
    filler { type: "constant" value: 99 }
  }
}

一旦你在 pred_age 中有了预测,你就可以添加一个损失层

layer {
  bottom: "pred_age"
  bottom: "true_age"
  top: "loss"
  type: "EuclideanLoss"
  name: "loss"
}

不过,我建议在这种情况下使用 "SmoothL1",因为它更可靠。

2。回归离散预测的期望

您可以在caffe 中实现您的预​​测公式。为此,您需要一个 fixed 值 [0..99] 向量。有很多方法可以做到这一点,none 非常 straight-forward。这是使用 net-surgery 的一种方法:

首先,定义网络

layer {
  bottom: "prob"
  top: "pred_age"
  name: "pred_age"
  type: "Convolution"
  param { lr_mult: 0 }  # fixed layer. 
  convolution_param { 
    num_output: 1
    bias_term: false
  }
}
layer {
  bottom: "pred_age"
  bottom: "true_age"
  top: "loss"
  type: "EuclideanLoss"  # same comment about type of loss as before
  name: "loss"
}

你还不能使用这个网络,首先你需要将pred_age层的内核设置为0..99.

在python中加载新的

net = caffe.Net('path/to/train_val.prototxt', caffe.TRAIN)
li = list(net._layer_names).index('pred_age')  # get layer index
net.layers[li].blobs[0].data[...] = np.arange(100, dtype=np.float32)  # set the kernel
net.save('/path/to/init_weights.caffemodel')  # save the weights

现在您可以训练您的网了,但是请确保您是从'/path/to/init_weights.caffemodel'中保存的权重开始训练的。