From 35a4a9a26e7b35e507755a5d4fe3ea7f4f1ca6e0 Mon Sep 17 00:00:00 2001 From: Francois Fleuret Date: Sun, 20 Aug 2017 22:17:44 +0200 Subject: [PATCH] Complete re-write for pytorch 0.2.0 --- agtree2dot.py | 205 ++++++++++++++++++++++++++++---------------------- mlp.pdf | Bin 16619 -> 17239 bytes 2 files changed, 113 insertions(+), 92 deletions(-) diff --git a/agtree2dot.py b/agtree2dot.py index f215f94..2d89af5 100755 --- a/agtree2dot.py +++ b/agtree2dot.py @@ -1,108 +1,129 @@ - -######################################################################### -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the version 3 of the GNU General Public License # -# as published by the Free Software Foundation. # -# # -# This program is distributed in the hope that it will be useful, but # -# WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # -# General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program. If not, see . # -# # -# Written by and Copyright (C) Francois Fleuret # -# Contact for comments & bug reports # -######################################################################### +#!/usr/bin/env python-for-pytorch import torch -import re -import sys +import math, sys, re -import torch.autograd +from torch import nn +from torch.nn import functional as fn -###################################################################### +from torch import Tensor +from torch.autograd import Variable +from torch.nn.parameter import Parameter +from torch.nn import Module -def save_dot_rec(x, node_labels = {}, out = sys.stdout, drawn_node_id = {}): +###################################################################### - if isinstance(x, set): +class Link: + def __init__(self, from_node, from_nb, to_node, to_nb): + self.from_node = from_node + self.from_nb = from_nb + self.to_node = to_node + self.to_nb = to_nb + +class Node: + def __init__(self, id, label): + self.id = id + self.label = label + self.max_in = -1 + self.max_out = -1 + +def slot(node_list, n, k, for_input): + if for_input: + if node_list[n].max_out > 0: + return str(node_list[n].id) + ':input' + str(k) + else: + return str(node_list[n].id) + else: + if node_list[n].max_in > 0: + return str(node_list[n].id) + ':output' + str(k) + else: + return str(node_list[n].id) - for y in x: - save_dot_rec(y, node_labels, out, drawn_node_id) +def slot_string(k, for_input): + result = '' + if for_input: + label = 'input' else: + label = 'output' + + if k > 0: + if not for_input: result = ' |' + result + result += ' { <' + label + '0> 0' + for j in range(1, k+1): + result += " | " + '<' + label + str(j) + '> ' + str(j) + result += " } " + if for_input: result = result + '| ' - if not x in drawn_node_id: - drawn_node_id[x] = len(drawn_node_id) + 1 - - # Draw the node (Variable or Function) if not already - # drawn - - if isinstance(x, torch.autograd.Variable): - name = ((x in node_labels and node_labels[x]) or 'Variable') - # Add the tensor size - name = name + ' [' - for d in range(0, x.data.dim()): - if d > 0: name = name + ', ' - name = name + str(x.data.size(d)) - name = name + ']' - - out.write(' ' + str(drawn_node_id[x]) + - ' [shape=record,penwidth=1,style=rounded,label="' + name + '"]\n') - - if hasattr(x, 'creator') and x.creator: - y = x.creator - save_dot_rec(y, node_labels, out, drawn_node_id) - # Edge to the creator - out.write(' ' + str(drawn_node_id[y]) + ' -> ' + str(drawn_node_id[x]) + '\n') - - elif isinstance(x, torch.autograd.Function): - name = ((x in node_labels and (node_labels[x] + ': ')) or '') + \ - re.search('<.*\.([a-zA-Z0-9_]*)\'>', str(type(x))).group(1) - - prefix = '' - suffix = '' - - if hasattr(x, 'num_inputs') and x.num_inputs > 1: - prefix = '{ ' - for i in range(0, x.num_inputs): - if i > 0: prefix = prefix + ' | ' - prefix = prefix + ' ' + str(i) - prefix = prefix + ' } | ' - - if hasattr(x, 'num_outputs') and x.num_outputs > 1: - suffix = ' | { ' - for i in range(0, x.num_outputs): - if i > 0: suffix = suffix + ' | ' - suffix = suffix + ' ' + str(i) - suffix = suffix + ' }' - - out.write(' ' + str(drawn_node_id[x]) + \ - ' [shape=record,label="{ ' + prefix + name + suffix + ' }"]\n') - - else: - - print('Cannot handle ' + str(type(x)) + ' (only Variables and Functions).') - exit(1) - - if hasattr(x, 'num_inputs'): - for i in range(0, x.num_inputs): - y = x.previous_functions[i][0] - save_dot_rec(y, node_labels, out, drawn_node_id) - from_str = str(drawn_node_id[y]) - if hasattr(y, 'num_outputs') and y.num_outputs > 1: - from_str = from_str + ':output' + str(x.previous_functions[i][1]) - to_str = str(drawn_node_id[x]) - if x.num_inputs > 1: - to_str = to_str + ':input' + str(i) - out.write(' ' + from_str + ' -> ' + to_str + '\n') + return result ###################################################################### -def save_dot(x, node_labels = {}, out = sys.stdout): - out.write('digraph {\n') - save_dot_rec(x, node_labels, out, {}) +def add_link(node_list, link_list, u, nu, v, nv): + link = Link(u, nu, v, nv) + link_list.append(link) + node_list[u].max_in = max(node_list[u].max_in, nu) + node_list[v].max_out = max(node_list[u].max_out, nv) + +###################################################################### + +def build_ag_graph_lists(u, node_labels, out, node_list, link_list): + + if not u in node_list: + node = Node(len(node_list) + 1, + (u in node_labels and node_labels[u]) or \ + re.search('', str(type(u))).group(2)) + node_list[u] = node + + if isinstance(u, torch.autograd.Variable): + build_ag_graph_lists(u.grad_fn, node_labels, out, node_list, link_list) + add_link(node_list, link_list, u, 0, u.grad_fn, 0) + else: + if hasattr(u, 'next_functions'): + i = 0 + for v, j in u.next_functions: + build_ag_graph_lists(v, node_labels, out, node_list, link_list) + add_link(node_list, link_list, u, i, v, j) + i += 1 + +###################################################################### + +def print_dot(node_list, link_list, out): + out.write('digraph{\n') + + for n in node_list: + node = node_list[n] + + out.write( + ' ' + \ + str(node.id) + ' [shape=record,label="{ ' + \ + slot_string(node.max_out, for_input = True) + \ + node.label + \ + slot_string(node.max_in, for_input = False) + \ + ' }"]\n' + ) + + for n in link_list: + out.write(' ' + \ + slot(node_list, n.from_node, n.from_nb, for_input = False) + \ + ' -> ' + \ + slot(node_list, n.to_node, n.to_nb, for_input = True) + \ + '\n') + out.write('}\n') ###################################################################### + +def save_dot(x, node_labels = {}, out = sys.stdout): + node_list = {} + link_list = [] + build_ag_graph_lists(x, node_labels, out, node_list, link_list) + print_dot(node_list, link_list, out) + +###################################################################### + +# x = Variable(torch.rand(5)) +# y = torch.topk(x, 3) +# l = torch.sqrt(torch.norm(y[0]) + torch.norm(5.0 * y[1].float())) + +# save_dot(l, { l: 'variable l' }, open('/tmp/test.dot', 'w')) diff --git a/mlp.pdf b/mlp.pdf index 0f735a5775033d38289d522e73f7c02f3a595f62..f233b200ee7a28c445dfc830c06b049e6c26c33b 100644 GIT binary patch delta 15840 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 MFy!RoiV`sY2atv*Qvd(} -- 2.20.1