5

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

谢谢。

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

4

3 回答 3

9

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 定义中没有类。

于 2017-01-17T22:17:10.113 回答
3

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

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

  • compile中,计算总损失。它分几个步骤进行:第一步创建一个损失列表,模型的每个输出都有一个损失列表。

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

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

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只是一种优雅的方式,可以在代码中的另一点对损失进行屏蔽和加权

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

于 2018-02-11T19:39:46.487 回答
2

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

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

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

于 2017-01-18T20:02:17.947 回答