Tensorflow/Keras:惩罚特定错误/混乱的成本函数

Tensorflow/Keras:惩罚特定错误/混乱的成本函数,tensorflow,keras,loss-function,false-positive,cross-entropy,Tensorflow,Keras,Loss Function,False Positive,Cross Entropy,我有一个超过10个类的分类场景,其中一个类是专用的“垃圾”类。有了CNN,我目前的准确率达到96%左右,这对我来说已经足够好了 在这个特定的应用程序中,误报(将“垃圾”识别为任何非垃圾类)比混淆非垃圾类或误报(识别任何非垃圾类而不是“垃圾”)严重得多。为了减少这些误报,我正在寻找一个合适的损失函数 我的第一个想法是使用分类交叉熵,并在检测到假阳性时添加一个惩罚值:(伪代码) 我的Keras实施是: def penalized_cross_entropy(y_true, y_pred, garba

我有一个超过10个类的分类场景,其中一个类是专用的“垃圾”类。有了CNN,我目前的准确率达到96%左右,这对我来说已经足够好了

在这个特定的应用程序中,误报(将“垃圾”识别为任何非垃圾类)比混淆非垃圾类或误报(识别任何非垃圾类而不是“垃圾”)严重得多。为了减少这些误报,我正在寻找一个合适的损失函数

我的第一个想法是使用分类交叉熵,并在检测到假阳性时添加一个惩罚值:(伪代码)

我的Keras实施是:

def penalized_cross_entropy(y_true, y_pred, garbage_id=0, weight=1.0):
    ref_is_garbage = K.equal(K.argmax(y_true), garbage_id)
    hyp_not_garbage = K.not_equal(K.argmax(y_pred), garbage_id)
    penalty_ind = K.all(K.stack([ref_is_garbage, hyp_not_garbage], axis=0), axis=0) # logical and
    penalty = K.cast(penalty_ind, dtype='float32')
    return K.categorical_crossentropy(y_true, y_pred) + weight * penalty
我尝试了不同的
权重值
,但无法减少误报。对于较小的值,惩罚完全无效(如预期),对于非常大的值(例如,
weight=50
),网络仅识别单个类别

  • 我的方法完全是胡说八道还是理论上可行?(这是我第一次使用非标准损耗函数)

  • 是否有其他/更好的方法来惩罚此类假阳性错误?遗憾的是,大多数文章都集中在二进制分类上,对于多类的情况,我找不到太多

编辑:

如评论中所述,上述处罚是不可区分的,因此对培训升级没有影响。这是我的下一次尝试:

penalized_cross_entropy(y_true, y_pred, garbage_id=0, weight=1.0):
    ngs = (1 - y_pred[:, garbage_id]) # non garbage score (sum of scores of all non-garbage classes)
    penalty = y_true[:, garbage_id] * ngs / (1.-ngs)
    return K.categorical_crossentropy(y_true, y_pred) + weight * penalty
在这里,所有非垃圾类的综合得分被添加到所有误报的minibatch样本中。对于非误报的样本,惩罚为0

我使用一个小型前馈网络和sgd优化器在mnist上测试了实现,使用类“5”作为“垃圾”:

  • 仅使用交叉熵,精度约为0.9343,而 “假阳性率”(识别为其他内容的“5”类图像) 是0.0093

  • 使用惩罚交叉熵(权重3.0),准确度为0.9378 假阳性率为0.0016


显然这是可行的,但我不确定这是否是最好的方法。另外,adam优化器不能很好地处理这个丢失函数,这就是我必须使用sgd的原因。

这个实现真的有效吗?您正在使用的某些操作似乎是不可微的(例如argmax),您是否考虑过
fit()
方法的
sample\u weights
参数?这可能是定义自己损失的另一种选择。似乎您希望将误差乘以一个权重。当计算梯度时,权重加法不是一个NOP吗?你想让重量影响梯度。Keras没有抱怨缺少梯度。我怀疑这是因为交叉熵有一个有效的梯度,惩罚“无”梯度可能会被忽略。。。我编辑了这个问题。这个实现真的有效吗?您正在使用的某些操作似乎是不可微的(例如argmax),您是否考虑过
fit()
方法的
sample\u weights
参数?这可能是定义自己损失的另一种选择。似乎您希望将误差乘以一个权重。当计算梯度时,权重加法不是一个NOP吗?你想让重量影响梯度。Keras没有抱怨缺少梯度。我怀疑这是因为交叉熵有一个有效的梯度,惩罚“无”梯度可能会被忽略。。。我编辑了这个问题。
penalized_cross_entropy(y_true, y_pred, garbage_id=0, weight=1.0):
    ngs = (1 - y_pred[:, garbage_id]) # non garbage score (sum of scores of all non-garbage classes)
    penalty = y_true[:, garbage_id] * ngs / (1.-ngs)
    return K.categorical_crossentropy(y_true, y_pred) + weight * penalty