Merge pull request #11 from pedrodiamel/master

python interface
This commit is contained in:
Haris Iqbal
2019-02-11 10:05:57 +01:00
committed by GitHub
8 changed files with 488 additions and 1 deletions
+82
View File
@@ -1,3 +1,85 @@
*.aux *.aux
*.log *.log
*.gz *.gz
__pycache__
books
project
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
+45 -1
View File
@@ -1,7 +1,51 @@
# PlotNeuralNet # PlotNeuralNet
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.2526396.svg)](https://doi.org/10.5281/zenodo.2526396) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.2526396.svg)](https://doi.org/10.5281/zenodo.2526396)
Latex code for drawing neural networks for reports and presentation. Have a look into examples to see how they are made. Additionally, lets consolidate any improvements that you make and fix any bugs to help more people with this code. Latex code for drawing neural networks for reports and presentation. Have a look into examples to see how they are made. Additionally, lets consolidate any improvements that you make and fix any bugs to help more people with this code.
## TODO
- [X] Python interfaz
- [ ] Generate Pytorch graph architecture
- [ ] Add easy legend functionality
- [ ] Add more layer shapes like TruncatedPyramid, 2DSheet etc
## Usage
mkdir my_project
cd my_project
vim my_arch.py
import sys
sys.path.append('../')
from core.tikzeng import *
# defined your arch
arch = [
to_head( '..' ),
to_cor(),
to_begin(),
to_Conv("conv1", 512, 64, offset="(0,0,0)", to="(0,0,0)", height=64, depth=64, width=2 ),
to_Pool("pool1", offset="(0,0,0)", to="(conv1-east)"),
to_Conv("conv2", 128, 64, offset="(1,0,0)", to="(pool1-east)", height=32, depth=32, width=2 ),
to_connection( "pool1", "conv2"),
to_Pool("pool2", offset="(0,0,0)", to="(conv2-east)", height=28, depth=28, width=1),
to_SoftMax("soft1", 10 ,"(3,0,0)", "(pool1-east)", caption="SOFT" ),
to_connection("pool2", "soft1"),
to_end()
]
def main():
namefile = str(sys.argv[0]).split('.')[0]
to_generate(arch, namefile + '.tex' )
if __name__ == '__main__':
main()
bash ../tikzmake.sh my_arch
## Examples
Following are some network representations: Following are some network representations:
<p align="center"><img src="https://user-images.githubusercontent.com/17570785/50308846-c2231880-049c-11e9-8763-3daa1024de78.png" width="85%" height="85%"></p> <p align="center"><img src="https://user-images.githubusercontent.com/17570785/50308846-c2231880-049c-11e9-8763-3daa1024de78.png" width="85%" height="85%"></p>
View File
+75
View File
@@ -0,0 +1,75 @@
from .tikzeng import *
#define new block
def block_2ConvPool( name, botton, top, s_filer=256, n_filer=64, offset="(1,0,0)", size=(32,32,3.5), opacity=0.5 ):
return [
to_ConvConvRelu(
name="ccr_{}".format( name ),
s_filer=str(s_filer),
n_filer=(n_filer,n_filer),
offset=offset,
to="({}-east)".format( botton ),
width=(size[2],size[2]),
height=size[0],
depth=size[1],
),
to_Pool(
name="{}".format( top ),
offset="(0,0,0)",
to="(ccr_{}-east)".format( name ),
width=1,
height=size[0] - int(size[0]/4),
depth=size[1] - int(size[0]/4),
opacity=opacity, ),
to_connection(
"{}".format( botton ),
"ccr_{}".format( name )
)
]
def block_Unconv( name, botton, top, s_filer=256, n_filer=64, offset="(1,0,0)", size=(32,32,3.5), opacity=0.5 ):
return [
to_UnPool( name='unpool_{}'.format(name), offset=offset, to="({}-east)".format(botton), width=1, height=size[0], depth=size[1], opacity=opacity ),
to_ConvRes( name='ccr_res_{}'.format(name), offset="(0,0,0)", to="(unpool_{}-east)".format(name), s_filer=str(s_filer), n_filer=str(n_filer), width=size[2], height=size[0], depth=size[1], opacity=opacity ),
to_Conv( name='ccr_{}'.format(name), offset="(0,0,0)", to="(ccr_res_{}-east)".format(name), s_filer=str(s_filer), n_filer=str(n_filer), width=size[2], height=size[0], depth=size[1] ),
to_ConvRes( name='ccr_res_c_{}'.format(name), offset="(0,0,0)", to="(ccr_{}-east)".format(name), s_filer=str(s_filer), n_filer=str(n_filer), width=size[2], height=size[0], depth=size[1], opacity=opacity ),
to_Conv( name='{}'.format(top), offset="(0,0,0)", to="(ccr_res_c_{}-east)".format(name), s_filer=str(s_filer), n_filer=str(n_filer), width=size[2], height=size[0], depth=size[1] ),
to_connection(
"{}".format( botton ),
"unpool_{}".format( name )
)
]
def block_Res( num, name, botton, top, s_filer=256, n_filer=64, offset="(0,0,0)", size=(32,32,3.5), opacity=0.5 ):
lys = []
layers = [ *[ '{}_{}'.format(name,i) for i in range(num-1) ], top]
for name in layers:
ly = [ to_Conv(
name='{}'.format(name),
offset=offset,
to="({}-east)".format( botton ),
s_filer=str(s_filer),
n_filer=str(n_filer),
width=size[2],
height=size[0],
depth=size[1]
),
to_connection(
"{}".format( botton ),
"{}".format( name )
)
]
botton = name
lys+=ly
lys += [
to_skip( of=layers[1], to=layers[-2], pos=1.25),
]
return lys
+197
View File
@@ -0,0 +1,197 @@
import os
def to_head( projectpath ):
pathlayers = os.path.join( projectpath, 'layers/' )
return r"""
\documentclass[border=8pt, multi, tikz]{standalone}
\usepackage{import}
\subimport{"""+ pathlayers + r"""}{init}
\usetikzlibrary{positioning}
\usetikzlibrary{3d} %for including external image
"""
def to_cor():
return r"""
\def\ConvColor{rgb:yellow,5;red,2.5;white,5}
\def\ConvReluColor{rgb:yellow,5;red,5;white,5}
\def\PoolColor{rgb:red,1;black,0.3}
\def\UnpoolColor{rgb:blue,2;green,1;black,0.3}
\def\FcColor{rgb:blue,5;red,2.5;white,5}
\def\FcReluColor{rgb:blue,5;red,5;white,4}
\def\SoftmaxColor{rgb:magenta,5;black,7}
"""
def to_begin():
return r"""
\newcommand{\copymidarrow}{\tikz \draw[-Stealth,line width=0.8mm,draw={rgb:blue,4;red,1;green,1;black,3}] (-0.3,0) -- ++(0.3,0);}
\begin{document}
\begin{tikzpicture}
\tikzstyle{connection}=[ultra thick,every node/.style={sloped,allow upside down},draw=\edgecolor,opacity=0.7]
\tikzstyle{copyconnection}=[ultra thick,every node/.style={sloped,allow upside down},draw={rgb:blue,4;red,1;green,1;black,3},opacity=0.7]
"""
# layers definition
def to_input( pathfile, to='(-3,0,0)', width=8, height=8 ):
return r"""
\node[canvas is zy plane at x=0] (temp) at """+ to +""" {\includegraphics[width="""+ str(width)+"cm"+""",height="""+ str(height)+"cm"+"""]{"""+ pathfile +"""}};
"""
# Conv
def to_Conv( name, s_filer=256, n_filer=64, offset="(0,0,0)", to="(0,0,0)", width=1, height=40, depth=40, caption=" " ):
return r"""
\pic[shift={"""+ offset +"""}] at """+ to +"""
{Box={
name=""" + name +""",
caption="""+ caption +r""",
xlabel={{"""+ str(n_filer) +""", }},
zlabel="""+ str(s_filer) +""",
fill=\ConvColor,
height="""+ str(height) +""",
width="""+ str(width) +""",
depth="""+ str(depth) +"""
}
};
"""
# Conv,Conv,relu
# Bottleneck
def to_ConvConvRelu( name, s_filer=256, n_filer=(64,64), offset="(0,0,0)", to="(0,0,0)", width=(2,2), height=40, depth=40, caption=" " ):
return r"""
\pic[shift={ """+ offset +""" }] at """+ to +"""
{RightBandedBox={
name="""+ name +""",
caption="""+ caption +""",
xlabel={{ """+ str(n_filer[0]) +""", """+ str(n_filer[1]) +""" }},
zlabel="""+ str(s_filer) +""",
fill=\ConvColor,
bandfill=\ConvReluColor,
height="""+ str(height) +""",
width={ """+ str(width[0]) +""" , """+ str(width[1]) +""" },
depth="""+ str(depth) +"""
}
};
"""
# Pool
def to_Pool(name, offset="(0,0,0)", to="(0,0,0)", width=1, height=32, depth=32, opacity=0.5, caption=" "):
return r"""
\pic[shift={ """+ offset +""" }] at """+ to +"""
{Box={
name="""+name+""",
caption="""+ caption +r""",
fill=\PoolColor,
opacity="""+ str(opacity) +""",
height="""+ str(height) +""",
width="""+ str(width) +""",
depth="""+ str(depth) +"""
}
};
"""
# unpool4,
def to_UnPool(name, offset="(0,0,0)", to="(0,0,0)", width=1, height=32, depth=32, opacity=0.5, caption=" "):
return r"""
\pic[shift={ """+ offset +""" }] at """+ to +"""
{Box={
name="""+ name +r""",
caption="""+ caption +r""",
fill=\UnpoolColor,
opacity="""+ str(opacity) +""",
height="""+ str(height) +""",
width="""+ str(width) +""",
depth="""+ str(depth) +"""
}
};
"""
def to_ConvRes( name, s_filer=256, n_filer=64, offset="(0,0,0)", to="(0,0,0)", width=6, height=40, depth=40, opacity=0.2, caption=" " ):
return r"""
\pic[shift={ """+ offset +""" }] at """+ to +"""
{RightBandedBox={
name="""+ name + """,
caption="""+ caption + """,
xlabel={{ """+ str(n_filer) + """, }},
zlabel="""+ str(s_filer) +r""",
fill={rgb:white,1;black,3},
bandfill={rgb:white,1;black,2},
opacity="""+ str(opacity) +""",
height="""+ str(height) +""",
width="""+ str(width) +""",
depth="""+ str(depth) +"""
}
};
"""
# ConvSoftMax
def to_ConvSoftMax( name, s_filer=40, offset="(0,0,0)", to="(0,0,0)", width=1, height=40, depth=40, caption=" " ):
return r"""
\pic[shift={"""+ offset +"""}] at """+ to +"""
{Box={
name=""" + name +""",
caption="""+ caption +""",
zlabel="""+ str(s_filer) +""",
fill=\SoftmaxColor,
height="""+ str(height) +""",
width="""+ str(width) +""",
depth="""+ str(depth) +"""
}
};
"""
# SoftMax
def to_SoftMax( name, s_filer=10, offset="(0,0,0)", to="(0,0,0)", width=1.5, height=3, depth=25, opacity=0.8, caption=" " ):
return r"""
\pic[shift={"""+ offset +"""}] at """+ to +"""
{Box={
name=""" + name +""",
caption="""+ caption +""",
xlabel={{" ","dummy"}},
zlabel="""+ str(s_filer) +""",
fill=\SoftmaxColor,
opacity="""+ str(opacity) +""",
height="""+ str(height) +""",
width="""+ str(width) +""",
depth="""+ str(depth) +"""
}
};
"""
def to_connection( of, to):
return r"""
\draw [connection] ("""+of+"""-east) -- node {\midarrow} ("""+to+"""-west);
"""
def to_skip( of, to, pos=1.25):
return r"""
\path ("""+ of +"""-southeast) -- ("""+ of +"""-northeast) coordinate[pos="""+ str(pos) +"""] ("""+ of +"""-top) ;
\path ("""+ to +"""-south) -- ("""+ to +"""-north) coordinate[pos=1.25] ("""+ to +"""-top) ;
\draw [copyconnection] ("""+of+"""-northeast)
-- node {\copymidarrow}("""+of+"""-top)
-- node {\copymidarrow}("""+to+"""-top)
-- node {\copymidarrow} ("""+to+"""-north);
"""
def to_end():
return r"""
\end{tikzpicture}
\end{document}
"""
def to_generate( arch, pathname="file.tex" ):
with open(pathname, "w") as f:
for c in arch:
print(c)
f.write( c )
+26
View File
@@ -0,0 +1,26 @@
import sys
sys.path.append('../')
from core.tikzeng import *
# defined your arch
arch = [
to_head( '..' ),
to_cor(),
to_begin(),
to_Conv("conv1", 512, 64, offset="(0,0,0)", to="(0,0,0)", height=64, depth=64, width=2 ),
to_Pool("pool1", offset="(0,0,0)", to="(conv1-east)"),
to_Conv("conv2", 128, 64, offset="(1,0,0)", to="(pool1-east)", height=32, depth=32, width=2 ),
to_connection( "pool1", "conv2"),
to_Pool("pool2", offset="(0,0,0)", to="(conv2-east)", height=28, depth=28, width=1),
to_SoftMax("soft1", 10 ,"(3,0,0)", "(pool1-east)", caption="SOFT" ),
to_connection("pool2", "soft1"),
to_end()
]
def main():
namefile = str(sys.argv[0]).split('.')[0]
to_generate(arch, namefile + '.tex' )
if __name__ == '__main__':
main()
+52
View File
@@ -0,0 +1,52 @@
import sys
sys.path.append('../')
from core.tikzeng import *
from core.blocks import *
arch = [
to_head('..'),
to_cor(),
to_begin(),
#input
to_input( '../examples/fcn8s/cats.jpg' ),
#block-001
to_ConvConvRelu( name='ccr_b1', s_filer=500, n_filer=(64,64), offset="(0,0,0)", to="(0,0,0)", width=(2,2), height=40, depth=40 ),
to_Pool(name="pool_b1", offset="(0,0,0)", to="(ccr_b1-east)", width=1, height=32, depth=32, opacity=0.5),
*block_2ConvPool( name='b2', botton='pool_b1', top='pool_b2', s_filer=256, n_filer=128, offset="(1,0,0)", size=(32,32,3.5), opacity=0.5 ),
*block_2ConvPool( name='b3', botton='pool_b2', top='pool_b3', s_filer=128, n_filer=256, offset="(1,0,0)", size=(25,25,4.5), opacity=0.5 ),
*block_2ConvPool( name='b4', botton='pool_b3', top='pool_b4', s_filer=64, n_filer=512, offset="(1,0,0)", size=(16,16,5.5), opacity=0.5 ),
#Bottleneck
#block-005
to_ConvConvRelu( name='ccr_b5', s_filer=32, n_filer=(1024,1024), offset="(2,0,0)", to="(pool_b4-east)", width=(8,8), height=8, depth=8, caption="Bottleneck" ),
to_connection( "pool_b4", "ccr_b5"),
#Decoder
*block_Unconv( name="b6", botton="ccr_b5", top='end_b6', s_filer=64, n_filer=512, offset="(2.1,0,0)", size=(16,16,5.0), opacity=0.5 ),
to_skip( of='ccr_b4', to='ccr_res_b6', pos=1.25),
*block_Unconv( name="b7", botton="end_b6", top='end_b7', s_filer=128, n_filer=256, offset="(2.1,0,0)", size=(25,25,4.5), opacity=0.5 ),
to_skip( of='ccr_b3', to='ccr_res_b7', pos=1.25),
*block_Unconv( name="b8", botton="end_b7", top='end_b8', s_filer=256, n_filer=128, offset="(2.1,0,0)", size=(32,32,3.5), opacity=0.5 ),
to_skip( of='ccr_b2', to='ccr_res_b8', pos=1.25),
*block_Unconv( name="b9", botton="end_b8", top='end_b9', s_filer=512, n_filer=64, offset="(2.1,0,0)", size=(40,40,2.5), opacity=0.5 ),
to_skip( of='ccr_b1', to='ccr_res_b9', pos=1.25),
to_ConvSoftMax( name="soft1", s_filer=512, offset="(0.75,0,0)", to="(end_b9-east)", width=1, height=40, depth=40, caption="SOFT" ),
to_connection( "end_b9", "soft1"),
to_end()
]
def main():
namefile = str(sys.argv[0]).split('.')[0]
to_generate(arch, namefile + '.tex' )
if __name__ == '__main__':
main()
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
python $1.py
pdflatex $1.tex
rm *.aux *.log *.vscodeLog
rm *.tex
evince $1.pdf