【问题标题】:Use of 1-a weight in categorical focal loss在分类焦点损失中使用 1-a 权重
【发布时间】:2019-09-12 21:25:33
【问题描述】:

我正在尝试在具有多个类的 keras/tensorflow 中使用焦点损失,这导致使用 分类焦点损失 我猜。我找到了一些实现heretherethere

据我所知,焦点损失中的参数a 主要用于 二元焦点损失 情况,其中存在 2 个类,一个以 a 作为权重,另一个得到1-a 作为权重。在分类焦点损失的情况下,我发现所有实现只在每个类损失前面使用权重a,例如:

    # Calculate weight that consists of  modulating factor and weighting factor
    weight = alpha * y_true * K.pow((1-y_pred), gamma)
    # Calculate focal loss
    loss = weight * cross_entropy

    # Calculate Cross Entropy
    cross_entropy = -y_true * K.log(y_pred)
    # Calculate Focal Loss
    loss = alpha * K.pow(1 - y_pred, gamma) * cross_entropy

那么,我的问题是,为什么这样的权重因子会对训练过程产生任何影响?当然,损失通常用于计算每次迭代后添加的权重(当然,乘以学习率)。但这只是意味着每个类在损失部分之前得到相同的系数,所以没什么大不了的。这是否意味着我可以调整学习率并获得完全相同的效果?我在这里想念什么? 参数a的具体用途是什么?

我还发现了这个实现here,他们似乎也使用(1-a) 作为否定示例,尽管他们将值传递给keras.backend.binary_crossentropy,这使得我猜它更加复杂。

你知道哪个是正确的实现吗?

【问题讨论】:

  • 你解决了吗?如果没有,你能在这个问题上悬赏吗?

标签: python tensorflow keras


【解决方案1】:

TL;博士

它们是一样的。所以,就用更简单的吧。

加长版:

(玩具示例中的计算已在 numpy 中执行,我认为相同的功能也适用于 tensorflow

在对该问题进行了一些研究后,我得出以下结论:

  • a 系数使用固定方法的方法确实应用了(一种)焦点损失,因为它们将置信度得分和功率与伽马相反,但它并不完全是原始论文中提到的焦点损失。
  • 第二种方法似乎比原始方法更准确,但它们本质上是相同的(至少在这些实现中看起来如此)。

我使用一个玩具示例对这些损失进行了一些实验。例如使用 2 个前景类中的 8 个样本加上我们得到的背景:

gamma = 2
alpha2 = 0.25
preds = np.array(
    [[0.3, 0.2, 0.5], [0.1, 0.4, 0.4], [0.1, 0.8, 0.1], 
     [0.7, 0.2, 0.1], [0.75, 0.15, 0.1], [0.9, 0.05, 0.05],
     [0.72, 0.18, 0.1], [0.8, 0.1, 0.1]])
gt = np.array([[1, 0, 0], [0, 1, 0], [0, 1, 0], 
               [1, 0, 0], [1, 0, 0], [1, 0, 0], 
               [1, 0, 0], [1, 0, 0]]).astype(float)

两个焦点损失是:

focal_log_loss_v1 = -np.sum(alpha2 * gt * np.power((1 - preds), gamma) * np.log(preds), axis=-1)

alpha_factor = np.ones_like(gt) * alpha2
alpha_factor = np.where(gt == 1, alpha_factor, 1 - alpha_factor)
focal_weight2 = np.where(gt == 1, 1 - preds, preds)
focal_weight2 = alpha_factor * np.power(focal_weight2, gamma)
focal_log_loss_v2 = -np.sum(focal_weight2 * gt * np.log(preds), axis=-1)

结果表明:

focal_log_loss_v1

数组([0.14748667, 0.08246617, 0.00223144, 0.00802519, 0.00449503, 0.0002634 , 0.00643868, 0.00223144])

focal_log_loss_v3

数组([0.14748667, 0.08246617, 0.00223144, 0.00802519, 0.00449503, 0.0002634 , 0.00643868, 0.00223144])

这两种方法是等价的 (!)。这是出乎意料的(至少在我这边)。
无论如何,对此的解释在此命令中:

gt * np.log(preds)

数组([[-1.2039728 , -0. , -0. ],
[-0。 ,-0.91629073,-0。 ],
[-0。 ,-0.22314355,-0。 ],
[-0.35667494,-0。 , -0。 ],
[-0.28768207,-0。 , -0。 ],
[-0.10536052,-0。 , -0。 ],
[-0.32850407,-0。 , -0。 ],
[-0.22314355,-0。 , -0。 ]])

这基本上消除了所有非真实样本的所有贡献(意味着所有不属于真实样本的置信度分数)。因此,即使focal_weight2 包含非 gt 样本的非零值,它们也会在之后被消除。

focal_weight2

数组([[0.1225 , 0.03 , 0.1875 ],
[0.0075 , 0.09 , 0.12 ],
[0.0075 , 0.01 , 0.0075 ],
[0.0225 , 0.03 , 0.0075 ],
[0.015625, 0.016875, 0.0075 ],
[0.0025 , 0.001875, 0.001875],
[0.0196 , 0.0243 , 0.0075 ],
[0.01 , 0.0075 , 0.0075 ]])

这就是为什么这段代码会产生同样的损失:

alpha_factor = np.ones_like(gt) * alpha2
alpha_factor = np.where(gt == 1, alpha_factor, 0)
focal_weight2 = np.where(gt == 1, 1 - preds, 0)
focal_weight2 = alpha_factor * np.power(focal_weight2, gamma)
focal_log_loss_v3 = -np.sum(focal_weight2 * gt * np.log(preds), axis=-1)

focal_log_loss_v3

数组([0.14748667, 0.08246617, 0.00223144, 0.00802519, 0.00449503, 0.0002634 , 0.00643868, 0.00223144])

我不确定背景和前景样本之间是否应该有任何区别(这是另一个主题问题)。

【讨论】:

    【解决方案2】:

    我和你一样困惑,为什么他们将损失乘以一个常数。您提供的代码将alpha 作为参数,默认值 设置为0.25,但也许当您调用该函数时,您应该提供一个张量(与y_pred/y_true) 这个参数的权重?这是我能想到的唯一解释。

    但是,我确实认为您可以简单地在代码中完全省略这些权重,而是将您的权重提供给tf.fit()class_weight 参数,然后它会为您进行加权。你能告诉我这是否有效吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 2021-05-16
      • 2021-04-28
      • 2021-03-08
      • 1970-01-01
      • 2018-10-19
      • 2019-08-16
      相关资源
      最近更新 更多