ann-visualizer
ann-visualizer copied to clipboard
Issue with displaying: tensorflow.keras.layers
In Python 3.7.x we need to install tensorflow.keras.layers (Tensorflow compatibility is broken)
import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D, AveragePooling2D
# ==============================================================================
def CNN3(input_shape, output_shape):
model = Sequential()
# Layer #1: Convolutional Layer
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
# Layer #2: Dense Layer
model.add(Dense(128, activation='relu'))
# Layer #3: Dense Layer
model.add(Dense(output_shape, activation='softmax'))
return model
This library does not currently support tensorflow.keras.layers
Could you kindly update this awesome vis library to support this?
Related StackOverflow post, describing the issue with using keras.xxx, and suggesting we use tensorflow.keras.xxx to work around.
I have modified the ../ann_visualizer/visualize.py file. It now works fine for me.
"""
Copyright (C) 2018 by Tudor Gheorghiu
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and associated
documentation files (the "Software"),
to deal in the Software without restriction,
including without l> imitation the rights to
use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
"""
def ann_viz(model, view=True, filename="network.gv", title="My Neural Network"):
"""Vizualizez a Sequential model.
# Arguments
model: A Keras model instance.
view: whether to display the model after generation.
filename: where to save the vizualization. (a .gv file)
title: A title for the graph
"""
from graphviz import Digraph;
#import keras;
import tensorflow
from tensorflow import keras
#from keras.models import Sequential;
from tensorflow.keras.models import Sequential
#from keras.layers import Dense, Conv2D, MaxPooling2D, Dropout, Flatten;
from tensorflow.keras.layers import Dense, Conv2D, MaxPooling2D, Dropout, Flatten
import json;
input_layer = 0;
hidden_layers_nr = 0;
layer_types = [];
hidden_layers = [];
output_layer = 0;
for layer in model.layers:
if(layer == model.layers[0]):
input_layer = int(str(layer.input_shape).split(",")[1][1:-1]);
hidden_layers_nr += 1;
#if (type(layer) == (keras.layers.core.Dense)):
if (type(layer) == (keras.layers.Dense)):
hidden_layers.append(int(str(layer.output_shape).split(",")[1][1:-1]));
layer_types.append("Dense");
else:
hidden_layers.append(1);
#if (type(layer) == keras.layers.convolutional.Conv2D):
if (type(layer) == keras.layers.Conv2D):
layer_types.append("Conv2D");
#elif (type(layer) == keras.layers.pooling.MaxPooling2D):
elif (type(layer) == keras.layers.MaxPooling2D):
layer_types.append("MaxPooling2D");
#elif (type(layer) == keras.layers.core.Dropout):
elif (type(layer) == keras.layers.Dropout):
layer_types.append("Dropout");
#elif (type(layer) == keras.layers.core.Flatten):
elif (type(layer) == keras.layers.Flatten):
layer_types.append("Flatten");
#elif (type(layer) == keras.layers.core.Activation):
elif (type(layer) == keras.layers.Activation):
layer_types.append("Activation");
else:
if(layer == model.layers[-1]):
output_layer = int(str(layer.output_shape).split(",")[1][1:-1]);
else:
hidden_layers_nr += 1;
#if (type(layer) == keras.layers.core.Dense):
if (type(layer) == keras.layers.Dense):
hidden_layers.append(int(str(layer.output_shape).split(",")[1][1:-1]));
layer_types.append("Dense");
else:
hidden_layers.append(1);
#if (type(layer) == keras.layers.convolutional.Conv2D):
if (type(layer) == keras.layers.Conv2D):
layer_types.append("Conv2D");
#elif (type(layer) == keras.layers.pooling.MaxPooling2D):
elif (type(layer) == keras.layers.MaxPooling2D):
layer_types.append("MaxPooling2D");
#elif (type(layer) == keras.layers.core.Dropout):
elif (type(layer) == keras.layers.Dropout):
layer_types.append("Dropout");
#elif (type(layer) == keras.layers.core.Flatten):
elif (type(layer) == keras.layers.Flatten):
layer_types.append("Flatten");
#elif (type(layer) == keras.layers.core.Activation):
elif (type(layer) == keras.layers.Activation):
layer_types.append("Activation");
last_layer_nodes = input_layer;
nodes_up = input_layer;
#if(type(model.layers[0]) != keras.layers.core.Dense):
if(type(model.layers[0]) != keras.layers.Dense):
last_layer_nodes = 1;
nodes_up = 1;
input_layer = 1;
g = Digraph('g', filename=filename);
n = 0;
g.graph_attr.update(splines="false", nodesep='1', ranksep='2');
#Input Layer
with g.subgraph(name='cluster_input') as c:
#if(type(model.layers[0]) == keras.layers.core.Dense):
if(type(model.layers[0]) == keras.layers.Dense):
the_label = title+'\n\n\n\nInput Layer';
if (int(str(model.layers[0].input_shape).split(",")[1][1:-1]) > 10):
the_label += " (+"+str(int(str(model.layers[0].input_shape).split(",")[1][1:-1]) - 10)+")";
input_layer = 10;
c.attr(color='white')
for i in range(0, input_layer):
n += 1;
c.node(str(n));
c.attr(label=the_label)
c.attr(rank='same');
c.node_attr.update(color="#2ecc71", style="filled", fontcolor="#2ecc71", shape="circle");
#elif(type(model.layers[0]) == keras.layers.convolutional.Conv2D):
elif(type(model.layers[0]) == keras.layers.Conv2D):
#Conv2D Input visualizing
the_label = title+'\n\n\n\nInput Layer';
c.attr(color="white", label=the_label);
c.node_attr.update(shape="square");
pxls = str(model.layers[0].input_shape).split(',');
clr = int(pxls[3][1:-1]);
if (clr == 1):
clrmap = "Grayscale";
the_color = "black:white";
elif (clr == 3):
clrmap = "RGB";
the_color = "#e74c3c:#3498db";
else:
clrmap = "";
c.node_attr.update(fontcolor="white", fillcolor=the_color, style="filled");
n += 1;
c.node(str(n), label="Image\n"+pxls[1]+" x"+pxls[2]+" pixels\n"+clrmap, fontcolor="white");
else:
raise ValueError("ANN Visualizer: Layer not supported for visualizing");
for i in range(0, hidden_layers_nr):
with g.subgraph(name="cluster_"+str(i+1)) as c:
if (layer_types[i] == "Dense"):
c.attr(color='white');
c.attr(rank='same');
#If hidden_layers[i] > 10, dont include all
the_label = "";
if (int(str(model.layers[i].output_shape).split(",")[1][1:-1]) > 10):
the_label += " (+"+str(int(str(model.layers[i].output_shape).split(",")[1][1:-1]) - 10)+")";
hidden_layers[i] = 10;
c.attr(labeljust="right", labelloc="b", label=the_label);
for j in range(0, hidden_layers[i]):
n += 1;
c.node(str(n), shape="circle", style="filled", color="#3498db", fontcolor="#3498db");
for h in range(nodes_up - last_layer_nodes + 1 , nodes_up + 1):
g.edge(str(h), str(n));
last_layer_nodes = hidden_layers[i];
nodes_up += hidden_layers[i];
elif (layer_types[i] == "Conv2D"):
c.attr(style='filled', color='#5faad0');
n += 1;
kernel_size = str(model.layers[i].get_config()['kernel_size']).split(',')[0][1] + "x" + str(model.layers[i].get_config()['kernel_size']).split(',')[1][1 : -1];
filters = str(model.layers[i].get_config()['filters']);
c.node("conv_"+str(n), label="Convolutional Layer\nKernel Size: "+kernel_size+"\nFilters: "+filters, shape="square");
c.node(str(n), label=filters+"\nFeature Maps", shape="square");
g.edge("conv_"+str(n), str(n));
for h in range(nodes_up - last_layer_nodes + 1 , nodes_up + 1):
g.edge(str(h), "conv_"+str(n));
last_layer_nodes = 1;
nodes_up += 1;
elif (layer_types[i] == "MaxPooling2D"):
c.attr(color="white");
n += 1;
pool_size = str(model.layers[i].get_config()['pool_size']).split(',')[0][1] + "x" + str(model.layers[i].get_config()['pool_size']).split(',')[1][1 : -1];
c.node(str(n), label="Max Pooling\nPool Size: "+pool_size, style="filled", fillcolor="#8e44ad", fontcolor="white");
for h in range(nodes_up - last_layer_nodes + 1 , nodes_up + 1):
g.edge(str(h), str(n));
last_layer_nodes = 1;
nodes_up += 1;
elif (layer_types[i] == "Flatten"):
n += 1;
c.attr(color="white");
c.node(str(n), label="Flattening", shape="invtriangle", style="filled", fillcolor="#2c3e50", fontcolor="white");
for h in range(nodes_up - last_layer_nodes + 1 , nodes_up + 1):
g.edge(str(h), str(n));
last_layer_nodes = 1;
nodes_up += 1;
elif (layer_types[i] == "Dropout"):
n += 1;
c.attr(color="white");
c.node(str(n), label="Dropout Layer", style="filled", fontcolor="white", fillcolor="#f39c12");
for h in range(nodes_up - last_layer_nodes + 1 , nodes_up + 1):
g.edge(str(h), str(n));
last_layer_nodes = 1;
nodes_up += 1;
elif (layer_types[i] == "Activation"):
n += 1;
c.attr(color="white");
fnc = model.layers[i].get_config()['activation'];
c.node(str(n), shape="octagon", label="Activation Layer\nFunction: "+fnc, style="filled", fontcolor="white", fillcolor="#00b894");
for h in range(nodes_up - last_layer_nodes + 1 , nodes_up + 1):
g.edge(str(h), str(n));
last_layer_nodes = 1;
nodes_up += 1;
with g.subgraph(name='cluster_output') as c:
#if (type(model.layers[-1]) == keras.layers.core.Dense):
if (type(model.layers[-1]) == keras.layers.Dense):
c.attr(color='white')
c.attr(rank='same');
c.attr(labeljust="1");
for i in range(1, output_layer+1):
n += 1;
c.node(str(n), shape="circle", style="filled", color="#e74c3c", fontcolor="#e74c3c");
for h in range(nodes_up - last_layer_nodes + 1 , nodes_up + 1):
g.edge(str(h), str(n));
c.attr(label='Output Layer', labelloc="bottom")
c.node_attr.update(color="#2ecc71", style="filled", fontcolor="#2ecc71", shape="circle");
g.attr(arrowShape="none");
g.edge_attr.update(arrowhead="none", color="#707070");
if view == True:
g.view();