【问题标题】:How to implement sparse mean squared error loss in Keras如何在 Keras 中实现稀疏均方误差损失
【发布时间】:2017-11-23 18:25:08
【问题描述】:

我想修改以下 keras 均方误差损失 (MSE),以便仅对损失进行稀疏计算。

def mean_squared_error(y_true, y_pred): return K.mean(K.square(y_pred - y_true), axis=-1)

我的输出y 是一个 3 通道图像,其中第三通道仅在要计算损失的那些像素处为非零。知道如何修改上述内容以计算稀疏损失吗?

【问题讨论】:

    标签: machine-learning neural-network computer-vision keras conv-neural-network


    【解决方案1】:

    这不是您正在寻找的确切损失,但我希望它会给您一个编写函数的提示(另请参阅 here 以获取 Github 讨论):

    def masked_mse(mask_value):
        def f(y_true, y_pred):
            mask_true = K.cast(K.not_equal(y_true, mask_value), K.floatx())
            masked_squared_error = K.square(mask_true * (y_true - y_pred))
            masked_mse = (K.sum(masked_squared_error, axis=-1) /
                          K.sum(mask_true, axis=-1))
            return masked_mse
        f.__name__ = 'Masked MSE (mask_value={})'.format(mask_value)
        return f
    

    该函数计算预测输出的所有值的 MSE 损失,但真实输出中对应值等于掩码值(例如 -1)的元素除外。

    两个音符:

    • 计算平均值时,分母必须是非屏蔽值的计数,而不是 数组的维度,这就是为什么我不使用 K.mean(masked_squared_error, axis=1) 而我 而是手动平均
    • 掩码值必须是一个有效数字(即np.nannp.inf 不会做这项工作),这意味着您必须调整您的数据,使其不包含mask_value

    在本例中,目标输出始终为[1, 1, 1, 1],但一些预测值被逐渐屏蔽。

    y_pred = K.constant([[ 1, 1, 1, 1], 
                         [ 1, 1, 1, 3],
                         [ 1, 1, 1, 3],
                         [ 1, 1, 1, 3],
                         [ 1, 1, 1, 3],
                         [ 1, 1, 1, 3]])
    y_true = K.constant([[ 1, 1, 1, 1],
                         [ 1, 1, 1, 1],
                         [-1, 1, 1, 1],
                         [-1,-1, 1, 1],
                         [-1,-1,-1, 1],
                         [-1,-1,-1,-1]])
    
    true = K.eval(y_true)
    pred = K.eval(y_pred)
    loss = K.eval(masked_mse(-1)(y_true, y_pred))
    
    for i in range(true.shape[0]):
        print(true[i], pred[i], loss[i], sep='\t')
    

    预期的输出是:

    [ 1.  1.  1.  1.]  [ 1.  1.  1.  1.]  0.0
    [ 1.  1.  1.  1.]  [ 1.  1.  1.  3.]  1.0
    [-1.  1.  1.  1.]  [ 1.  1.  1.  3.]  1.33333
    [-1. -1.  1.  1.]  [ 1.  1.  1.  3.]  2.0
    [-1. -1. -1.  1.]  [ 1.  1.  1.  3.]  4.0
    [-1. -1. -1. -1.]  [ 1.  1.  1.  3.]  nan
    

    【讨论】:

      【解决方案2】:

      为防止出现nan,请按照说明here。以下假设您希望掩码值(背景)等于零:

       # Copied almost character-by-character (only change is default mask_value=0)
       # from https://github.com/keras-team/keras/issues/7065#issuecomment-394401137
       def masked_mse(mask_value=0):
          """
          Made default mask_value=0; not sure this is necessary/helpful
          """
          def f(y_true, y_pred):
              mask_true = K.cast(K.not_equal(y_true, mask_value), K.floatx())
              masked_squared_error = K.square(mask_true * (y_true - y_pred))
              # in case mask_true is 0 everywhere, the error would be nan, therefore divide by at least 1
              # this doesn't change anything as where sum(mask_true)==0, sum(masked_squared_error)==0 as well
              masked_mse = K.sum(masked_squared_error, axis=-1) / K.maximum(K.sum(mask_true, axis=-1), 1)
              return masked_mse
          f.__name__ = str('Masked MSE (mask_value={})'.format(mask_value))
          return f
      

      【讨论】:

      • @baldassarreFe 我注意到您的答案也在上述位置;我建议根据此观察对您的答案进行修改。
      猜你喜欢
      • 2017-06-02
      • 1970-01-01
      • 2020-10-12
      • 2019-05-23
      • 2020-04-28
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多