Clone a `Sequential` model instance. Model cloning is similar to calling a model on new inputs, except that it creates new layers (and thus new weights) instead of sharing the weights of the existing layers. Arguments: model: Instance of `Sequential`. input_tensors: optional li
(model, input_tensors=None, layer_fn=_clone_layer)
| 259 | |
| 260 | |
| 261 | def _clone_sequential_model(model, input_tensors=None, layer_fn=_clone_layer): |
| 262 | """Clone a `Sequential` model instance. |
| 263 | |
| 264 | Model cloning is similar to calling a model on new inputs, |
| 265 | except that it creates new layers (and thus new weights) instead |
| 266 | of sharing the weights of the existing layers. |
| 267 | |
| 268 | Arguments: |
| 269 | model: Instance of `Sequential`. |
| 270 | input_tensors: optional list of input tensors |
| 271 | to build the model upon. If not provided, |
| 272 | placeholders will be created. |
| 273 | layer_fn: callable to be applied on non-input layers in the model. By |
| 274 | default it clones the layer. Another example is to preserve the layer |
| 275 | to share the weights. This is required when we create a per-replica |
| 276 | copy of the model with distribution strategy; we want the weights to |
| 277 | be shared but still feed inputs separately so we create new input |
| 278 | layers. |
| 279 | |
| 280 | Returns: |
| 281 | An instance of `Sequential` reproducing the behavior |
| 282 | of the original model, on top of new inputs tensors, |
| 283 | using newly instantiated weights. |
| 284 | |
| 285 | Raises: |
| 286 | ValueError: in case of invalid `model` argument value or `layer_fn` |
| 287 | argument value. |
| 288 | """ |
| 289 | if not isinstance(model, Sequential): |
| 290 | raise ValueError('Expected `model` argument ' |
| 291 | 'to be a `Sequential` model instance, ' |
| 292 | 'but got:', model) |
| 293 | |
| 294 | if not callable(layer_fn): |
| 295 | raise ValueError('Expected `layer_fn` argument to be a callable.') |
| 296 | |
| 297 | layers = [] # Layers needed to compute the model's outputs. |
| 298 | layer_map = {} |
| 299 | # Use model._layers to ensure that all layers are cloned. The model's layers |
| 300 | # property will exclude the initial InputLayer (if it exists) in the model, |
| 301 | # resulting in a different Sequential model structure. |
| 302 | for layer in model._layers: |
| 303 | if isinstance(layer, InputLayer) and input_tensors is not None: |
| 304 | # If input tensors are provided, the original model's InputLayer is |
| 305 | # overwritten with a different InputLayer. |
| 306 | continue |
| 307 | cloned_layer = ( |
| 308 | _clone_layer(layer) |
| 309 | if isinstance(layer, InputLayer) else layer_fn(layer)) |
| 310 | layers.append(cloned_layer) |
| 311 | layer_map[layer] = cloned_layer |
| 312 | layers, ancillary_layers = _remove_ancillary_layers(model, layer_map, layers) |
| 313 | |
| 314 | if input_tensors is None: |
| 315 | cloned_model = Sequential(layers=layers, name=model.name) |
| 316 | elif len(generic_utils.to_list(input_tensors)) != 1: |
| 317 | raise ValueError('To clone a `Sequential` model, we expect ' |
| 318 | ' at most one tensor ' |
no test coverage detected