0
点赞
收藏
分享

微信扫一扫

Keras Node源码分析


Node描述两层之间的连接
当一层连接了一些新的输入,相关node就被添加到​​​layer._inbound_nodes​​​ 当layer的输出用于另外一层时,相关node就被添加到​​layer._outbound_nodes​​ 参数:

  • ​outbound_layer​​ node的尾部层,将输入转化为输出,运行call时创建node
  • ​inbound_layers​​​ node的头部层列表(这里是一个列表,是因为一个node可能对应多个头,但只有一个尾),与​​input_tensors​​等长
  • ​node_indices​​​一组数值,与​​inbound_layers​​​等长,​​node_indices[i]​​​对应​​input_tensors[i]​​的原始node(因为可能会出现当前层是一个共享层,会有不同的输入node)
  • ​tensor_indices​​​也是一组数值。 ​​tensor_indices[i]​​​对应​​input_tensors[i]​​​通过​​inbound layer​​​输出的第几个(因为可能一个​​inbound layer​​有多个不同的输出)

其他参数比较常规,这里不一一解释了
注意:​​node_indices​​​(确定某个输入层的节点) 和 ​​tensor_indices​​​(确定某个输入层节点的输出)是描述​​input_tensors​​的来源的,我们可以通过以下方式验证:

# 假定验证第i个输入层
# 原始节点(输入层的输入节点) = 第i个输入层的的输入节点(因为层的输入节点可能为多个,tensor_indices保存的是输入节点信息,通过i获取对应该层的输入节点)
origin_node = inbound_layers[i]._inbound_nodes[node_indices[i]]
# 第i个输入tensors == 输入层的输入节点的输出tensors可能有多个,tensor_indices保存的是第几个输出tensors
input_tensors[i] == origin_node.output_tensors[tensor_indices[i]]

假定一个node从layer A到layer B,那么该节点被添加到
​​​A._outbound_nodes​​​​B._inbound_nodes​​ 所以Node初始化最后,将node添加到​​inbound_layers​​的每个层的​​_outbound_nodes​​和​​outbound_layer​​的​​_inbound_nodes​​ 这样,每一个layer的​​_outbound_nodes​​和​​_inbound_nodes​​都保存了相关Node的信息
具体代码

class Node(object):
"""A `Node` describes the connectivity between two layers.

Each time a layer is connected to some new input,
a node is added to `layer._inbound_nodes`.
Each time the output of a layer is used by another layer,
a node is added to `layer._outbound_nodes`.

# Arguments
outbound_layer: the layer that takes
`input_tensors` and turns them into `output_tensors`
(the node gets created when the `call`
method of the layer was called).
inbound_layers: a list of layers, the same length as `input_tensors`,
the layers from where `input_tensors` originate.
node_indices: a list of integers, the same length as `inbound_layers`.
`node_indices[i]` is the origin node of `input_tensors[i]`
(necessary since each inbound layer might have several nodes,
e.g. if the layer is being shared with a different data stream).
tensor_indices: a list of integers,
the same length as `inbound_layers`.
`tensor_indices[i]` is the index of `input_tensors[i]` within the
output of the inbound layer
(necessary since each inbound layer might
have multiple tensor outputs, with each one being
independently manipulable).
input_tensors: list of input tensors.
output_tensors: list of output tensors.
input_masks: list of input masks (a mask can be a tensor, or None).
output_masks: list of output masks (a mask can be a tensor, or None).
input_shapes: list of input shape tuples.
output_shapes: list of output shape tuples.
arguments: dictionary of keyword arguments that were passed to the
`call` method of the layer at the call that created the node.

`node_indices` and `tensor_indices` are basically fine-grained coordinates
describing the origin of the `input_tensors`, verifying the following:

origin_node = inbound_layers[i]._inbound_nodes[node_indices[i]]
input_tensors[i] == origin_node.output_tensors[tensor_indices[i]]

A node from layer A to layer B is added to:
A._outbound_nodes
B._inbound_nodes
"""

def __init__(self, outbound_layer,
inbound_layers, node_indices, tensor_indices,
input_tensors, output_tensors,
input_masks, output_masks,
input_shapes, output_shapes,
arguments=None):
# Layer instance (NOT a list).
# this is the layer that takes a list of input tensors
# and turns them into a list of output tensors.
# the current node will be added to
# the inbound_nodes of outbound_layer.
self.outbound_layer = outbound_layer

# The following 3 properties describe where
# the input tensors come from: which layers,
# and for each layer, which node and which
# tensor output of each node.

# List of layer instances.
self.inbound_layers = inbound_layers
# List of integers, 1:1 mapping with inbound_layers.
self.node_indices = node_indices
# List of integers, 1:1 mapping with inbound_layers.
self.tensor_indices = tensor_indices

# Following 2 properties:
# tensor inputs and outputs of outbound_layer.

# List of tensors. 1:1 mapping with inbound_layers.
self.input_tensors = input_tensors
# List of tensors, created by outbound_layer.call().
self.output_tensors = output_tensors

# Following 2 properties: input and output masks.
# List of tensors, 1:1 mapping with input_tensor.
self.input_masks = input_masks
# List of tensors, created by outbound_layer.compute_mask().
self.output_masks = output_masks

# Following 2 properties: input and output shapes.

# List of shape tuples, shapes of input_tensors.
self.input_shapes = input_shapes
# List of shape tuples, shapes of output_tensors.
self.output_shapes = output_shapes

# Optional keyword arguments to layer's `call`.
self.arguments = arguments

# Add nodes to all layers involved.
for layer in inbound_layers:
if layer is not None:
layer._outbound_nodes.append(self)
outbound_layer._inbound_nodes.append(self)

def get_config(self):
inbound_names = []
for layer in self.inbound_layers:
if layer:
inbound_names.append(layer.name)
else:
inbound_names.append(None)
if self.outbound_layer:
outbound_layer = self.outbound_layer.name
else:
outbound_layer = None
return {'outbound_layer': outbound_layer,
'inbound_layers': inbound_names,
'node_indices': self.node_indices,
'tensor_indices': self.tensor_indices}

画张图总结一下上面验证的式子

Keras Node源码分析_List


举报

相关推荐

0 条评论