Visualization

You can run this page in Jupyter Notebook Open in Colab

PyNeuraLogic offers multiple options for visualization of templates and samples, which can be helpful while investigating how the high-level rule representations are being translated into computation graphs. The usage of visualization tools requires having installed Graphviz.

Depending on the parametrization, the drawing methods can output either graph image in bytes, graph image rendered into a file, or graph image displayed into IPython (Jupyter Notebook).

Additionally, it is also possible to retrieve the generated source of graphs in the DOT format. This format can then be used to display or further customize and manipulate generated graphs in other libraries.

Visualization of the XOR Example

To showcase the usage of visualization tools, we will use the template and the dataset introduced in XOR Example Open in Colab

Model Rendering

All that is needed to visualize the model - the template with current weights’ values is to call the draw method.

from neuralogic.utils.data import XOR_Vectorized


template, dataset = XOR_Vectorized()
model = template.build()

model.draw()
Template Rendered Graph

Tip

You can also visualize the template by calling the template.draw method.

Templates (models) and samples can be drawn into various raster formats (such as PNG or JPEG) or SVG format, which is considerably faster for larger graphs. To set the format, simply use the img_type parameter.

The drawing can be further parameterized, for example, with the value_detail parameter to display more (or less) decimal places of all values (there are three levels of detail - 0-2, where 0 has the least number of decimals and 2 the most number of decimals).

The model above was directly drawn into Jupyter Notebook without any parametrization. To draw the model into a file, all we have to do is add the filename parameter with a path to the output image, such as:

model.draw(filename="my_image.png")

We can also get raw images bytes by turning off displaying into IPython:

model.draw(show=False)

Tip

If you are drawing straight into Jupyter Notebook, you can include additional parameters into drawing functions to customize the underlying Image and SVG objects.

Samples Rendering

Samples can be drawn in the same way and supports the same parametrization as the model drawing.

An example of drawing samples can be seen in the code below, where we render the actual computation graph for the first example (input [0, 0]).

built_dataset = model.build_dataset(dataset)

built_dataset.samples[0].draw()
Sample Rendered Graph

Getting the DOT Source

To get the DOT source of the model or the sample, all you have to do is call the model_to_dot_source function or the sample_to_dot_source function, respectively.

from neuralogic.utils.visualize import sample_to_dot_source


dot_source = sample_to_dot_source(built_dataset.samples[0])
print(dot_source)
digraph G {
3 [shape=house, color=black, label="FactNeuron:3:w:<w3> [0,0] : xy
val: [0,0]
grad: [0,0]
dim: [2, 1]
fcn:
"]

2 [shape=ellipse, color=red, label="WeightedRuleNeuron:2:{1,8}xor:-{8,2}xy.
val: [0,0,0,0,0,0,0,0]
grad: [0,0,0,0,0,0,0,0]
dim: [8, 1]
fcn: Tanh
"]
2 -> 3 [label="1:w1:[8, 2]:[
[0.76,0.88],
[-0.45,-0.74],
[-0.71,-0.95],
[0.09,0.93],
[-0.79,0.25],
[-0.18,0.55],
[0.98,-0.03],
[0.49,0.47]
]"]

0 [shape=ellipse, color=blue, label="WeightedAtomNeuron:0:xor
val: 0
grad: 0
dim: []
fcn: Tanh
"]
0 -> 2 [label="0:w0:[1, 8]:[0.46,-0.52,0.27,0.1,0.2,-0.33,-0.23,0.97]"]

0 [shape = tripleoctagon]
}

Customizing Drawings

Beyond the value_detail parameter, drawings can be fully styled through the standalone DrawingSettings class from neuralogic.utils.visualize. It is separate from the training settings (SettingsProxy) and only configures the drawing backend.

from neuralogic.utils.visualize import DrawingSettings, draw_model


ds = DrawingSettings()
ds.value_decimals = 4
ds.display_values = False
ds.display_weights = False
ds.set_node_attr("fact", "fillcolor", "#fff2cc")
ds.set_edge_attr("ruleToHead", "color", "red")
ds.set_graph_attr("bgcolor", "white")

draw_model(model, filename="model.svg", img_type="svg", settings=ds)

Value detail is controlled by:

  • value_decimals - number of decimal places for numeric values (0 = integers only)

  • display_values - master switch for all numeric values

  • display_gradients - show gradients in neural-network drawings

  • display_dimensions - show value dimensions

  • display_functions - show combination/transformation function names

  • display_weights - show weight labels on edges

Styles are addressed by semantic element names rather than raw Graphviz attributes:

  • Template drawing: literal, fact, rule; edges ruleToBody, negatedRuleToBody, ruleToHead, bodyToFact

  • Grounding drawing: groundLiteral, groundHeadRule, groundRule, target; edges headToGroundRule, groundHeadRuleToGroundRule, groundRuleToLiteral, compactRuleEdge

  • Neural-network drawing: atomNeuron, weightedAtomNeuron, negationNeuron, aggregationNeuron, ruleNeuron, weightedRuleNeuron, factNeuron, targetNeuron; edges unweightedInput, weightedInput, fixedWeightInput

  • Pipeline drawing: pipe, identityPipe, branch, merge, start, terminal; edges pipelineEdge, pipelineTypeEdge

Graph-level attributes (e.g. bgcolor, rankdir, splines, fontname, nodesep, ranksep) can be set with set_graph_attr.

Pipeline Drawing

Backend pipelines can be drawn the same way via draw_pipeline:

from neuralogic.utils.visualize import draw_pipeline

draw_pipeline(pipeline, settings=ds)

Pipeline export helpers are pipeline_to_dot_source, pipeline_to_graphml_source, pipeline_to_networkx and save_pipeline_graphml.

GraphML and networkx Export

In addition to DOT source, graphs can be exported to GraphML - an XML format that can be loaded directly with networkx.read_graphml(...). The export helpers accept the same optional settings=DrawingSettings(...) argument as the drawing functions.

from neuralogic.utils.visualize import (
    model_to_graphml_source,
    model_to_networkx,
    save_model_graphml,
)


graphml = model_to_graphml_source(model, settings=ds)
graph = model_to_networkx(model, settings=ds)          # networkx.DiGraph
save_model_graphml(model, "model.graphml", settings=ds)

Sample-level variants are sample_to_graphml_source, sample_to_networkx and save_sample_graphml. Node labels are stored in the "label" node attribute of the returned networkx.DiGraph.