1# Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15# pylint: disable=protected-access 16"""Home of the `Sequential` model. 17""" 18from __future__ import absolute_import 19from __future__ import division 20from __future__ import print_function 21 22import copy 23 24from tensorflow.python.keras import layers as layer_module 25from tensorflow.python.keras.engine import base_layer 26from tensorflow.python.keras.engine import input_layer 27from tensorflow.python.keras.engine import training 28from tensorflow.python.keras.engine import training_utils 29from tensorflow.python.keras.utils import layer_utils 30from tensorflow.python.platform import tf_logging as logging 31from tensorflow.python.training.tracking import base as trackable 32from tensorflow.python.util import nest 33from tensorflow.python.util import tf_inspect 34from tensorflow.python.util.tf_export import keras_export 35 36 37@keras_export('keras.models.Sequential', 'keras.Sequential') 38class Sequential(training.Model): 39 """Linear stack of layers. 40 41 Arguments: 42 layers: list of layers to add to the model. 43 44 Example: 45 46 ```python 47 # Optionally, the first layer can receive an `input_shape` argument: 48 model = Sequential() 49 model.add(Dense(32, input_shape=(500,))) 50 # Afterwards, we do automatic shape inference: 51 model.add(Dense(32)) 52 53 # This is identical to the following: 54 model = Sequential() 55 model.add(Dense(32, input_dim=500)) 56 57 # And to the following: 58 model = Sequential() 59 model.add(Dense(32, batch_input_shape=(None, 500))) 60 61 # Note that you can also omit the `input_shape` argument: 62 # In that case the model gets built the first time you call `fit` (or other 63 # training and evaluation methods). 64 model = Sequential() 65 model.add(Dense(32)) 66 model.add(Dense(32)) 67 model.compile(optimizer=optimizer, loss=loss) 68 # This builds the model for the first time: 69 model.fit(x, y, batch_size=32, epochs=10) 70 71 # Note that when using this delayed-build pattern (no input shape specified), 72 # the model doesn't have any weights until the first call 73 # to a training/evaluation method (since it isn't yet built): 74 model = Sequential() 75 model.add(Dense(32)) 76 model.add(Dense(32)) 77 model.weights # returns [] 78 79 # Whereas if you specify the input shape, the model gets built continuously 80 # as you are adding layers: 81 model = Sequential() 82 model.add(Dense(32, input_shape=(500,))) 83 model.add(Dense(32)) 84 model.weights # returns list of length 4 85 86 # When using the delayed-build pattern (no input shape specified), you can 87 # choose to manually build your model by calling `build(batch_input_shape)`: 88 model = Sequential() 89 model.add(Dense(32)) 90 model.add(Dense(32)) 91 model.build((None, 500)) 92 model.weights # returns list of length 4 93 ``` 94 """ 95 96 @trackable.no_automatic_dependency_tracking 97 def __init__(self, layers=None, name=None): 98 super(Sequential, self).__init__(name=name) 99 self.supports_masking = True 100 self._build_input_shape = None 101 self._compute_output_and_mask_jointly = True 102 103 self._layer_call_argspecs = {} 104 105 # Add to the model any layers passed to the constructor. 106 if layers: 107 for layer in layers: 108 self.add(layer) 109 110 @property 111 def layers(self): 112 # Historically, `sequential.layers` only returns layers that were added 113 # via `add`, and omits the auto-generated `InputLayer` that comes at the 114 # bottom of the stack. 115 # `Trackable` manages the `_layers` attributes and does filtering 116 # over it. 117 layers = super(Sequential, self).layers 118 if layers and isinstance(layers[0], input_layer.InputLayer): 119 return layers[1:] 120 return layers[:] 121 122 @property 123 def dynamic(self): 124 return any(layer.dynamic for layer in self.layers) 125 126 @trackable.no_automatic_dependency_tracking 127 def add(self, layer): 128 """Adds a layer instance on top of the layer stack. 129 130 Arguments: 131 layer: layer instance. 132 133 Raises: 134 TypeError: If `layer` is not a layer instance. 135 ValueError: In case the `layer` argument does not 136 know its input shape. 137 ValueError: In case the `layer` argument has 138 multiple output tensors, or is already connected 139 somewhere else (forbidden in `Sequential` models). 140 """ 141 # If we are passed a Keras tensor created by keras.Input(), we can extract 142 # the input layer from its keras history and use that without any loss of 143 # generality. 144 if hasattr(layer, '_keras_history'): 145 origin_layer = layer._keras_history[0] 146 if isinstance(origin_layer, input_layer.InputLayer): 147 layer = origin_layer 148 149 if not isinstance(layer, base_layer.Layer): 150 raise TypeError('The added layer must be ' 151 'an instance of class Layer. ' 152 'Found: ' + str(layer)) 153 self.built = False 154 set_inputs = False 155 if not self._layers: 156 if isinstance(layer, input_layer.InputLayer): 157 # Corner case where the user passes an InputLayer layer via `add`. 158 assert len(nest.flatten(layer._inbound_nodes[-1].output_tensors)) == 1 159 set_inputs = True 160 else: 161 batch_shape, dtype = training_utils.get_input_shape_and_dtype(layer) 162 if batch_shape: 163 # Instantiate an input layer. 164 x = input_layer.Input( 165 batch_shape=batch_shape, dtype=dtype, name=layer.name + '_input') 166 # This will build the current layer 167 # and create the node connecting the current layer 168 # to the input layer we just created. 169 layer(x) 170 set_inputs = True 171 172 if set_inputs: 173 # If an input layer (placeholder) is available. 174 if len(nest.flatten(layer._inbound_nodes[-1].output_tensors)) != 1: 175 raise ValueError('All layers in a Sequential model ' 176 'should have a single output tensor. ' 177 'For multi-output layers, ' 178 'use the functional API.') 179 self.outputs = [ 180 nest.flatten(layer._inbound_nodes[-1].output_tensors)[0] 181 ] 182 self.inputs = layer_utils.get_source_inputs(self.outputs[0]) 183 184 elif self.outputs: 185 # If the model is being built continuously on top of an input layer: 186 # refresh its output. 187 output_tensor = layer(self.outputs[0]) 188 if isinstance(output_tensor, list): 189 raise TypeError('All layers in a Sequential model ' 190 'should have a single output tensor. ' 191 'For multi-output layers, ' 192 'use the functional API.') 193 self.outputs = [output_tensor] 194 if set_inputs or self._is_graph_network: 195 self._init_graph_network(self.inputs, self.outputs, name=self.name) 196 self.built = True 197 else: 198 self._layers.append(layer) 199 if self._layers: 200 self._track_layers(self._layers) 201 202 self._layer_call_argspecs[layer] = tf_inspect.getfullargspec(layer.call) 203 204 @trackable.no_automatic_dependency_tracking 205 def pop(self): 206 """Removes the last layer in the model. 207 208 Raises: 209 TypeError: if there are no layers in the model. 210 """ 211 if not self.layers: 212 raise TypeError('There are no layers in the model.') 213 214 layer = self._layers.pop() 215 self._layer_call_argspecs.pop(layer) 216 if not self.layers: 217 self.outputs = None 218 self.inputs = None 219 self.built = False 220 elif self._is_graph_network: 221 self.layers[-1]._outbound_nodes = [] 222 self.outputs = [self.layers[-1].output] 223 self._init_graph_network(self.inputs, self.outputs, name=self.name) 224 self.built = True 225 226 @base_layer.default 227 def build(self, input_shape=None): 228 if self._is_graph_network: 229 self._init_graph_network(self.inputs, self.outputs, name=self.name) 230 else: 231 if input_shape is None: 232 raise ValueError('You must provide an `input_shape` argument.') 233 input_shape = tuple(input_shape) 234 self._build_input_shape = input_shape 235 super(Sequential, self).build(input_shape) 236 self.built = True 237 238 def call(self, inputs, training=None, mask=None): # pylint: disable=redefined-outer-name 239 if self._is_graph_network: 240 if not self.built: 241 self._init_graph_network(self.inputs, self.outputs, name=self.name) 242 return super(Sequential, self).call(inputs, training=training, mask=mask) 243 244 outputs = inputs # handle the corner case where self.layers is empty 245 for layer in self.layers: 246 # During each iteration, `inputs` are the inputs to `layer`, and `outputs` 247 # are the outputs of `layer` applied to `inputs`. At the end of each 248 # iteration `inputs` is set to `outputs` to prepare for the next layer. 249 kwargs = {} 250 argspec = self._layer_call_argspecs[layer].args 251 if 'mask' in argspec: 252 kwargs['mask'] = mask 253 if 'training' in argspec: 254 kwargs['training'] = training 255 256 outputs = layer(inputs, **kwargs) 257 258 # `outputs` will be the inputs to the next layer. 259 inputs = outputs 260 mask = outputs._keras_mask 261 262 return outputs 263 264 def compute_output_shape(self, input_shape): 265 shape = input_shape 266 for layer in self.layers: 267 shape = layer.compute_output_shape(shape) 268 return shape 269 270 def compute_mask(self, inputs, mask): 271 # TODO(omalleyt): b/123540974 This function is not really safe to call 272 # by itself because it will duplicate any updates and losses in graph 273 # mode by `call`ing the Layers again. 274 outputs = self.call(inputs, mask=mask) 275 return outputs._keras_mask 276 277 def predict_proba(self, x, batch_size=32, verbose=0): 278 """Generates class probability predictions for the input samples. 279 280 The input samples are processed batch by batch. 281 282 Arguments: 283 x: input data, as a Numpy array or list of Numpy arrays 284 (if the model has multiple inputs). 285 batch_size: integer. 286 verbose: verbosity mode, 0 or 1. 287 288 Returns: 289 A Numpy array of probability predictions. 290 """ 291 preds = self.predict(x, batch_size, verbose) 292 if preds.min() < 0. or preds.max() > 1.: 293 logging.warning('Network returning invalid probability values. ' 294 'The last layer might not normalize predictions ' 295 'into probabilities ' 296 '(like softmax or sigmoid would).') 297 return preds 298 299 def predict_classes(self, x, batch_size=32, verbose=0): 300 """Generate class predictions for the input samples. 301 302 The input samples are processed batch by batch. 303 304 Arguments: 305 x: input data, as a Numpy array or list of Numpy arrays 306 (if the model has multiple inputs). 307 batch_size: integer. 308 verbose: verbosity mode, 0 or 1. 309 310 Returns: 311 A numpy array of class predictions. 312 """ 313 proba = self.predict(x, batch_size=batch_size, verbose=verbose) 314 if proba.shape[-1] > 1: 315 return proba.argmax(axis=-1) 316 else: 317 return (proba > 0.5).astype('int32') 318 319 def save(self, filepath, overwrite=True, include_optimizer=True): 320 from tensorflow.python.keras.models import save_model # pylint: disable=g-import-not-at-top 321 save_model(self, filepath, overwrite, include_optimizer) 322 323 def get_config(self): 324 layer_configs = [] 325 for layer in self.layers: 326 layer_configs.append({ 327 'class_name': layer.__class__.__name__, 328 'config': layer.get_config() 329 }) 330 config = { 331 'name': self.name, 332 'layers': copy.deepcopy(layer_configs) 333 } 334 if self._build_input_shape: 335 config['build_input_shape'] = self._build_input_shape 336 return config 337 338 @classmethod 339 def from_config(cls, config, custom_objects=None): 340 if 'name' in config: 341 name = config['name'] 342 build_input_shape = config.get('build_input_shape') 343 layer_configs = config['layers'] 344 else: 345 name = None 346 build_input_shape = None 347 layer_configs = config 348 model = cls(name=name) 349 for layer_config in layer_configs: 350 layer = layer_module.deserialize(layer_config, 351 custom_objects=custom_objects) 352 model.add(layer) 353 if not model.inputs and build_input_shape: 354 model.build(build_input_shape) 355 if not model._is_graph_network: 356 # Still needs to be built when passed input data. 357 model.built = False 358 return model 359 360 @property 361 def input_spec(self): 362 if self.layers and hasattr(self.layers[0], 'input_spec'): 363 return self.layers[0].input_spec 364 return None 365