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])
我不确定背景和前景样本之间是否应该有任何区别(这是另一个主题问题)。