Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/torch/nngraph.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkoray kavukcuoglu <koray@kavukcuoglu.org>2015-01-14 18:30:12 +0300
committerkoray kavukcuoglu <koray@kavukcuoglu.org>2015-01-14 18:30:12 +0300
commit1b7d7c9de325e7adf309912d59ba8f2c68d95931 (patch)
tree9990f3d3547759153576accd50b3de7ecbc9e3ea
parent518b60b632179b09db4b06c953c2ac4fc66097ce (diff)
parent6dc7823207a32fb93f3979bf659fb6cce71d1df5 (diff)
Merge pull request #36 from jjh42/annotation
Annotation
-rw-r--r--README.md35
-rw-r--r--doc/annotation_bg.svg166
-rw-r--r--doc/annotation_fg.svg166
-rw-r--r--node.lua65
-rw-r--r--test/test_nngraph.lua38
5 files changed, 460 insertions, 10 deletions
diff --git a/README.md b/README.md
index 12416e8..8366cc6 100644
--- a/README.md
+++ b/README.md
@@ -131,3 +131,38 @@ graph.dot(gmod.fg,'Big MLP')
<img src= "https://raw.github.com/koraykv/torch-nngraph/master/doc/mlp4_backward.png" width="300px"/>
+## Annotations
+
+It is possible to add annotations to your network, such as labeling nodes
+with names or attributes which will show up when you graph the network.
+This can be helpful in large graphs.
+
+For the full list of graph attributes see the
+[graphviz documentation](http://www.graphviz.org/doc/info/attrs.html).
+
+```
+ input = nn.Identity()()
+ L1 = nn.Tanh()(nn.Linear(10,20)(input)):annotate{
+ name = 'L1', description = 'Level 1 Node',
+ graphAttributes = {color = 'red'}}
+ L2 = nn.Tanh()(nn.Linear(30,60)(nn.JoinTable(1)({input,L1}))):annotate{
+ name = 'L2', description = 'Level 2 Node',
+ graphAttributes = {color = 'blue', fontcolor = 'green'}}
+ L3 = nn.Tanh()(nn.Linear(80,160)(nn.JoinTable(1)({L1,L2}))):annotate{
+ name = 'L3', descrption = 'Level 3 Node',
+ graphAttributes = {color = 'green',
+ style='filled', fillcolor = 'yellow'}}
+
+ g = nn.gModule({input},{L3})
+
+ indata = torch.rand(10)
+ gdata = torch.rand(160)
+ g:forward(indata)
+ g:backward(indata,gdata)
+
+ graph.dot(g.fg,'Forward Graph', '/tmp/fg')
+ graph.dot(g.bg,'Backward Graph', '/tmp/bg')
+```
+
+![Annotated forward graph](doc/annotation_fg.svg?raw=true)
+![Annotated backward graph](doc/annotation_bg.svg?raw=true)
diff --git a/doc/annotation_bg.svg b/doc/annotation_bg.svg
new file mode 100644
index 0000000..96af42a
--- /dev/null
+++ b/doc/annotation_bg.svg
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.36.0 (20140111.2315)
+ -->
+<!-- Title: G Pages: 1 -->
+<svg width="477pt" height="1539pt"
+ viewBox="0.00 0.00 477.00 1539.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1535)">
+<title>G</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-1535 473,-1535 473,4 -4,4"/>
+<text text-anchor="middle" x="234.5" y="-1515.8" font-family="Times,serif" font-size="14.00">Backward Graph</text>
+<!-- n1 -->
+<g id="node1" class="node"><title>n1</title>
+<ellipse fill="none" stroke="black" cx="236" cy="-1470" rx="123.055" ry="37.4533"/>
+<text text-anchor="middle" x="236" y="-1481.3" font-family="Times,serif" font-size="14.00">Node1</text>
+<text text-anchor="start" x="157" y="-1466.3" font-family="Times,serif" font-size="14.00">input = {Tensor[160]}</text>
+<text text-anchor="middle" x="236" y="-1451.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[160]}</text>
+</g>
+<!-- n2 -->
+<g id="node2" class="node"><title>n2</title>
+<ellipse fill="yellow" stroke="green" cx="236" cy="-1348" rx="123.055" ry="48.1667"/>
+<text text-anchor="middle" x="236" y="-1366.8" font-family="Times,serif" font-size="14.00">L3 (2)</text>
+<text text-anchor="start" x="157" y="-1351.8" font-family="Times,serif" font-size="14.00">input = {Tensor[160]}</text>
+<text text-anchor="start" x="157" y="-1336.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[160]}</text>
+<text text-anchor="middle" x="236" y="-1321.8" font-family="Times,serif" font-size="14.00">module = nn.Tanh</text>
+</g>
+<!-- n1&#45;&gt;n2 -->
+<g id="edge1" class="edge"><title>n1&#45;&gt;n2</title>
+<path fill="none" stroke="black" d="M236,-1432.34C236,-1424.22 236,-1415.42 236,-1406.68"/>
+<polygon fill="black" stroke="black" points="239.5,-1406.5 236,-1396.5 232.5,-1406.5 239.5,-1406.5"/>
+</g>
+<!-- n3 -->
+<g id="node3" class="node"><title>n3</title>
+<ellipse fill="none" stroke="black" cx="236" cy="-1216" rx="123.055" ry="48.1667"/>
+<text text-anchor="middle" x="236" y="-1234.8" font-family="Times,serif" font-size="14.00">Node3</text>
+<text text-anchor="start" x="157" y="-1219.8" font-family="Times,serif" font-size="14.00">input = {Tensor[80]}</text>
+<text text-anchor="start" x="157" y="-1204.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[160]}</text>
+<text text-anchor="middle" x="236" y="-1189.8" font-family="Times,serif" font-size="14.00">module = nn.Linear</text>
+</g>
+<!-- n2&#45;&gt;n3 -->
+<g id="edge2" class="edge"><title>n2&#45;&gt;n3</title>
+<path fill="none" stroke="black" d="M236,-1299.7C236,-1291.54 236,-1282.99 236,-1274.6"/>
+<polygon fill="black" stroke="black" points="239.5,-1274.48 236,-1264.48 232.5,-1274.48 239.5,-1274.48"/>
+</g>
+<!-- n4 -->
+<g id="node4" class="node"><title>n4</title>
+<ellipse fill="none" stroke="black" cx="236" cy="-1073" rx="138.951" ry="58.8803"/>
+<text text-anchor="middle" x="236" y="-1099.3" font-family="Times,serif" font-size="14.00">Node4</text>
+<text text-anchor="start" x="145.5" y="-1084.3" font-family="Times,serif" font-size="14.00">input = {Tensor[20],Tensor[60]}</text>
+<text text-anchor="start" x="145.5" y="-1069.3" font-family="Times,serif" font-size="14.00">mapindex = {Node5,Node6}</text>
+<text text-anchor="start" x="145.5" y="-1054.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[80]}</text>
+<text text-anchor="middle" x="236" y="-1039.3" font-family="Times,serif" font-size="14.00">module = nn.JoinTable</text>
+</g>
+<!-- n3&#45;&gt;n4 -->
+<g id="edge3" class="edge"><title>n3&#45;&gt;n4</title>
+<path fill="none" stroke="black" d="M236,-1167.66C236,-1159.38 236,-1150.62 236,-1141.91"/>
+<polygon fill="black" stroke="black" points="239.5,-1141.74 236,-1131.74 232.5,-1141.74 239.5,-1141.74"/>
+</g>
+<!-- n5 -->
+<g id="node5" class="node"><title>n5</title>
+<ellipse fill="none" stroke="red" cx="163" cy="-468" rx="163.013" ry="69.0935"/>
+<text text-anchor="middle" x="163" y="-501.8" font-family="Times,serif" font-size="14.00">L1 (5)</text>
+<text text-anchor="middle" x="163" y="-486.8" font-family="Times,serif" font-size="14.00">desc = Level 1 Node</text>
+<text text-anchor="start" x="55.5" y="-471.8" font-family="Times,serif" font-size="14.00">input = {Tensor[20]}</text>
+<text text-anchor="start" x="55.5" y="-456.8" font-family="Times,serif" font-size="14.00">gradOutputBuffer = Tensor[20]</text>
+<text text-anchor="start" x="55.5" y="-441.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[20],Tensor[20]}</text>
+<text text-anchor="middle" x="163" y="-426.8" font-family="Times,serif" font-size="14.00">module = nn.Tanh</text>
+</g>
+<!-- n4&#45;&gt;n5 -->
+<g id="edge4" class="edge"><title>n4&#45;&gt;n5</title>
+<path fill="none" stroke="black" d="M198.203,-1016.31C191.643,-1004.16 185.737,-991.025 182,-978 139.683,-830.489 146.007,-649.067 154.472,-547.496"/>
+<polygon fill="black" stroke="black" points="157.978,-547.583 155.35,-537.319 151.004,-546.981 157.978,-547.583"/>
+</g>
+<!-- n6 -->
+<g id="node6" class="node"><title>n6</title>
+<ellipse fill="none" stroke="blue" cx="309" cy="-919" rx="118.13" ry="58.8803"/>
+<text text-anchor="middle" x="309" y="-945.3" font-family="Times,serif" font-size="14.00" fill="green">L2 (6)</text>
+<text text-anchor="middle" x="309" y="-930.3" font-family="Times,serif" font-size="14.00" fill="green">desc = Level 2 Node</text>
+<text text-anchor="start" x="233.5" y="-915.3" font-family="Times,serif" font-size="14.00" fill="green">input = {Tensor[60]}</text>
+<text text-anchor="start" x="233.5" y="-900.3" font-family="Times,serif" font-size="14.00" fill="green">gradOutput = {Tensor[60]}</text>
+<text text-anchor="middle" x="309" y="-885.3" font-family="Times,serif" font-size="14.00" fill="green">module = nn.Tanh</text>
+</g>
+<!-- n4&#45;&gt;n6 -->
+<g id="edge5" class="edge"><title>n4&#45;&gt;n6</title>
+<path fill="none" stroke="black" d="M263.183,-1015.4C267.9,-1005.58 272.84,-995.292 277.658,-985.261"/>
+<polygon fill="black" stroke="black" points="280.864,-986.67 282.038,-976.14 274.554,-983.639 280.864,-986.67"/>
+</g>
+<!-- n7 -->
+<g id="node7" class="node"><title>n7</title>
+<ellipse fill="none" stroke="black" cx="186" cy="-314" rx="118.13" ry="48.1667"/>
+<text text-anchor="middle" x="186" y="-332.8" font-family="Times,serif" font-size="14.00">Node7</text>
+<text text-anchor="start" x="110.5" y="-317.8" font-family="Times,serif" font-size="14.00">input = {Tensor[10]}</text>
+<text text-anchor="start" x="110.5" y="-302.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[20]}</text>
+<text text-anchor="middle" x="186" y="-287.8" font-family="Times,serif" font-size="14.00">module = nn.Linear</text>
+</g>
+<!-- n5&#45;&gt;n7 -->
+<g id="edge6" class="edge"><title>n5&#45;&gt;n7</title>
+<path fill="none" stroke="black" d="M173.356,-398.559C174.693,-389.724 176.051,-380.751 177.356,-372.125"/>
+<polygon fill="black" stroke="black" points="180.824,-372.597 178.86,-362.186 173.903,-371.55 180.824,-372.597"/>
+</g>
+<!-- n8 -->
+<g id="node8" class="node"><title>n8</title>
+<ellipse fill="none" stroke="black" cx="319" cy="-776" rx="118.13" ry="48.1667"/>
+<text text-anchor="middle" x="319" y="-794.8" font-family="Times,serif" font-size="14.00">Node8</text>
+<text text-anchor="start" x="243.5" y="-779.8" font-family="Times,serif" font-size="14.00">input = {Tensor[30]}</text>
+<text text-anchor="start" x="243.5" y="-764.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[60]}</text>
+<text text-anchor="middle" x="319" y="-749.8" font-family="Times,serif" font-size="14.00">module = nn.Linear</text>
+</g>
+<!-- n6&#45;&gt;n8 -->
+<g id="edge7" class="edge"><title>n6&#45;&gt;n8</title>
+<path fill="none" stroke="black" d="M313.096,-860.243C313.702,-851.7 314.326,-842.899 314.932,-834.364"/>
+<polygon fill="black" stroke="black" points="318.442,-834.344 315.658,-824.121 311.459,-833.848 318.442,-834.344"/>
+</g>
+<!-- n9 -->
+<g id="node9" class="node"><title>n9</title>
+<ellipse fill="none" stroke="black" cx="270" cy="-171" rx="163.013" ry="58.8803"/>
+<text text-anchor="middle" x="270" y="-197.3" font-family="Times,serif" font-size="14.00">Node9</text>
+<text text-anchor="start" x="162.5" y="-182.3" font-family="Times,serif" font-size="14.00">input = {Tensor[10]}</text>
+<text text-anchor="start" x="162.5" y="-167.3" font-family="Times,serif" font-size="14.00">gradOutputBuffer = Tensor[10]</text>
+<text text-anchor="start" x="162.5" y="-152.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[10],Tensor[10]}</text>
+<text text-anchor="middle" x="270" y="-137.3" font-family="Times,serif" font-size="14.00">module = nn.Identity</text>
+</g>
+<!-- n7&#45;&gt;n9 -->
+<g id="edge8" class="edge"><title>n7&#45;&gt;n9</title>
+<path fill="none" stroke="black" d="M213.505,-266.831C219.13,-257.389 225.15,-247.283 231.088,-237.317"/>
+<polygon fill="black" stroke="black" points="234.161,-238.996 236.273,-228.614 228.148,-235.413 234.161,-238.996"/>
+</g>
+<!-- n10 -->
+<g id="node10" class="node"><title>n10</title>
+<ellipse fill="none" stroke="black" cx="330" cy="-633" rx="138.951" ry="58.8803"/>
+<text text-anchor="middle" x="330" y="-659.3" font-family="Times,serif" font-size="14.00">Node10</text>
+<text text-anchor="start" x="239.5" y="-644.3" font-family="Times,serif" font-size="14.00">input = {Tensor[10],Tensor[20]}</text>
+<text text-anchor="start" x="239.5" y="-629.3" font-family="Times,serif" font-size="14.00">mapindex = {Node9,Node5}</text>
+<text text-anchor="start" x="239.5" y="-614.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[30]}</text>
+<text text-anchor="middle" x="330" y="-599.3" font-family="Times,serif" font-size="14.00">module = nn.JoinTable</text>
+</g>
+<!-- n8&#45;&gt;n10 -->
+<g id="edge9" class="edge"><title>n8&#45;&gt;n10</title>
+<path fill="none" stroke="black" d="M322.693,-727.657C323.339,-719.376 324.023,-710.617 324.702,-701.909"/>
+<polygon fill="black" stroke="black" points="328.207,-701.986 325.495,-691.744 321.228,-701.442 328.207,-701.986"/>
+</g>
+<!-- n11 -->
+<g id="node11" class="node"><title>n11</title>
+<ellipse fill="none" stroke="black" cx="270" cy="-38" rx="118.13" ry="37.4533"/>
+<text text-anchor="middle" x="270" y="-49.3" font-family="Times,serif" font-size="14.00">Node11</text>
+<text text-anchor="start" x="194.5" y="-34.3" font-family="Times,serif" font-size="14.00">input = {Tensor[10]}</text>
+<text text-anchor="middle" x="270" y="-19.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[10]}</text>
+</g>
+<!-- n9&#45;&gt;n11 -->
+<g id="edge10" class="edge"><title>n9&#45;&gt;n11</title>
+<path fill="none" stroke="black" d="M270,-112.16C270,-103.389 270,-94.4321 270,-85.9302"/>
+<polygon fill="black" stroke="black" points="273.5,-85.8285 270,-75.8285 266.5,-85.8285 273.5,-85.8285"/>
+</g>
+<!-- n10&#45;&gt;n5 -->
+<g id="edge12" class="edge"><title>n10&#45;&gt;n5</title>
+<path fill="none" stroke="black" d="M275.318,-578.628C262.396,-566.015 248.424,-552.378 234.869,-539.148"/>
+<polygon fill="black" stroke="black" points="236.992,-536.329 227.391,-531.849 232.103,-541.338 236.992,-536.329"/>
+</g>
+<!-- n10&#45;&gt;n9 -->
+<g id="edge11" class="edge"><title>n10&#45;&gt;n9</title>
+<path fill="none" stroke="black" d="M336.006,-574.074C341.673,-500.625 345.121,-370.921 313,-266 310.212,-256.894 306.732,-247.524 302.967,-238.391"/>
+<polygon fill="black" stroke="black" points="306.097,-236.808 298.958,-228.98 299.658,-239.551 306.097,-236.808"/>
+</g>
+</g>
+</svg>
diff --git a/doc/annotation_fg.svg b/doc/annotation_fg.svg
new file mode 100644
index 0000000..12148fa
--- /dev/null
+++ b/doc/annotation_fg.svg
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.36.0 (20140111.2315)
+ -->
+<!-- Title: G Pages: 1 -->
+<svg width="477pt" height="1539pt"
+ viewBox="0.00 0.00 477.00 1539.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1535)">
+<title>G</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-1535 473,-1535 473,4 -4,4"/>
+<text text-anchor="middle" x="234.5" y="-1515.8" font-family="Times,serif" font-size="14.00">Forward Graph</text>
+<!-- n1 -->
+<g id="node1" class="node"><title>n1</title>
+<ellipse fill="yellow" stroke="green" cx="238" cy="-160" rx="123.055" ry="48.1667"/>
+<text text-anchor="middle" x="238" y="-178.8" font-family="Times,serif" font-size="14.00">L3 (1)</text>
+<text text-anchor="start" x="159" y="-163.8" font-family="Times,serif" font-size="14.00">input = {Tensor[160]}</text>
+<text text-anchor="start" x="159" y="-148.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[160]}</text>
+<text text-anchor="middle" x="238" y="-133.8" font-family="Times,serif" font-size="14.00">module = nn.Tanh</text>
+</g>
+<!-- n2 -->
+<g id="node2" class="node"><title>n2</title>
+<ellipse fill="none" stroke="black" cx="238" cy="-38" rx="123.055" ry="37.4533"/>
+<text text-anchor="middle" x="238" y="-49.3" font-family="Times,serif" font-size="14.00">Node2</text>
+<text text-anchor="start" x="159" y="-34.3" font-family="Times,serif" font-size="14.00">input = {Tensor[160]}</text>
+<text text-anchor="middle" x="238" y="-19.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[160]}</text>
+</g>
+<!-- n1&#45;&gt;n2 -->
+<g id="edge1" class="edge"><title>n1&#45;&gt;n2</title>
+<path fill="none" stroke="black" d="M238,-111.573C238,-103.096 238,-94.269 238,-85.8099"/>
+<polygon fill="black" stroke="black" points="241.5,-85.7224 238,-75.7224 234.5,-85.7224 241.5,-85.7224"/>
+</g>
+<!-- n3 -->
+<g id="node3" class="node"><title>n3</title>
+<ellipse fill="none" stroke="black" cx="238" cy="-292" rx="123.055" ry="48.1667"/>
+<text text-anchor="middle" x="238" y="-310.8" font-family="Times,serif" font-size="14.00">Node3</text>
+<text text-anchor="start" x="159" y="-295.8" font-family="Times,serif" font-size="14.00">input = {Tensor[80]}</text>
+<text text-anchor="start" x="159" y="-280.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[160]}</text>
+<text text-anchor="middle" x="238" y="-265.8" font-family="Times,serif" font-size="14.00">module = nn.Linear</text>
+</g>
+<!-- n3&#45;&gt;n1 -->
+<g id="edge2" class="edge"><title>n3&#45;&gt;n1</title>
+<path fill="none" stroke="black" d="M238,-243.699C238,-235.544 238,-226.987 238,-218.597"/>
+<polygon fill="black" stroke="black" points="241.5,-218.483 238,-208.483 234.5,-218.483 241.5,-218.483"/>
+</g>
+<!-- n4 -->
+<g id="node4" class="node"><title>n4</title>
+<ellipse fill="none" stroke="black" cx="238" cy="-435" rx="138.951" ry="58.8803"/>
+<text text-anchor="middle" x="238" y="-461.3" font-family="Times,serif" font-size="14.00">Node4</text>
+<text text-anchor="start" x="147.5" y="-446.3" font-family="Times,serif" font-size="14.00">input = {Tensor[20],Tensor[60]}</text>
+<text text-anchor="start" x="147.5" y="-431.3" font-family="Times,serif" font-size="14.00">mapindex = {Node5,Node6}</text>
+<text text-anchor="start" x="147.5" y="-416.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[80]}</text>
+<text text-anchor="middle" x="238" y="-401.3" font-family="Times,serif" font-size="14.00">module = nn.JoinTable</text>
+</g>
+<!-- n4&#45;&gt;n3 -->
+<g id="edge3" class="edge"><title>n4&#45;&gt;n3</title>
+<path fill="none" stroke="black" d="M238,-376.243C238,-367.7 238,-358.899 238,-350.364"/>
+<polygon fill="black" stroke="black" points="241.5,-350.121 238,-340.121 234.5,-350.121 241.5,-350.121"/>
+</g>
+<!-- n5 -->
+<g id="node5" class="node"><title>n5</title>
+<ellipse fill="none" stroke="red" cx="163" cy="-1040" rx="163.013" ry="69.0935"/>
+<text text-anchor="middle" x="163" y="-1073.8" font-family="Times,serif" font-size="14.00">L1 (5)</text>
+<text text-anchor="middle" x="163" y="-1058.8" font-family="Times,serif" font-size="14.00">desc = Level 1 Node</text>
+<text text-anchor="start" x="55.5" y="-1043.8" font-family="Times,serif" font-size="14.00">input = {Tensor[20]}</text>
+<text text-anchor="start" x="55.5" y="-1028.8" font-family="Times,serif" font-size="14.00">gradOutputBuffer = Tensor[20]</text>
+<text text-anchor="start" x="55.5" y="-1013.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[20],Tensor[20]}</text>
+<text text-anchor="middle" x="163" y="-998.8" font-family="Times,serif" font-size="14.00">module = nn.Tanh</text>
+</g>
+<!-- n5&#45;&gt;n4 -->
+<g id="edge4" class="edge"><title>n5&#45;&gt;n4</title>
+<path fill="none" stroke="black" d="M156.686,-970.368C149.678,-871.134 144.38,-682.741 187,-530 189.695,-520.343 193.522,-510.577 197.884,-501.179"/>
+<polygon fill="black" stroke="black" points="201.161,-502.442 202.402,-491.92 194.871,-499.373 201.161,-502.442"/>
+</g>
+<!-- n10 -->
+<g id="node10" class="node"><title>n10</title>
+<ellipse fill="none" stroke="black" cx="330" cy="-875" rx="138.951" ry="58.8803"/>
+<text text-anchor="middle" x="330" y="-901.3" font-family="Times,serif" font-size="14.00">Node10</text>
+<text text-anchor="start" x="239.5" y="-886.3" font-family="Times,serif" font-size="14.00">input = {Tensor[10],Tensor[20]}</text>
+<text text-anchor="start" x="239.5" y="-871.3" font-family="Times,serif" font-size="14.00">mapindex = {Node9,Node5}</text>
+<text text-anchor="start" x="239.5" y="-856.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[30]}</text>
+<text text-anchor="middle" x="330" y="-841.3" font-family="Times,serif" font-size="14.00">module = nn.JoinTable</text>
+</g>
+<!-- n5&#45;&gt;n10 -->
+<g id="edge12" class="edge"><title>n5&#45;&gt;n10</title>
+<path fill="none" stroke="black" d="M227.567,-975.98C240.964,-962.903 255.048,-949.156 268.339,-936.184"/>
+<polygon fill="black" stroke="black" points="270.92,-938.556 275.631,-929.067 266.03,-933.547 270.92,-938.556"/>
+</g>
+<!-- n6 -->
+<g id="node6" class="node"><title>n6</title>
+<ellipse fill="none" stroke="blue" cx="314" cy="-589" rx="118.13" ry="58.8803"/>
+<text text-anchor="middle" x="314" y="-615.3" font-family="Times,serif" font-size="14.00" fill="green">L2 (6)</text>
+<text text-anchor="middle" x="314" y="-600.3" font-family="Times,serif" font-size="14.00" fill="green">desc = Level 2 Node</text>
+<text text-anchor="start" x="238.5" y="-585.3" font-family="Times,serif" font-size="14.00" fill="green">input = {Tensor[60]}</text>
+<text text-anchor="start" x="238.5" y="-570.3" font-family="Times,serif" font-size="14.00" fill="green">gradOutput = {Tensor[60]}</text>
+<text text-anchor="middle" x="314" y="-555.3" font-family="Times,serif" font-size="14.00" fill="green">module = nn.Tanh</text>
+</g>
+<!-- n6&#45;&gt;n4 -->
+<g id="edge5" class="edge"><title>n6&#45;&gt;n4</title>
+<path fill="none" stroke="black" d="M285.916,-531.833C281.028,-522.056 275.904,-511.808 270.9,-501.801"/>
+<polygon fill="black" stroke="black" points="273.952,-500.077 266.349,-492.698 267.691,-503.208 273.952,-500.077"/>
+</g>
+<!-- n7 -->
+<g id="node7" class="node"><title>n7</title>
+<ellipse fill="none" stroke="black" cx="185" cy="-1194" rx="118.13" ry="48.1667"/>
+<text text-anchor="middle" x="185" y="-1212.8" font-family="Times,serif" font-size="14.00">Node7</text>
+<text text-anchor="start" x="109.5" y="-1197.8" font-family="Times,serif" font-size="14.00">input = {Tensor[10]}</text>
+<text text-anchor="start" x="109.5" y="-1182.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[20]}</text>
+<text text-anchor="middle" x="185" y="-1167.8" font-family="Times,serif" font-size="14.00">module = nn.Linear</text>
+</g>
+<!-- n7&#45;&gt;n5 -->
+<g id="edge6" class="edge"><title>n7&#45;&gt;n5</title>
+<path fill="none" stroke="black" d="M178.16,-1145.74C176.95,-1137.38 175.662,-1128.48 174.366,-1119.53"/>
+<polygon fill="black" stroke="black" points="177.801,-1118.83 172.905,-1109.43 170.874,-1119.83 177.801,-1118.83"/>
+</g>
+<!-- n8 -->
+<g id="node8" class="node"><title>n8</title>
+<ellipse fill="none" stroke="black" cx="324" cy="-732" rx="118.13" ry="48.1667"/>
+<text text-anchor="middle" x="324" y="-750.8" font-family="Times,serif" font-size="14.00">Node8</text>
+<text text-anchor="start" x="248.5" y="-735.8" font-family="Times,serif" font-size="14.00">input = {Tensor[30]}</text>
+<text text-anchor="start" x="248.5" y="-720.8" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[60]}</text>
+<text text-anchor="middle" x="324" y="-705.8" font-family="Times,serif" font-size="14.00">module = nn.Linear</text>
+</g>
+<!-- n8&#45;&gt;n6 -->
+<g id="edge7" class="edge"><title>n8&#45;&gt;n6</title>
+<path fill="none" stroke="black" d="M320.642,-683.657C320.055,-675.376 319.434,-666.617 318.816,-657.909"/>
+<polygon fill="black" stroke="black" points="322.294,-657.472 318.095,-647.744 315.312,-657.967 322.294,-657.472"/>
+</g>
+<!-- n9 -->
+<g id="node9" class="node"><title>n9</title>
+<ellipse fill="none" stroke="black" cx="280" cy="-1337" rx="163.013" ry="58.8803"/>
+<text text-anchor="middle" x="280" y="-1363.3" font-family="Times,serif" font-size="14.00">Node9</text>
+<text text-anchor="start" x="172.5" y="-1348.3" font-family="Times,serif" font-size="14.00">input = {Tensor[10]}</text>
+<text text-anchor="start" x="172.5" y="-1333.3" font-family="Times,serif" font-size="14.00">gradOutputBuffer = Tensor[10]</text>
+<text text-anchor="start" x="172.5" y="-1318.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[10],Tensor[10]}</text>
+<text text-anchor="middle" x="280" y="-1303.3" font-family="Times,serif" font-size="14.00">module = nn.Identity</text>
+</g>
+<!-- n9&#45;&gt;n7 -->
+<g id="edge8" class="edge"><title>n9&#45;&gt;n7</title>
+<path fill="none" stroke="black" d="M242.181,-1279.87C235.308,-1269.67 228.154,-1259.05 221.326,-1248.92"/>
+<polygon fill="black" stroke="black" points="224.171,-1246.87 215.681,-1240.54 218.366,-1250.79 224.171,-1246.87"/>
+</g>
+<!-- n9&#45;&gt;n10 -->
+<g id="edge11" class="edge"><title>n9&#45;&gt;n10</title>
+<path fill="none" stroke="black" d="M301.065,-1278.76C305.049,-1266.72 308.925,-1254.03 312,-1242 342.052,-1124.46 338.223,-1091.28 335,-970 334.777,-961.604 334.442,-952.792 334.049,-944.067"/>
+<polygon fill="black" stroke="black" points="337.536,-943.719 333.564,-933.897 330.544,-944.052 337.536,-943.719"/>
+</g>
+<!-- n10&#45;&gt;n8 -->
+<g id="edge9" class="edge"><title>n10&#45;&gt;n8</title>
+<path fill="none" stroke="black" d="M327.542,-816.243C327.179,-807.7 326.804,-798.899 326.441,-790.364"/>
+<polygon fill="black" stroke="black" points="329.927,-789.963 326.005,-780.121 322.934,-790.261 329.927,-789.963"/>
+</g>
+<!-- n11 -->
+<g id="node11" class="node"><title>n11</title>
+<ellipse fill="none" stroke="black" cx="280" cy="-1470" rx="118.13" ry="37.4533"/>
+<text text-anchor="middle" x="280" y="-1481.3" font-family="Times,serif" font-size="14.00">Node11</text>
+<text text-anchor="start" x="204.5" y="-1466.3" font-family="Times,serif" font-size="14.00">input = {Tensor[10]}</text>
+<text text-anchor="middle" x="280" y="-1451.3" font-family="Times,serif" font-size="14.00">gradOutput = {Tensor[10]}</text>
+</g>
+<!-- n11&#45;&gt;n9 -->
+<g id="edge10" class="edge"><title>n11&#45;&gt;n9</title>
+<path fill="none" stroke="black" d="M280,-1432.51C280,-1424.26 280,-1415.24 280,-1406.15"/>
+<polygon fill="black" stroke="black" points="283.5,-1405.9 280,-1395.9 276.5,-1405.9 283.5,-1405.9"/>
+</g>
+</g>
+</svg>
diff --git a/node.lua b/node.lua
index 53e7a12..758df4c 100644
--- a/node.lua
+++ b/node.lua
@@ -3,15 +3,29 @@ local utils = paths.dofile('utils.lua')
local istensor = utils.istensor
local istable = utils.istable
local istorchclass = utils.istorchclass
+require 'debug'
local nnNode,parent = torch.class('nngraph.Node','graph.Node')
function nnNode:__init(data)
parent.__init(self,data)
+ self.data.annotations = self.data.annotations or {}
self.data.mapindex = self.data.mapindex or {}
+ if not self.data.annotations._debugLabel then
+ self:_makeDebugLabel(debug.getinfo(6, 'Sl'))
+ end
end
+
+--[[ Build a string label which will be used a tooltip when
+ making a graph.]]
+function nnNode:_makeDebugLabel(dinfo)
+ self.data.annotations._debugLabel = string.format('[%s]:%d',
+ dinfo.short_src, dinfo.currentline, dinfo.name)
+end
+
+
-- domap ensures that this node will keep track of the order its children are added.
-- mapindex is a forward/backward list
-- index = self.data.mapindex[child.data]
@@ -28,7 +42,7 @@ function nnNode:add(child,domap)
end
-- this function returns noutput number of new nodes
--- that each take a single component of the output of this
+-- that each take a single component of the output of this
-- node in the order they are returned.
function nnNode:split(noutput)
assert(noutput >= 2, "splitting to one output is not supported")
@@ -44,13 +58,37 @@ function nnNode:split(noutput)
return unpack(selectnodes)
end
-function nnNode:name(name)
- if self.data and istable(self.data) then
- self.data.name = name
- end
- return self
+
+function nnNode:annotate(annotations)
+ for k, v in pairs(annotations) do
+ self.data.annotations[k] = v
+ end
+
+ return self
+end
+
+
+function nnNode:graphNodeName()
+ if self.data.annotations.name then
+ return self.data.annotations.name .. ' (' .. self.id .. ')'
+ else
+ return 'Node' .. self.id
+ end
+end
+
+
+function nnNode:graphNodeAttributes()
+ self.data.annotations.graphAttributes =
+ self.data.annotations.graphAttributes or {}
+ if not self.data.annotations.graphAttributes.tooltip then
+ self.data.annotations.graphAttributes.tooltip =
+ self.data.annotations._debugLabel
+ end
+
+ return self.data.annotations.graphAttributes
end
+
function nnNode:label()
local lbl = {}
@@ -85,17 +123,24 @@ function nnNode:label()
for k,v in pairs(self.data) do
local vstr = ''
- if k == 'mapindex' then
- if #v > 1 then
+ if k== 'mapindex' then
+ if #v > 1 then
vstr = getmapindexstr(v)
table.insert(lbl, k .. ' = ' .. vstr)
end
- elseif k == 'forwardNodeId' then
+ elseif k== 'forwardNodeId' or k== 'annotations' then
-- the forwardNodeId is not displayed in the label.
else
vstr = getstr(v)
table.insert(lbl, k .. ' = ' .. vstr)
end
end
- return table.concat(lbl,"\\l")
+
+ local desc
+ if self.data.annotations.description then
+ desc = 'desc = ' .. self.data.annotations.description .. '\\n'
+ else
+ desc = ''
+ end
+ return desc .. table.concat(lbl,"\\l")
end
diff --git a/test/test_nngraph.lua b/test/test_nngraph.lua
index 1193dc9..4062c5a 100644
--- a/test/test_nngraph.lua
+++ b/test/test_nngraph.lua
@@ -303,4 +303,42 @@ function test.test_resizeNestedAs()
checkGradients(net, input)
end
+
+function test.test_annotateGraph()
+ local input = nn.Identity()():annotate(
+ {name = 'Input', description = 'DescA',
+ graphAttributes = {color = 'red'}})
+
+ local hidden_a = nn.Linear(10, 10)(input):annotate(
+ {name = 'Hidden A', description = 'DescB',
+ graphAttributes = {color = 'blue', fontcolor='green', tooltip = 'I am green'}})
+ local hidden_b = nn.Sigmoid()(hidden_a)
+ local output = nn.Linear(10, 10)(hidden_b)
+ local net = nn.gModule({input}, {output})
+
+ tester:assert(hidden_a:label():match('DescB'))
+ local fg_tmpfile = os.tmpname()
+ local bg_tmpfile = os.tmpname()
+ graph.dot(net.fg, 'Test', fg_tmpfile)
+ graph.dot(net.fg, 'Test BG', bg_tmpfile)
+
+ local function checkDotFile(tmpfile)
+ local dotcontent = io.open(tmpfile .. '.dot', 'r'):read("*all")
+ tester:assert(
+ dotcontent:match('%[label=%"Input.*DescA.*%" color=red%]'))
+ tester:assert(
+ dotcontent:match(
+ '%[label=%"Hidden A.*DescB.*%".*fontcolor=green.*%]'))
+ tester:assert(
+ dotcontent:match('%[label=%".*DescB.*%".*color=blue.*%]'))
+ tester:assert(
+ dotcontent:match(
+ '%[label=%".*DescB.*%".*tooltip=%".*test_nngraph.lua.*%".*%]'))
+ end
+
+ checkDotFile(fg_tmpfile)
+ checkDotFile(bg_tmpfile)
+end
+
+
tester:add(test):run()