Python 1-a权重在分类焦点丢失中的应用

Python 1-a权重在分类焦点丢失中的应用,python,tensorflow,keras,Python,Tensorflow,Keras,我试图在keras/tensorflow中使用多个类别的焦点损失,我想这会导致使用分类焦点损失。我已经找到了一些实现和/或 据我所知,焦损中的参数a主要用于二进制焦损情况,其中存在两类,一类得到a作为权重,另一类得到1-a作为权重。在分类焦点丢失的情况下,我发现所有实现在每个类丢失之前只使用权重a,如: # Calculate weight that consists of modulating factor and weighting factor weight = alph

我试图在keras/tensorflow中使用多个类别的焦点损失,我想这会导致使用分类焦点损失。我已经找到了一些实现和/或

据我所知,焦损中的参数
a
主要用于二进制焦损情况,其中存在两类,一类得到
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

所以,我的问题是,为什么这样的权重因素会在训练过程中产生任何影响?当然,损失通常用于计算每次迭代后增加的权重(乘以当然是学习率)。但这只是意味着每个类在损失部分之前都得到相同的系数,所以没什么大不了的。这意味着我可以调整学习速度,并有同样的效果?我错过了什么? 参数
a
的确切用途是什么

我还发现,在这个实现中,他们似乎也使用
(1-a)
作为否定示例,尽管他们将值传递给
keras.backend.binary\u crossentropy
,我想这会使它更加复杂


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

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

但是,我确实认为您可以在代码中完全忽略这些权重,而是将权重提供给
tf.fit()
class\u weight
参数,然后这将为您进行权重计算。你能告诉我这是否有效吗;博士

它们是一样的。所以,只需使用更简单的一个

较长版本:

(玩具示例中的计算已在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])

阵列([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])


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

您解决了吗?如果没有,你能在这个问题上悬赏吗?
focal_weight2
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