【问题标题】:Keras mean squared error loss layerKeras均方误差损失层
【发布时间】:2017-06-02 03:14:35
【问题描述】:

我目前正在实现一个自定义损失层,在此过程中,我偶然发现了目标.py 文件 [1] 中均方误差的实现。我知道我在理解这个损失计算时遗漏了一些东西,因为我一直认为平均值是在每个小批量(张量的轴 0)中的每个输出的样本中单独完成的,但看起来平均值实际上是在最后一个轴上完成,在一个向量中,这意味着它是在输出上完成的。我在处理我的自定义损失层时偶然发现了这一点,因为它需要对一些输出的损失进行折扣,因为在特定位置的训练输出是一个特定值。无论如何,我对均方误差的理解不正确吗?为什么 Keras 会使用最后一个轴,从而将 1xn 输出向量转换为 1x1 输出向量?

谢谢。

[1]https://github.com/fchollet/keras/blob/master/keras/objectives.py#L7

【问题讨论】:

  • 你认为 K.mean 是什么意思? :)
  • 抱歉,我调整了我的问题。我的意思是我没有看到平方发生在哪里,而不是平均值。
  • 那就是 K.square
  • 你读完了我的整个问题吗?
  • 是的,但无论如何这里有多个问题,我只是指出一个。

标签: python deep-learning theano keras mean-square-error


【解决方案1】:

MSE 损失的相关代码如下:

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

这里首先将 y_pred 和 y_true 相减,然后将该结果传递给 K.square,它如预期的那样返回其参数的平方,然后将该结果提供给 K.mean,它计算平均值。

所以代码显然正在做它应该做的事情。关于为什么要对最后一个轴进行操作,这与类无关,只是一个约定。请注意,一般情况下,MSE 定义中没有类。

【讨论】:

  • 啊,你说得对,我错过了代码中的 K.square。哎呀。我在一个私人网络上,不幸的是我无法复制/粘贴代码,不得不手动插入它。在这种情况下,我不正确地用手卡住了它。因此,您对我最后问的最后一个问题是正确的。
  • 谢谢你的回答,顺便说一句!然而,轴确实是我提出问题的原因。实际上,他们使用axis=-1而不是axis=0对我来说意义重大,原因是他们如何定义通过网络的张量的约定。它们强制您使用批量大小作为张量的第一个维度,并且对于向量中的一组值作为输出,强制将其作为最后一个维度。这意味着他们要承担所有这些输出的损失,而不是单独承担每一个输出。
  • 我知道我在复制时做错了什么。我不小心复制了 mean_absolute_error 而不是 mean_squared。该部分已修复,但轴问题仍然困扰着我。
  • 什么意思? @Cor
  • 什么意思? @CoreyJ.Nolet 是完全正确的。应在批次间取平均值。为什么是axis=-1?
【解决方案2】:

让我们详细说明如何在 Keras 中计算损失的步骤,以证明所有损失计算中的 axis=-1 都是正确的:

  • 所以我们在losses.py 中选择一个损失,我们将传递给我们模型的compile 方法。

  • 在compile 中,计算总损失。它分几个步骤发生:The first step 创建一个损失列表,一个用于模型的每个输出。

  • 第一步调用_weighted_masked_objective,根据文档“向目标函数添加对掩蔽和样本加权的支持”
  • 基本上,_weighted_masked_objective 返回一个新的目标函数,其中考虑了用户在使用方法fit 时将提供的weights 和mask 参数。

如果我将代码剪切为只包含对问题重要的行,我们就会得到类似的结果。

def _weighted_masked_objective(fn):
    def weighted(y_true, y_pred, weights, mask=None):
          score_array = fn(y_true, y_pred) # Compute loss as in losses.py
          return K.mean(score_array) # Average over all axis

class Model(Container):
    def compile(self, optimizer, loss, metrics=None, loss_weights=None,
                sample_weight_mode=None, weighted_metrics=None,
                target_tensors=None, **kwargs):
        weighted_losses = [_weighted_masked_objective(fn) for fn in loss_functions]

所以最后,损失确实是在每个维度上平均的,使用axis=-1 只是一种优雅的方式,可以在代码中的另一点启用损失的屏蔽和加权

注意:我没有解释其他步骤,因为它们无助于回答问题。

【讨论】:

    【解决方案3】:

    我相信,在与同事交谈后,我了解这种情况并有适当的解决方案。虽然我知道 Theano 提供了在 GPU 上运行矩阵运算的惰性求值张量函数,但我没有意识到 Keras 的损失函数实际上是以编译后的 theano 执行图足够智能以缓存某些值,以便在整个网络中正确地反向传播损失值。由于我正在创建的网络类型,我潜心编写自己的自定义损失函数,但并没有完全了解 Theano 在函数计算后如何实际处理损失。

    据我所知,我担心 Keras 使用最后一个轴是一个问题是正确的。就我而言,我有一个完全卷积的深度神经网络,损失函数的输入是 (x, 7, 16, 16),其中 x 是小批量的大小。通常,神经网络输出一个矩阵,其中第一个维度是小批量大小,第二个(通常是最后一个)维度是输出向量的实际大小。因此,使用输出张量中的最后一个轴来执行均方误差的实际“均值”部分是不正确的。相反,轴应该是 1(在从零开始的索引的情况下),因为它是 7 个实际的回归输出特征,需要对反向传播进行区分。

    我最初知道axis = -1 可能不正确,我发布此问题的原因是因为我无法完全解释原因。自从我不得不深入研究神经网络背后的数学以来已经有很长时间了,但当我最终这样做时,我能够解决差距(我认为)。我在此处发布此回复,以供将来可能遇到同样问题或对 Theano 张量框架的理解存在差距的人使用。

    【讨论】:

      猜你喜欢
      • 2019-05-23
      • 2017-11-23
      • 2017-05-11
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多