<p dir="auto"><strong>System information</strong></p>
<ul dir="auto">
<li>TensorFlow installed from: <code class="notranslate">pip</code></li>
<li>TensorFlow version: <code class="notranslate">tf-nightly-2.0-preview-2.0.0.dev20190513</code></li>
<li>Python version: 3.6.7</li>
</ul>
<p dir="auto"><strong>Describe the current behavior</strong></p>
<p dir="auto">Attempting <code class="notranslate">tf.keras.models.load_model</code> on a <code class="notranslate">Sequential</code> model throws</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="ValueError: You are trying to load a weight file containing 2 layers into a model with 0 layers."><pre class="notranslate">ValueError: You are trying to load a weight file containing 2 layers into a model with 0 layers.</pre></div>
<p dir="auto">Might be caused by a <code class="notranslate">layers</code>/<code class="notranslate">_layers</code> mismatch as mentioned <a href="https://github.com/keras-team/keras/issues/10417#issuecomment-418511814" data-hovercard-type="issue" data-hovercard-url="/keras-team/keras/issues/10417/hovercard">here</a>. Not sure if this is the problem but <a href="https://github.com/tensorflow/tensorflow/blob/2c2d508aa2947ede05cfa195139b176d6cdc9056/tensorflow/python/keras/models.py#L218"><code class="notranslate">_clone_sequential_model</code></a> uses <code class="notranslate">model._layers</code> whereas <a href="https://github.com/tensorflow/tensorflow/blob/30f682e776fbcff8d2da3c3cc0e8d12e1b3dde12/tensorflow/python/keras/saving/hdf5_format.py#L104"><code class="notranslate">save_model_to_hdf5</code></a> accesses <code class="notranslate">model.layers</code>.</p>
<p dir="auto"><strong>Minimal example</strong></p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import tensorflow as tf

model = tf.keras.Sequential(
    [tf.keras.Input(3), tf.keras.layers.Dense(3), tf.keras.layers.Dense(1)]
)
model.compile(loss=&quot;mse&quot;, optimizer=&quot;adam&quot;)
model.fit(tf.constant([[1, 2, 3], [4, 5, 6]]), tf.constant([1, 2]))
model.save(&quot;model.h5&quot;)
restored_model = tf.keras.models.load_model(&quot;model.h5&quot;)"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">tensorflow</span> <span class="pl-k">as</span> <span class="pl-s1">tf</span>

<span class="pl-s1">model</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-v">Sequential</span>(
    [<span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-v">Input</span>(<span class="pl-c1">3</span>), <span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">layers</span>.<span class="pl-v">Dense</span>(<span class="pl-c1">3</span>), <span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">layers</span>.<span class="pl-v">Dense</span>(<span class="pl-c1">1</span>)]
)
<span class="pl-s1">model</span>.<span class="pl-en">compile</span>(<span class="pl-s1">loss</span><span class="pl-c1">=</span><span class="pl-s">"mse"</span>, <span class="pl-s1">optimizer</span><span class="pl-c1">=</span><span class="pl-s">"adam"</span>)
<span class="pl-s1">model</span>.<span class="pl-en">fit</span>(<span class="pl-s1">tf</span>.<span class="pl-en">constant</span>([[<span class="pl-c1">1</span>, <span class="pl-c1">2</span>, <span class="pl-c1">3</span>], [<span class="pl-c1">4</span>, <span class="pl-c1">5</span>, <span class="pl-c1">6</span>]]), <span class="pl-s1">tf</span>.<span class="pl-en">constant</span>([<span class="pl-c1">1</span>, <span class="pl-c1">2</span>]))
<span class="pl-s1">model</span>.<span class="pl-en">save</span>(<span class="pl-s">"model.h5"</span>)
<span class="pl-s1">restored_model</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">models</span>.<span class="pl-en">load_model</span>(<span class="pl-s">"model.h5"</span>)</pre></div>
<p dir="auto"><strong>System information</strong></p>
<ul dir="auto">
<li>Have I written custom code (as opposed to using a stock example script provided in TensorFlow): <strong>YES</strong></li>
<li>OS Platform and Distribution (e.g., Linux Ubuntu 16.04): <strong>Linux Debian Stable</strong></li>
<li>Mobile device (e.g. iPhone 8, Pixel 2, Samsung Galaxy) if the issue happens on mobile device: <strong>N/A</strong></li>
<li>TensorFlow installed from (source or binary): <strong>binary</strong></li>
<li>TensorFlow version (use command below): <strong>CPU, both TF-2.0.0a0 and tf-nightly-2.0-preview-2.0.0.dev20190315</strong></li>
<li>Python version: <strong>3.5.3</strong></li>
<li>Bazel version (if compiling from source): <strong>N/A</strong></li>
<li>GCC/Compiler version (if compiling from source): <strong>N/A</strong></li>
<li>CUDA/cuDNN version: <strong>N/A</strong></li>
<li>GPU model and memory: <strong>N/A</strong></li>
</ul>
<p dir="auto"><strong>Describe the current behavior</strong><br>
When a <code class="notranslate">Sequential</code> Keras model contains <code class="notranslate">InputLayer</code> and it is saved, it cannot be loaded and fails with a message</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="ValueError: You are trying to load a weight file containing 1 layers into a model with 0 layers."><pre class="notranslate"><code class="notranslate">ValueError: You are trying to load a weight file containing 1 layers into a model with 0 layers.
</code></pre></div>
<p dir="auto"><strong>Describe the expected behavior</strong><br>
The model can be loaded correctly.</p>
<p dir="auto"><strong>Code to reproduce the issue</strong></p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy as np
import tensorflow as tf

