【问题标题】:Is it possible to create a model in Keras Functional API without an input layer?是否可以在没有输入层的情况下在 Keras 功能 API 中创建模型?
【发布时间】:2021-04-02 15:26:51
【问题描述】:

我想在 Keras 中创建一个由 2 个卷积层、一个展平层和一个密集层组成的模型。这将是一个具有共享权重的模型,因此没有任何预定义的输入层。

可以使用顺序方式:

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Conv2D(10,3,2,'valid',activation=tf.nn.relu))
model.add(tf.keras.layers.Conv2D(20,3,2,'valid',activation=tf.nn.relu))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(200,activation=tf.nn.relu))

但是,使用 Functional API 会产生 TypeError:

model2 = tf.keras.layers.Conv2D(10,3,2,'valid',activation=tf.nn.relu)
model2 = tf.keras.layers.Conv2D(20,3,2,'valid',activation=tf.nn.relu)(model2)
model2 = tf.keras.layers.Flatten()(model2)
model2 = tf.keras.layers.Dense(200,activation=tf.nn.relu)(model2)

错误:

TypeError: Inputs to a layer should be tensors. Got: <tensorflow.python.keras.layers.convolutional.Conv2D object at 0x7fb060598100>

这样是不可能的,还是我错过了什么?

【问题讨论】:

  • 不能添加输入层有什么具体原因吗?
  • 在任何一个 API(顺序或函数)中都不可能,没有输入层的神经网络是没有意义的,你为什么要做这样的事情?
  • 我想共享权重。所以 2 个单独的输入层,然后是几个共享的卷积层,然后是 2 个分离的层。当然可以只使用一个共享层 (stackoverflow.com/questions/49875127/…),但我还没有看到如何使用更多共享层的示例。但是,如果我尝试将它们中的更多链接在一起,则会出现错误。

标签: python tensorflow keras functional-api


【解决方案1】:

keras 顺序 api 被设计为更易于使用,因此不如函数式 api 灵活。这样做的好处是可以通过传递给它的任何数据形状自动推断输入“层”形状。缺点是这个更容易使用的模型被简化了,所以你不能做像使用多个输入这样的事情。

来自keras 文档:

在以下情况下不适合使用顺序模型:

  • 您的模型有多个输入或多个输出
  • 您的任何层都有多个输入或多个输出
  • 您需要进行图层共享
  • 您需要非线性拓扑(例如,残差连接、 多分支模型)

函数式 api 被设计为更灵活,即多个输入,因此它不会为您进行任何类型的自动推理,因此会出现错误。在这种情况下,您必须显式传递一个输入层。对于您的用例,它不会自动推断形状可能看起来很奇怪,但是当您考虑更广泛的用例场景时,它是有意义的。

所以第二种情况应该是:

model2 = tf.keras.layers.Input((10,3,2)) # specified input layer
model2 = tf.keras.layers.Conv2D(10,3,2,'valid',activation=tf.nn.relu)(model2)
model2 = tf.keras.layers.Conv2D(20,3,2,'valid',activation=tf.nn.relu)(model2)
model2 = tf.keras.layers.Flatten()(model2)
model2 = tf.keras.layers.Dense(200,activation=tf.nn.relu)(model2)

更新

如果您想创建两个单独的模型并将它们连接在一起,您应该使用功能 API,然后由于它的限制,您必须使用输入层。所以你可以这样做:

import tensorflow as tf
from tensorflow.keras.layers import Input, Flatten, Dense, concatenate, Conv2D
from tensorflow.keras.models import Model

input1 = Input((10,3,2))
model1 = Dense(200,activation=tf.nn.relu)(input1)

input2 = Input((10,3,2))
model2 = Dense(200,activation=tf.nn.relu)(input2)

merged = concatenate([model1, model2])

merged = Conv2D(10,3,2,'valid',activation=tf.nn.relu)(merged)
merged = Flatten()(merged)
merged = Dense(200,activation=tf.nn.relu)(merged)

model = Model(inputs=[input1, input2], outputs=merged)

上面我们有两个单独的输入,然后是两个 Dense 层 - 您可以根据需要构建这些单独的线,然后将它们合并在一起以通过卷积层,您需要使用 tf.keras.layers.concatenate 层,然后您可以从那里继续联合模型。将整个事物包装在 Model 对象中,然后您就可以访问训练和推理方法,例如拟合/预测等。

【讨论】:

  • 感谢您的回答。以及如何附加 2 个输入层?这就是为什么我想在没有输入层的情况下做一个没有输入的层序列,然后将 2 个单独的输入层传递给该序列,创建 2 个具有单独输入、单独输出但共享卷积层的单独模型。
  • 谢谢,但我认为这仍然不是我想要实现的。我想要这样的东西(stackoverflow.com/questions/49875127/…),但有多个共享层(他们在链接的问题中称之为密集)。我可能会问另一个问题,因为我问过 X,但我真正需要的是 Y。
  • 我同意也许问一个单独的问题会更清楚。如果您认为我回答了您最初的问题,但我会很感激“接受”:)
【解决方案2】:

keras 中的链接通过在层中传播tensors 来工作。因此,在您的第二个示例中,开头 model2keras.layers.Layer 的一个实例,而不是 tf.Tensor 这就是您收到错误的原因。

Input 创建一个张量,然后可以使用它来链接图层。所以如果没有具体原因,你就加一个吧:

model2 = tf.keras.layers.Input((10,3,2))
model2 = tf.keras.layers.Conv2D(10,3,2,'valid',activation=tf.nn.relu)(model2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 2020-01-02
    • 2023-03-29
    • 2014-06-16
    • 2011-05-08
    • 2021-10-11
    • 1970-01-01
    相关资源
    最近更新 更多