Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
b682ae60
提交
b682ae60
authored
8月 24, 2015
作者:
Christof Angermueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add user guide
上级
d8b8a536
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
302 行增加
和
25 行删除
+302
-25
.gitignore
.gitignore
+2
-0
index.ipynb
doc/d3viz/index.ipynb
+0
-0
index.txt
doc/d3viz/index.txt
+272
-0
d3viz.css
theano/d3viz/css/d3viz.css
+1
-1
d3viz.py
theano/d3viz/d3viz.py
+21
-11
template.html
theano/d3viz/html/template.html
+5
-10
d3viz.js
theano/d3viz/js/d3viz.js
+1
-1
test_d3viz.py
theano/d3viz/tests/test_d3viz.py
+0
-2
没有找到文件。
.gitignore
浏览文件 @
b682ae60
...
@@ -41,3 +41,5 @@ doc/d3viz/GSoC/150724_opfrom/bundle/
...
@@ -41,3 +41,5 @@ doc/d3viz/GSoC/150724_opfrom/bundle/
doc/d3viz/GSoC/150724_opfrom/bundle2/
doc/d3viz/GSoC/150724_opfrom/bundle2/
doc/d3viz/GSoC/150819
doc/d3viz/GSoC/150819
doc/d3viz/GSoC/150820
doc/d3viz/GSoC/150820
doc/d3viz/examples/
doc/d3viz/index_files/
doc/d3viz/index.ipynb
0 → 100644
浏览文件 @
b682ae60
This source diff could not be displayed because it is too large. You can
view the blob
instead.
doc/d3viz/index.txt
0 → 100644
浏览文件 @
b682ae60
.. _libdoc_printing:
============================================================================
:mod:`d3viz` -- d3viz: Interactive visualization of Theano compute graphs
============================================================================
.. module:: d3viz
:platform: Unix, Windows
:synopsis: Allows to interactively visualize Theano compute graphs
.. moduleauthor:: Christof Angermueller
Guide
=====
Requirements
------------
``d3viz`` requires the `pydot <https://pypi.python.org/pypi/pydot>`__
package, which can be installed with ``pip``:
::
pip install pydot
Overview
--------
``d3viz`` extends Theano’s `printing
module <http://deeplearning.net/software/theano/library/printing.html>`__
to interactively visualize compute graphs. Instead of creating a static
picture, it creates an HTML file, which can be opened with any
web-browser. ``d3viz`` allows
- to zoom to different regions and to move graphs via drag and drop,
- to position nodes both manually and automatically,
- to retrieve additional information about nodes and edges such as
their data type or definition in the source code,
- to edit node labels,
- to visualizing profiling information, and
- to explore nested graphs such as OpFromGraph nodes.
.. code:: python
import theano as th
import theano.tensor as T
import numpy as np
As an example, consider the following multilayer perceptron with one
hidden layer and a softmax output layer.
.. code:: python
ninputs = 1000
nfeatures = 100
noutputs = 10
nhiddens = 50
rng = np.random.RandomState(0)
x = T.dmatrix('x')
wh = th.shared(rng.normal(0, 1, (nfeatures, nhiddens)), borrow=True)
bh = th.shared(np.zeros(nhiddens), borrow=True)
h = T.nnet.sigmoid(T.dot(x, wh) + bh)
wy = th.shared(rng.normal(0, 1, (nhiddens, noutputs)))
by = th.shared(np.zeros(noutputs), borrow=True)
y = T.nnet.softmax(T.dot(h, wy) + by)
predict = th.function([x], y)
The function ``predict`` outputs the probability of 10 classes. You can
visualize it with :py:func:`theano.printing.pydotprint` as follows:
.. code:: python
from theano.printing import pydotprint
import os
if not os.path.exists('examples'):
os.makedirs('examples')
pydotprint(predict, 'examples/mlp.png')
.. parsed-literal::
The output file is available at examples/mlp.png
.. code:: python
from IPython.display import Image
Image('./examples/mlp.png', width='80%')
.. image:: index_files/index_10_0.png
To visualize it interactively, import :py:func:`theano.d3viz.d3viz.d3viz` from
the the :py:mod:`theano.d3viz.d3viz` module, which can be called as before:
.. code:: python
import theano.d3viz as d3v
d3v.d3viz(predict, 'examples/mlp.html')
`open <./examples/mlp.html>`__
When you open the output file ``mlp.html`` in your web-browser, you will
see an interactive visualization of the compute graph. You can move the
whole graph or single nodes via drag and drop, and zoom via the mouse
wheel. When you move the mouse cursor over a node, a window will pop up
that displays detailed information about the node, such as its data type
or definition in the source code. When you left-click on a node and
select ``Edit``, you can change the predefined node label. If you are
dealing with a complex graph with many nodes, the default node layout
may not be perfect. In this case, you can press the ``Release node``
button in the top-left corner to automatically arrange nodes. To reset
nodes to their default position, press the ``Reset nodes`` button.
Profiling
---------
Theano allows `function
profiling <http://deeplearning.net/software/theano/tutorial/profiling.html>`__
via the ``profile=True`` flag. After at least one function call, the
compute time of each node can be printed in text form with
``debugprint``. However, analyzing complex graphs in this way can be
cumbersome.
``d3viz`` can visualize the same timing information graphically, and
hence help to spot bottlenecks in the compute graph more easily! To
begin with, we will redefine the ``predict`` function, this time by
using ``profile=True`` flag. Afterwards, we capture the runtime on
random data:
.. code:: python
predict_profiled = th.function([x], y, profile=True)
x_val = rng.normal(0, 1, (ninputs, nfeatures))
y_val = predict_profiled(x_val)
.. code:: python
d3v.d3viz(predict_profiled, 'examples/mlp2.html')
`open <./examples/mlp2.html>`__
When you open the HTML file in your browser, you will find an additional
``Toggle profile colors`` button in the menu bar. By clicking on it,
nodes will be colored by their compute time, where red corresponds to a
high compute time. You can read out the exact timing information of a
node by moving the cursor over it.
Different output formats
------------------------
Internally, ``d3viz`` represents a compute graph in the `Graphviz DOT
language <http://www.graphviz.org/>`__, using the
`pydot <https://pypi.python.org/pypi/pydot>`__ package, and defines a
front-end based on the `d3.js <http://d3js.org/>`__ library to visualize
it. However, any other Graphviz front-end can be used, which allows to
export graphs to different formats.
.. code:: python
formatter = d3v.formatting.PyDotFormatter()
pydot_graph = formatter(predict_profiled)
pydot_graph.write_png('examples/mlp2.png');
pydot_graph.write_png('examples/mlp2.pdf');
.. code:: python
Image('./examples/mlp2.png')
.. image:: index_files/index_24_0.png
Here, we used the :py:class:`theano.d3viz.formatting.PyDotFormatter` class to
convert the compute graph into a ``pydot`` graph, and created a PNG and PDF
file. You can find all output formats supported by Graphviz `here
<http://www.graphviz.org/doc/info/output.html>`__.
OpFromGraph nodes
-----------------
An
`OpFromGraph <http://deeplearning.net/software/theano/library/compile/opfromgraph.html>`__
node defines a new operation, which can be called with different inputs
at different places in the compute graph. Each ``OpFromGraph`` node
defines a nested graph, which will be visualized accordingly by
``d3viz``.
.. code:: python
x, y, z = T.scalars('xyz')
e = T.nnet.sigmoid((x + y + z)**2)
op = th.OpFromGraph([x, y, z], [e])
e2 = op(x, y, z) + op(z, y, x)
f = th.function([x, y, z], e2)
.. code:: python
d3v.d3viz(f, 'examples/ofg.html')
`open <./examples/ofg.html>`__
In this example, an operation with three inputs is defined, which is
used to build a function that calls this operations twice, each time
with different input arguments.
In the ``d3viz`` visualization, you will find two OpFromGraph nodes,
which correspond to the two OpFromGraph calls. When you double click on
one of them, the nested graph appears with the correct mapping of its
input arguments. You can move it around by drag and drop in the shaded
area, and close it again by double-click.
An OpFromGraph operation can be composed of further OpFromGraph
operations, which will be visualized as nested graphs as you can see in
the following example.
.. code:: python
x, y, z = T.scalars('xyz')
e = x * y
op = th.OpFromGraph([x, y], [e])
e2 = op(x, y) + z
op2 = th.OpFromGraph([x, y, z], [e2])
e3 = op2(x, y, z) + z
f = th.function([x, y, z], [e3])
.. code:: python
d3v.d3viz(f, 'examples/ofg2.html')
`open <./examples/ofg2.html>`__
Feedback
--------
If you have any problems or great ideas on how to improve ``d3viz``,
please let me know!
- Christof Angermueller
- cangermueller@gmail.com
- http://cangermueller.com
References
==========
d3viz module
------------
.. automodule:: theano.d3viz.d3viz
:members:
PyDotFormatter
--------------
.. autoclass:: theano.d3viz.formatting.PyDotFormatter
:members: __call__
:special-members:
:private-members:
theano/d3viz/css/d3viz.css
浏览文件 @
b682ae60
...
@@ -4,7 +4,7 @@ svg {
...
@@ -4,7 +4,7 @@ svg {
display
:
block
;
display
:
block
;
position
:
fixed
;
position
:
fixed
;
border
:
0px
solid
black
;
border
:
0px
solid
black
;
top
:
32px
;
left
:
0%
;
right
:
0%
bottom
=
0%
top
:
32px
;
left
:
0%
;
right
:
0%
;
bottom
:
0%
;
}
}
.menuBar
{
.menuBar
{
...
...
theano/d3viz/d3viz.py
浏览文件 @
b682ae60
...
@@ -6,6 +6,7 @@ Author: Christof Angermueller <cangermueller@gmail.com>
...
@@ -6,6 +6,7 @@ Author: Christof Angermueller <cangermueller@gmail.com>
import
os
import
os
import
os.path
as
pt
import
os.path
as
pt
import
shutil
import
shutil
import
re
from
formatting
import
PyDotFormatter
from
formatting
import
PyDotFormatter
...
@@ -13,17 +14,16 @@ __path__ = pt.dirname(pt.realpath(__file__))
...
@@ -13,17 +14,16 @@ __path__ = pt.dirname(pt.realpath(__file__))
def
replace_patterns
(
x
,
replace
):
def
replace_patterns
(
x
,
replace
):
"""
Replace patterns `replace` in x."""
"""Replace patterns `replace` in x."""
for
from_
,
to
in
replace
.
items
():
for
from_
,
to
in
replace
.
items
():
x
=
x
.
replace
(
str
(
from_
),
str
(
to
))
x
=
x
.
replace
(
str
(
from_
),
str
(
to
))
return
x
return
x
def
d3write
(
fct
,
path
,
*
args
,
**
kwargs
):
def
escape_quotes
(
s
):
"""Convert Theano graph to pydot graph and write to file."""
"""Escape quotes in string."""
gf
=
PyDotFormatter
(
*
args
,
**
kwargs
)
s
=
re
.
sub
(
r'''(['"])'''
,
r'\\\1'
,
s
)
g
=
gf
(
fct
)
return
s
g
.
write_dot
(
path
)
def
d3viz
(
fct
,
outfile
,
copy_deps
=
True
,
*
args
,
**
kwargs
):
def
d3viz
(
fct
,
outfile
,
copy_deps
=
True
,
*
args
,
**
kwargs
):
...
@@ -50,20 +50,23 @@ def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):
...
@@ -50,20 +50,23 @@ def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):
edge will be red.
edge will be red.
"""
"""
# Create DOT graph
formatter
=
PyDotFormatter
(
*
args
,
**
kwargs
)
graph
=
formatter
(
fct
)
dot_graph
=
escape_quotes
(
graph
.
create_dot
())
.
replace
(
'
\n
'
,
''
)
# Create output directory if not existing
outdir
=
pt
.
dirname
(
outfile
)
outdir
=
pt
.
dirname
(
outfile
)
if
not
pt
.
exists
(
outdir
):
if
not
pt
.
exists
(
outdir
):
os
.
makedirs
(
outdir
)
os
.
makedirs
(
outdir
)
# Create dot file
dot_file
=
pt
.
splitext
(
outfile
)[
0
]
+
'.dot'
d3write
(
fct
,
dot_file
,
*
args
,
**
kwargs
)
# Read template HTML file
# Read template HTML file
template_file
=
pt
.
join
(
__path__
,
'html'
,
'template.html'
)
template_file
=
pt
.
join
(
__path__
,
'html'
,
'template.html'
)
f
=
open
(
template_file
)
f
=
open
(
template_file
)
template
=
f
.
read
()
template
=
f
.
read
()
f
.
close
()
f
.
close
()
# Copy dependencies to output directory
src_deps
=
__path__
src_deps
=
__path__
if
copy_deps
:
if
copy_deps
:
dst_deps
=
'd3viz'
dst_deps
=
'd3viz'
...
@@ -78,7 +81,7 @@ def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):
...
@@ -78,7 +81,7 @@ def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):
replace
=
{
replace
=
{
'
%%
JS_DIR
%%
'
:
pt
.
join
(
dst_deps
,
'js'
),
'
%%
JS_DIR
%%
'
:
pt
.
join
(
dst_deps
,
'js'
),
'
%%
CSS_DIR
%%
'
:
pt
.
join
(
dst_deps
,
'css'
),
'
%%
CSS_DIR
%%
'
:
pt
.
join
(
dst_deps
,
'css'
),
'
%%
DOT_
FILE
%%
'
:
pt
.
basename
(
dot_file
),
'
%%
DOT_
GRAPH
%%
'
:
pt
.
basename
(
dot_graph
),
}
}
html
=
replace_patterns
(
template
,
replace
)
html
=
replace_patterns
(
template
,
replace
)
...
@@ -87,3 +90,10 @@ def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):
...
@@ -87,3 +90,10 @@ def d3viz(fct, outfile, copy_deps=True, *args, **kwargs):
f
=
open
(
outfile
,
'w'
)
f
=
open
(
outfile
,
'w'
)
f
.
write
(
html
)
f
.
write
(
html
)
f
.
close
()
f
.
close
()
def
d3write
(
fct
,
path
,
*
args
,
**
kwargs
):
"""Convert Theano graph to pydot graph and write to file."""
formatter
=
PyDotFormatter
(
*
args
,
**
kwargs
)
graph
=
formatter
(
fct
)
graph
.
write_dot
(
path
)
theano/d3viz/html/template.html
浏览文件 @
b682ae60
...
@@ -22,10 +22,8 @@
...
@@ -22,10 +22,8 @@
</div>
</div>
<script
type=
"text/javascript"
>
<script
type=
"text/javascript"
>
// Path to DOT file
var
path
=
'%% DOT_FILE %%'
;
// '%% DOT_FILE %%';
// Backend graph in DOT format
// Backend graph in DOT format
var
dotGraph
;
var
dotGraph
=
graphlibDot
.
read
(
"%% DOT_GRAPH %%"
)
;
// Frontend graph for visualization
// Frontend graph for visualization
var
graph
=
{};
var
graph
=
{};
...
@@ -98,13 +96,10 @@
...
@@ -98,13 +96,10 @@
.
attr
(
"d"
,
"M0,0 L4,2 L0,4 Z"
)
.
attr
(
"d"
,
"M0,0 L4,2 L0,4 Z"
)
.
attr
(
'fill'
,
function
(
d
)
{
return
d
.
color
;});
.
attr
(
'fill'
,
function
(
d
)
{
return
d
.
color
;});
// Read and initialize graph
// Initialize graph
d3
.
text
(
path
,
function
(
data
)
{
processDotGraph
(
dotGraph
);
dotGraph
=
graphlibDot
.
read
(
data
);
graph
=
frontEndGraph
(
dotGraph
);
processDotGraph
(
dotGraph
);
drawGraph
();
graph
=
frontEndGraph
(
dotGraph
);
drawGraph
();
});
</script>
</script>
</body>
</body>
</html>
</html>
theano/d3viz/js/d3viz.js
浏览文件 @
b682ae60
...
@@ -68,7 +68,7 @@ function processDotGraph(dotGraph) {
...
@@ -68,7 +68,7 @@ function processDotGraph(dotGraph) {
for
(
var
nodeId
in
dotGraph
.
_nodes
)
{
for
(
var
nodeId
in
dotGraph
.
_nodes
)
{
var
node
=
dotGraph
.
_nodes
[
nodeId
];
var
node
=
dotGraph
.
_nodes
[
nodeId
];
node
.
id
=
nodeId
;
node
.
id
=
nodeId
;
node
.
isCluster
=
nodeId
.
s
tartsWith
(
'cluster'
)
;
node
.
isCluster
=
nodeId
.
s
ubstr
(
0
,
7
)
==
'cluster'
;
if
(
!
node
.
isCluster
)
{
if
(
!
node
.
isCluster
)
{
dotGraph
.
rnodes
[
nodeId
]
=
node
;
dotGraph
.
rnodes
[
nodeId
]
=
node
;
}
}
...
...
theano/d3viz/tests/test_d3viz.py
浏览文件 @
b682ae60
...
@@ -15,10 +15,8 @@ class TestD3Viz(unittest.TestCase):
...
@@ -15,10 +15,8 @@ class TestD3Viz(unittest.TestCase):
def
check
(
self
,
f
):
def
check
(
self
,
f
):
_
,
html_file
=
mkstemp
(
'.html'
)
_
,
html_file
=
mkstemp
(
'.html'
)
dot_file
=
html_file
.
replace
(
'.html'
,
'.dot'
)
d3v
.
d3viz
(
f
,
html_file
)
d3v
.
d3viz
(
f
,
html_file
)
assert
pt
.
getsize
(
html_file
)
>
0
assert
pt
.
getsize
(
html_file
)
>
0
assert
pt
.
getsize
(
dot_file
)
>
0
def
test_mlp
(
self
):
def
test_mlp
(
self
):
m
=
models
.
Mlp
(
rng
=
self
.
rng
)
m
=
models
.
Mlp
(
rng
=
self
.
rng
)
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论