【问题标题】:Keras with Lambda-Layer带有 Lambda 层的 Keras
【发布时间】:2018-11-22 17:02:42
【问题描述】:

我对 Keras 比较陌生,我即将建立一个 Dueling Q-Network 来训练一个 KI。我找到了一个代码 sn-p 来构建一个看起来很有效的模型。我只是不知道为什么,因为我对 Keras 中的 lambda 表达式不太熟悉。任何人都可以解释一下在以下模型中创建 lambda 层的工作原理吗? 非常感谢您!

def build_model():

    model = Sequential()
    model.add(Dense(units=16, activation='relu', input_dim = 2))
    model.add(Dense(units=32, activation='relu'))
    model.add(Dense(units=9, activation='relu'))

    #I definitely don't understand how the following layer works:
    model.add(Lambda(lambda i: K.expand_dims(i[:,0],-1) + i[:,1:] - K.mean(i[:,1:], keepdims=True), output_shape=(8,)))

    model.add(Dense(units=8, activation='linear'))
    model.compile(loss='mse',
    optimizer = RMSprop(lr=0.001) )
    return model

【问题讨论】:

  • 如果您需要更多帮助,请告诉我。
  • 谢谢你,你下面的回答完全解决了我理解这件事的问题:)

标签: python machine-learning lambda keras deep-learning


【解决方案1】:

我不熟悉您的特定研究领域,但我可以告诉您该层在做什么。 Lambda 层是当您想要对不来自 Keras 预定义的任何内容的输入定义自定义操作时。具体来说,您希望对进入 Keras 尚未处理的层的张量应用一些自定义操作。

Lambda 层的输入是 anonymous function,其中输入是进入该层的张量。但是请注意,您也可以在该层中指定任何函数或操作,并且它不必是匿名函数……只要它对输入张量进行操作并产生输出张量即可。然后,您定义要使用此输入张量执行的操作,并创建一个相应的输出张量,该输出张量将馈送到下一层。这种行为当然是假设我在这里看到的前馈网络。您可以将匿名函数视为用于执行操作的一次性函数,但您不希望它们在以后徘徊,因为在您指定如何处理输入张量后不再需要它们。

lambda i 因此表示您正在创建一个匿名函数,Lambda 层将在定义为i 的输入张量上运行。 K.expand_dims 确保您为broadcasting 添加单一维度。在这种情况下,我们希望将输入张量 i[:,0] 的第一列变成一维数组,并确保输入张量是具有单列的二维数组(即从 N, 数组到 @ 987654332@ 数组)。 -1 参数是您要扩展的轴。将此设置为-1 只会扩展最后一个维度,在这种情况下,最后一个维度是第一个(也是唯一一个)维度。

如果你不习惯广播,这个扩展数组的加法操作有点难以理解,但是一旦你掌握了它,它就是计算中最强大的机制之一。 i[:,1:] 对输入张量进行切片,以便我们考虑从第二列到末尾的张量。在幕后,将这个切片张量与展开的单列 i[:,0] 添加意味着该列被复制并单独添加到 i[:,1:] 中的每一列。

例如,如果 i[:,0][1, 2, 3, 4] 并且 i[:,1:][[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6],则执行 K.expand_dims(i[:,0], -1) + i[:,1:] 会导致 [[5, 6, 7, 8], [6, 7, 8, 9], [7, 8, 9, 10]]

拼图的最后一块是:K.mean(i[:,1:], keepdims=True)。我们取K.expand_dims(i[:,0], -1) + i[:,1:],然后用K.mean(i[:,1:], keepdims=True) 减去它。在这种情况下,K.mean 将从第二列开始的所有行的张量中找到 all 值的平均值。这是操作的默认行为。根据您使用K.mean 的方式,一个或多个维度可能会下降。 K.mean 的另一个输入是 axis,它允许您指定要分析张量中的平均值的维度。例如,如果您执行了axis=0,这将分别找到每列的平均值。 这将减少到值的一维张量。使用keepdims 关键字,如果您指定keepdims=True,这将确保张量仍然是2D,列数为1(即N x 1 张量而不是N, 张量)。默认行为是false

因此,通过执行K.mean 操作,我们确保最终结果为1 x 1,并从K.expand_dims(i[:,0],-1) + i[:,1:] 结果的每个值中减去该值。由于广播,这再次成为可能。

最后,我们确保该操作的输出形状给出大小为 8 的一维张量。

tl;dr

此操作是自定义操作,我们获取输入张量的第一列,将其添加到从第二列开始的所有其他列,然后用所有其他列的平均值减去该结果的每个值从第二列开始。此外,我们将张量的输出大小限制为一维,大小为 8。

【讨论】:

  • 太棒了!详尽的解释。但是,只有一件小事:“Lambda 层的输入是一个匿名函数”。这并不完全正确,因为您可以将任何函数传递给 Lambda 层,包括匿名函数。
  • @today 哦,对了。谢谢。我已经改变了它。我可以投票吗? :)
  • 当然 :) 虽然,我不是问这个问题的人 :)
  • @today 每一点都有帮助!还是谢谢你!
  • 很好的答案!这对我理解我在这里做什么很有帮助。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-21
  • 2018-06-16
  • 2021-01-16
  • 2017-12-09
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
相关资源
最近更新 更多