Inserts Layers into the Network after Network creation. This is only valid for Keras Graph Networks. Layers added via this function will be included in the `call` computation and `get_config` of this Network. They will not be added to the Network's outputs. Arguments: layer
(self, layers, relevant_nodes=None)
| 1517 | '(thus holding past layer metadata). Found: ' + str(x)) |
| 1518 | |
| 1519 | def _insert_layers(self, layers, relevant_nodes=None): |
| 1520 | """Inserts Layers into the Network after Network creation. |
| 1521 | |
| 1522 | This is only valid for Keras Graph Networks. Layers added via this function |
| 1523 | will be included in the `call` computation and `get_config` of this Network. |
| 1524 | They will not be added to the Network's outputs. |
| 1525 | |
| 1526 | |
| 1527 | Arguments: |
| 1528 | layers: Arbitrary nested structure of Layers. Layers must be reachable |
| 1529 | from one or more of the `keras.Input` Tensors that correspond to this |
| 1530 | Network's inputs. |
| 1531 | relevant_nodes: Nodes from the Layers that should be considered part of |
| 1532 | this Network. If `None`, all Nodes will be considered part of this |
| 1533 | Network. |
| 1534 | |
| 1535 | Raises: |
| 1536 | ValueError: If the layers depend on `Input`s not found in this Model. |
| 1537 | """ |
| 1538 | layers = nest.flatten(layers) |
| 1539 | tf_utils.assert_no_legacy_layers(layers) |
| 1540 | node_to_depth = {} |
| 1541 | for depth, nodes in self._nodes_by_depth.items(): |
| 1542 | node_to_depth.update({node: depth for node in nodes}) |
| 1543 | # The nodes of these Layers that are relevant to this Network. If not |
| 1544 | # provided, assume all Nodes are relevant |
| 1545 | if not relevant_nodes: |
| 1546 | relevant_nodes = nest.flatten([layer._inbound_nodes for layer in layers]) |
| 1547 | network_nodes = set(relevant_nodes + list(node_to_depth.keys())) |
| 1548 | |
| 1549 | def _get_min_depth(node): |
| 1550 | """Gets the minimum depth at which node can be computed.""" |
| 1551 | min_depth = 0 |
| 1552 | for layer, node_id, _, _ in node.iterate_inbound(include_arguments=True): |
| 1553 | inbound_node = layer._inbound_nodes[node_id] |
| 1554 | if inbound_node in node_to_depth: |
| 1555 | min_depth = min(min_depth, node_to_depth[inbound_node]) |
| 1556 | elif inbound_node not in network_nodes: |
| 1557 | continue |
| 1558 | else: |
| 1559 | # Previous relevant nodes haven't been processed yet. |
| 1560 | return None |
| 1561 | # New node is one shallower than its shallowest input. |
| 1562 | return min_depth - 1 |
| 1563 | |
| 1564 | # Insert nodes into `_nodes_by_depth` and other node attrs. |
| 1565 | unprocessed_nodes = copy.copy(relevant_nodes) |
| 1566 | i = 0 |
| 1567 | while unprocessed_nodes: |
| 1568 | i += 1 |
| 1569 | # Do a sanity check. This can occur if `Input`s from outside this Model |
| 1570 | # are being relied on. |
| 1571 | if i > 10000: |
| 1572 | raise ValueError('Layers could not be added due to missing ' |
| 1573 | 'dependencies.') |
| 1574 | |
| 1575 | node = unprocessed_nodes.pop(0) |
| 1576 | depth = _get_min_depth(node) |