I’m trying to replace some nodes in a graph using model.clone(). I get these nodes I want to replace by calling the below function: times_nodes = find_all_with_name(model, name, -1) The nodes in question are not in depth 0 in the graph. I noticed that when I then call clone as follows: model = model.clone('clone', substitutions=subst) none of the nodes are actually replaced. Is there a way to do this or is this intended behavior?
Currently, nodes that are block functions cannot have their guts replaced by clone. We will probably add this mode of operation in clone. For now you can try to flatten the graph. The following code is probably good enough to flatten most networks. I haven't thoroughly tested it though:
def break_a_block(root):
blocks = C.logging.graph.depth_first_search(root, lambda node: isinstance(node, C.cntk_py.Function) and node.is_block, depth=-1)
if len(blocks) == 0:
return False, root
block = blocks[0]
composite = C.as_composite(block.block_root)
output_dict = dict(zip(block.outputs, composite.outputs))
mapping = dict(block.block_arguments_mapping)
items = list(mapping.items())
owners = set(C.as_composite(arg.owner) for _, arg in items if arg.is_output)
for owner in owners:
clone = owner.clone('share', output_dict)
out = dict(zip(owner.outputs,clone.outputs))
for p,a in items:
if mapping[p] in out:
mapping[p] = out[mapping[p]]
composite.replace_placeholders(mapping)
return True, root.clone('share',output_dict)
def flatten(root):
changed, root = break_a_block(root)
while changed:
changed, root = break_a_block(root)
return root