【问题标题】:Keras Sequential without providing input shapeKeras Sequential 不提供输入形状
【发布时间】:2019-09-10 13:04:51
【问题描述】:

我目前有一个看起来像这样的 keras 模型:

model = keras.Sequential()
model.add(keras.layers.Dense(100, activation=tf.nn.relu))
model.add(keras.layers.Dense(100, activation=tf.nn.relu))
model.add(keras.layers.Dense(len(labels), activation=tf.nn.softmax))

Keras documentation 告诉我:

模型需要知道它应该期望什么输入形状。出于这个原因,顺序模型中的第一层(并且只有第一层,因为后面的层可以进行自动形状推断)需要接收有关其输入形状的信息

然而,尽管我从未指定输入的形状,但实际上模型训练得很好,没有错误。

它如何知道预期的形状?如果我不提供输入形状,默认行为是什么?它将如何影响我的模型?

编辑:这是使用 tf.keras,也就是 keras 的 Tensorflow 后端

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:

    很好的观察 - 我相信 Keras 文档应该更新。当没有提供输入形状时,Keras 从 Model.fit 的参数 x 推断它,然后才构建整个模型。具体来说,这就是正在发生的事情:

    1. Sequential 模型中添加 Keras 层时,由于从未设置参数input_shape(以及扩展的batch_input_shape),所以属性Model.inputs 仍然是None(请参阅Sequential.add)。
    2. 然后,在Model.fit 中,他们检查是否设置了Model.inputs(请参阅Model.fitModel._standardize_user_data),如果没有设置,他们从提供的输入数组推断输入形状。李>
    3. 最后,在Model._set_inputs 中,他们使用推断的input_shape 构建了整个模型(参见Model._set_inputs)。

    这可以通过在拟合模型之前打印一些权重(例如print(model.layers[0].get_weights()))来验证。你会看到,当参数input_shapebatch_input_shape没有提供给模型的第一层时,由于模型尚未构建,权重数组为空。

    【讨论】:

    • 这似乎是最正确的答案。形状检测不是特定于 tensorflow 的功能,但它仅在 tf.keras 中正确记录。
    【解决方案2】:

    文档The Sequential model 已于 2020/04/12 更新。 Specifying the input shape in advance 部分澄清了这个问题。

    当您实例化一个没有输入形状的 Sequential 模型时,它不是“构建”的:它没有权重(调用 model.weights 会导致错误说明这一点)。当模型首先看到一些输入数据时创建权重:

    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    
    
    model1 = keras.Sequential(
        [
            layers.Dense(2, activation="relu"),
            layers.Dense(3, activation="relu"),
            layers.Dense(4),
        ]
    )  # No weights at this stage!
    
    for layer in model1.layers:
        print(layer.weights)  # Empty
    
    # At this point, you can't do this:
    # model1.weights
    
    # You also can't do this:
    # model1.summary()
    
    # Call the model on a test input
    x = tf.ones((1, 4))
    y = model1(x)
    
    # Once a model is "built", you can call its summary() method to display its contents:
    
    model1.summary()
    

    您可以通过将Input 对象传递给您的模型来启动您的模型,以便它从一开始就知道其输入形状:

    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    
    model2 = keras.Sequential()
    model2.add(keras.Input(shape=(4,)))
    model2.add(layers.Dense(2, activation="relu"))
    model2.add(layers.Dense(3, activation="relu"))
    model2.add(layers.Dense(4))
    
    for layer in model2.layers:
        print(layer.weights)
    
    print(model2.weights)
    
    model2.summary()
    

    一个简单的替代方法是将input_shape 参数传递给您的第一层:

    model2.add(layers.Dense(2, activation="relu", input_shape=(4,)))
    

    使用此类预定义输入形状构建的模型始终具有权重(甚至在看到任何数据之前),并且始终具有定义的输出形状。

    最后,文件说:

    一般来说,如果您知道顺序模型的输入形状是什么,建议您始终提前指定输入形状。

    回到你的问题:

    它如何知道预期的形状?

    如果没有定义输入形状,模型将匹配它首先看到的数据。

    x = tf.ones((1, 4))
    y = model1(x)
    
    model1.summary()
    
    # Output
    Model: "sequential"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    dense_2 (Dense)              (1, 2)                    10        
    _________________________________________________________________
    dense_3 (Dense)              (1, 3)                    9         
    _________________________________________________________________
    dense_4 (Dense)              (1, 4)                    16        
    =================================================================
    Total params: 35
    Trainable params: 35
    Non-trainable params: 0
    _________________________________________________________________
    
    x = tf.ones((3, 5, 10))
    y = model1(x)
    model1.summary()
    
    # Output:
    Model: "sequential"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    dense_2 (Dense)              (3, 5, 2)                 22        
    _________________________________________________________________
    dense_3 (Dense)              (3, 5, 3)                 9         
    _________________________________________________________________
    dense_4 (Dense)              (3, 5, 4)                 16        
    =================================================================
    Total params: 47
    Trainable params: 47
    Non-trainable params: 0
    _________________________________________________________________
    

    如果我不提供输入形状,默认行为是什么?它将如何影响我的模型?

    如果你没有预先指定模型的输入形状,模型没有权重,你不能调用model.summary(),因为它没有被构建。

    【讨论】:

      【解决方案3】:

      TensorFlow 版本和 Keras 文档之间似乎存在不相关性。

      据我所知,您所指的文档是来自 Keras 的文档,而您使用的 TensorFlow 版本是 2.0.0 >= alpha 版本,其 Keras 内部版本不同。

      您应该检查 TensorFlow 2.0 中的 Keras 文档,否则您很可能会遇到不匹配的情况。

      【讨论】:

      • 你似乎是对的。在 TF 文档(不是 Keras)的 this page 上,它说“请注意,您也可以省略 input_shape 参数:在这种情况下,模型会在您第一次调用 fit(或其他训练和评估方法)时构建。”
      • 是的,这就是为什么我说最好去那里看看。 TF 2.0 中的 Keras 与“准系统”Keras 相比存在一些差异。
      • 我为普通的 keras 测试了它 - 行为是一样的
      猜你喜欢
      • 2020-12-11
      • 2018-02-16
      • 1970-01-01
      • 2020-06-10
      • 2017-08-14
      • 2018-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多