(self, inputs, outputs, name=None, **kwargs)
| 249 | |
| 250 | @trackable.no_automatic_dependency_tracking |
| 251 | def _init_graph_network(self, inputs, outputs, name=None, **kwargs): |
| 252 | generic_utils.validate_kwargs( |
| 253 | kwargs, {'trainable'}, |
| 254 | 'Functional models may only specify `name` and `trainable` keyword ' |
| 255 | 'arguments during initialization. Got an unexpected argument:') |
| 256 | # Normalize and set self.inputs, self.outputs. |
| 257 | if isinstance(inputs, list) and len(nest.flatten(inputs)) == 1: |
| 258 | inputs = inputs[0] |
| 259 | if isinstance(outputs, list) and len(nest.flatten(outputs)) == 1: |
| 260 | outputs = outputs[0] |
| 261 | self._nested_outputs = outputs |
| 262 | self._nested_inputs = inputs |
| 263 | self.inputs = nest.flatten(inputs) |
| 264 | self.outputs = nest.flatten(outputs) |
| 265 | |
| 266 | if any(not hasattr(tensor, '_keras_history') for tensor in self.outputs): |
| 267 | base_layer_utils.create_keras_history(self._nested_outputs) |
| 268 | |
| 269 | self._base_init(name=name, **kwargs) |
| 270 | self._validate_graph_inputs_and_outputs() |
| 271 | |
| 272 | # A Network does not create weights of its own, thus it is already |
| 273 | # built. |
| 274 | self.built = True |
| 275 | self._compute_output_and_mask_jointly = True |
| 276 | self._is_graph_network = True |
| 277 | # `_expects_training_arg` is True since the `training` argument is always |
| 278 | # present in the signature of the `call` method of a graph network. |
| 279 | self._expects_training_arg = True |
| 280 | self._expects_mask_arg = True |
| 281 | # A graph network does not autocast inputs, as its layers will cast them |
| 282 | # instead. |
| 283 | self._autocast = False |
| 284 | |
| 285 | self._input_layers = [] |
| 286 | self._output_layers = [] |
| 287 | self._input_coordinates = [] |
| 288 | self._output_coordinates = [] |
| 289 | |
| 290 | # This is for performance optimization when calling the Network on new |
| 291 | # inputs. Every time the Network is called on a set on input tensors, |
| 292 | # we compute the output tensors, output masks and output shapes in one pass, |
| 293 | # then cache them here. When any of these outputs is queried later, we |
| 294 | # retrieve it from there instead of recomputing it. |
| 295 | self._output_mask_cache = {} |
| 296 | self._output_tensor_cache = {} |
| 297 | self._output_shape_cache = {} |
| 298 | |
| 299 | # Build self._output_layers: |
| 300 | for x in self.outputs: |
| 301 | layer, node_index, tensor_index = x._keras_history # pylint: disable=protected-access |
| 302 | self._output_layers.append(layer) |
| 303 | self._output_coordinates.append((layer, node_index, tensor_index)) |
| 304 | |
| 305 | # Build self._input_layers: |
| 306 | for x in self.inputs: |
| 307 | layer, node_index, tensor_index = x._keras_history # pylint: disable=protected-access |
| 308 | # It's supposed to be an input layer, so only one node |
no test coverage detected