inputs = np.arange(10)
outputs = 2 * inputs

model = tf.keras.Sequential([
    tf.keras.layers.InputLayer(input_shape=[1]),
    tf.keras.layers.Dense(1),
])
model.compile(
    optimizer=tf.keras.optimizers.Adam(),
    loss=tf.keras.losses.MeanSquaredError(),
    metrics=[tf.keras.metrics.MeanSquaredError()]
)
model.fit(inputs, outputs)
model.save(&quot;model.h5&quot;)

loaded_model = tf.keras.models.load_model(&quot;model.h5&quot;)"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">import</span> <span class="pl-s1">tensorflow</span> <span class="pl-k">as</span> <span class="pl-s1">tf</span>

<span class="pl-s1">inputs</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">arange</span>(<span class="pl-c1">10</span>)
<span class="pl-s1">outputs</span> <span class="pl-c1">=</span> <span class="pl-c1">2</span> <span class="pl-c1">*</span> <span class="pl-s1">inputs</span>

<span class="pl-s1">model</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-v">Sequential</span>([
    <span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">layers</span>.<span class="pl-v">InputLayer</span>(<span class="pl-s1">input_shape</span><span class="pl-c1">=</span>[<span class="pl-c1">1</span>]),
    <span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">layers</span>.<span class="pl-v">Dense</span>(<span class="pl-c1">1</span>),
])
<span class="pl-s1">model</span>.<span class="pl-en">compile</span>(
    <span class="pl-s1">optimizer</span><span class="pl-c1">=</span><span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">optimizers</span>.<span class="pl-v">Adam</span>(),
    <span class="pl-s1">loss</span><span class="pl-c1">=</span><span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">losses</span>.<span class="pl-v">MeanSquaredError</span>(),
    <span class="pl-s1">metrics</span><span class="pl-c1">=</span>[<span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">metrics</span>.<span class="pl-v">MeanSquaredError</span>()]
)
<span class="pl-s1">model</span>.<span class="pl-en">fit</span>(<span class="pl-s1">inputs</span>, <span class="pl-s1">outputs</span>)
<span class="pl-s1">model</span>.<span class="pl-en">save</span>(<span class="pl-s">"model.h5"</span>)

<span class="pl-s1">loaded_model</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">models</span>.<span class="pl-en">load_model</span>(<span class="pl-s">"model.h5"</span>)</pre></div>
<p dir="auto"><strong>Other info / logs</strong><br>
The problem is in the fact that <code class="notranslate">Sequential.layers</code> does not return the <code class="notranslate">InputLayer</code>. To quote comments from the method:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="  def layers(self):
    # Historically, `sequential.layers` only returns layers that were added
    # via `add`, and omits the auto-generated `InputLayer` that comes at the
    # bottom of the stack.
    # `Trackable` manages the `_layers` attributes and does filtering
    # over it."><pre class="notranslate">  <span class="pl-k">def</span> <span class="pl-en">layers</span>(<span class="pl-s1">self</span>):
    <span class="pl-c"># Historically, `sequential.layers` only returns layers that were added</span>
    <span class="pl-c"># via `add`, and omits the auto-generated `InputLayer` that comes at the</span>
    <span class="pl-c"># bottom of the stack.</span>
    <span class="pl-c"># `Trackable` manages the `_layers` attributes and does filtering</span>
    <span class="pl-c"># over it.</span></pre></div>
<p dir="auto">The problem is that if <code class="notranslate">InputLayer</code> was added manually with a specified <code class="notranslate">input_shape</code>, then it is an error not to serialize it -- because then the following layers do not know what the input shape is.</p>
<p dir="auto">Workarounds:</p>
<ul dir="auto">
<li>if instead of <code class="notranslate">InputLayer</code> you add <code class="notranslate">input_shape</code> to the <code class="notranslate">Dense</code> layer, it works. However, input <code class="notranslate">dtype</code> cannot be specified in this way and when you pass <code class="notranslate">tf.int32</code> on input, using an <code class="notranslate">InputLayer</code> is required</li>
<li>in Functional API the <code class="notranslate">tf.keras.layers.Input</code> <em>is</em> serialized in the model (and, funnily, as a <code class="notranslate">InputLayer</code>).</li>
</ul>
<p dir="auto">Solutions:</p>
<ul dir="auto">
<li>when serializing a <code class="notranslate">Sequential</code> model, all layers need to be serialized (and no filtering of <code class="notranslate">InputLayer</code> performed).</li>
</ul>