# Customizing the hidden layer (number of nodes, color, connection) with TikZ

I am a new user of TikZ and seeking help with this. I am trying to draw an autoassoicative neural network as illustrated in the figure below in terms of number of units and label with each layer fully connected to the one after.

Im stuck . I couldn't figure how to specify each hidden layer seperately. It ends up over-writing the hidden layer specs and fully connecting to the last hidden layer while the others remain unconnected as shown below.

Here is the code:

    \documentclass[border=0.125cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}

\tikzset{%
neuron missing/.style={
draw=none,
scale=2,
text height=0.333cm,
execute at begin node=\color{black}$\vdots$
},
}

\begin{tikzpicture}[x=1.5cm, y=1.5cm, >=stealth]

\newcommand\Nhidden{3}

% First three nodes in Input Layer
\foreach \m/\l [count=\y] in {1,2,3}
{
\node [circle,fill=green!50,minimum size=1cm] (input-\m) at (0,2.5-\y) {};
}
% Last  node in Input Layer
\foreach \m/\l [count=\y] in {4}
{
\node [circle,fill=green!50,minimum size=1cm ] (input-\m) at (0,-2.5) {};
}
% The missing nodes in Input Layer
\node [neuron missing]  at (0,-1.5) {};

%%%%%%

% First  node in Hidden Layer#1 (Mapping)
\foreach \m [count=\y] in {1,2,3,4,5,6}
\node [circle,fill=red!50,minimum size=1cm ] (hidden-\m) at (2,0.75) {};

% Last  node in Hidden Layer#1 (Mapping)
\foreach \m [count=\y] in {7}
\node [circle,fill=red!50,minimum size=1cm ] (hidden-\m) at (2,-1.85) {};

% The missing nodes in Hidden Layer#1 (Mapping)
\node [neuron missing]  at (2,-0.3) {};

%%%%%%%

% First  node in Hidden Layer#2 (Bottleneck)
\foreach \m [count=\y] in {1}
\node [circle,fill=blue!50,minimum size=1cm ] (hidden-\m) at (4,1.5-\y) {};

% Last  node in Hidden Layer#2 (Bottleneck)
\foreach \m [count=\y] in {2}
\node [circle,fill=blue!50,minimum size=1cm ] (hidden-\m) at (4,-0.5-\y) {};

% The missing  nodes in Hidden Layer#2 (Bottleneck)
\node [neuron missing]  at (4,-0.4) {};

%%%%%%%
% First  node in Hidden Layer#3 (De-Mapping)
\foreach \m [count=\y] in {1,2,3,4,5,6}
\node [circle,fill=red!50,minimum size=1cm ] (hidden-\m) at (6,0.75) {};

% Last  node in Hidden Layer#3 (De-Mapping)
\foreach \m [count=\y] in {7}
\node [circle,fill=red!50,minimum size=1cm ] (hidden-\m) at (6,-1.85) {};

% The missing nodes in Hidden Layer#1 (De-Mapping)
\node [neuron missing]  at (6,-0.3) {};

%%%%%%%

% First three nodes in Output Layer
\foreach \m/\l [count=\y] in {1,2,3}
{
\node [circle,fill=green!50,minimum size=1cm] (output-\m) at (8,2.5-\y) {};
}
% Last  node in Output Layer
\foreach \m/\l [count=\y] in {4}
{
\node [circle,fill=green!50,minimum size=1cm ] (output-\m) at (8,-2.5) {};
}
% The missing nodes in Output Layer
\node [neuron missing]  at (8,-1.5) {};

%%%%%%%%%%------------------------------------

\foreach \l [count=\i] in {1,2,3,n}
\draw [<-] (input-\i) -- ++(-1,0)
node [above, midway] {$X_{\l}$};

\foreach \N in {1,...,\Nhidden} {
\foreach \l [count=\i] in {1,2,3,4,5,6,k}
\node [above] at (hidden-\i.north) {$H_{m\l}$};

\foreach \l [count=\i] in {1,f}
\draw [->] (hidden-\i) -- ++(1,0)
node [above, midway] {$T_{ \l}$};

\foreach \l [count=\i] in {1,2,3,4,5,6,k}
\node [above] at (hidden-\i.north) {$H_{d\l}$};
}
\foreach \l [count=\i] in {1,2,3,n}
\draw [->] (output-\i) -- ++(1,0)
node [above, midway] {$Y_{\l}$};

\foreach \i in {1,...,4}
\foreach \j in {1,...,7}
\draw [->] (input-\i) -- (hidden-\j);

\foreach \i in {1,...,7}
\foreach \j in {1,...,4}
\draw [->] (hidden-\i) -- (output-\j);

\end{tikzpicture}

\end{document}


I really appricate your help. Thank you.

• Please refer to the original source tex.stackexchange.com/questions/362238 if that's the case. Jun 13 '18 at 1:36
• @Dr.ManuelKuehner I found an even earlier code here. Seems like in this business people do not like to disclose the source of their codes. I do not understand this since this would lead to better answers...
– user121799
Jun 13 '18 at 2:28
• @Dr.ManuelKuehner and marmot,This is the first time I use TikZ and I was trying to learn how to use it to draw my network. I checked many source codes on the internet so by the time I posted this I didn't pay attention to referring to the original source. However, since you requested it, I looked it up and here it is, the source code I was trying to modify, overleaf.com/latex/examples/neural-network-color/…. I learn from my mistakes. Thank you all for your advice and help. Jun 13 '18 at 8:18
• @marmot ^^^^^^^ Jun 13 '18 at 8:19

Well, that happens if someone writes a nice code and others extend it without knowing what they are doing. If everyone in that chain would reveal the source of the code, this exercise would not become so painful. In particular, I would have found Torbjørn T.'s nice code much earlier. UPDATE: After some (devastating ;-) feedback from @J Leon V. and @Skillmon (thanks, BTW) I tried to structure the code a bit. Ah, and now everything is taken care of by a single macro, and layers also get labeled.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{positioning}
\begin{document}

\tikzset{%
neuron missing/.style={
draw=none,
scale=2,
text height=0.333cm,
execute at begin node=\color{black}$\vdots$
},
}

% The command \DrawNeuronalNetwork has a list as argument, each entry is a
% layer. each entry has the form
%  Layer name/number of nodes/color/missing node/label/symbolic number
% where
% * layer name is, well,  the name of the layer
% * number of nodes is the number of neurons in that layer (including the missing neuron)
% * color is the color of the layer
% * missing node denotes the index of the missing neuron
% * label denotes the label of the layer
% * symbolic number denotes the symbol that indicates how many neurons there are

\newcommand{\DrawNeuronalNetwork}[2][]{
\xdef\Xmax{0}
\foreach \Layer/\X/\Col/\Miss/\Lab/\Count [count=\Y] in {#2}
{\pgfmathsetmacro{\Xmax}{max(\X,\Xmax)}
\xdef\Xmax{\Xmax}
\xdef\Ymax{\Y}
}
\foreach \Layer/\X/\Col/\Miss/\Lab/\Count [count=\Y] in {#2}
{\node[anchor=south] at ({2*\Y},{\Xmax/2+0.1}) {\Layer};
\foreach \m in {1,...,\X}
{
\ifnum\m=\Miss
\node [neuron missing] (neuron-\Y-\m) at ({2*\Y},{\X/2-\m}) {};
\else
\node [circle,fill=\Col!50,minimum size=1cm] (neuron-\Y-\m) at
({2*\Y},{\X/2-\m}) {};
\ifnum\Y=1
\else
\pgfmathtruncatemacro{\LastY}{\Y-1}
\foreach \Z in {1,...,\LastX}
{
\ifnum\Z=\LastMiss
\else
\draw[->] (neuron-\LastY-\Z) -- (neuron-\Y-\m);
\fi
}
\fi
\fi
\ifnum\Y=1
\ifnum\m=\X
\draw [<-] (neuron-\Y-\m) -- ++(-1,0) node [above, midway] {$\Lab_{\Count}$};
\else
\ifnum\m=\Miss
\else
\draw [<-] (neuron-\Y-\m) -- ++(-1,0) node [above, midway] {$\Lab_{\m}$};
\fi
\fi
\else
\ifnum\Y=\Ymax
\ifnum\m=\X
\draw [->] (neuron-\Y-\m) -- ++(1,0) node [above, midway] {$\Lab_{\Count}$};
\else
\ifnum\m=\Miss
\else
\draw [->] (neuron-\Y-\m) -- ++(1,0) node [above, midway] {$\Lab_{\m}$};
\fi
\fi
\else
\ifnum\m=1
\node[above=0pt of neuron-\Y-\m] {$\Lab_1$};
\fi
\ifnum\m=\X
\node[below=0pt of neuron-\Y-\m] {$\Lab_{\Count}$};
\fi
\fi
\fi
}
\xdef\LastMiss{\Miss}
\xdef\LastX{\X}
}
}
\begin{tikzpicture}[x=1.5cm, y=1.5cm, >=stealth,font=\sffamily]
\DrawNeuronalNetwork{Input Layer/5/green/4/X/n,
Mapping Layer/7/red/4/H/k,
Bottleneck Layer/3/blue/2/T/f,
Demapping Layer/7/red/4/G/f,
Output Layer/5/green/4/Y/n}
\end{tikzpicture}
\end{document}


• +1 It is hightly automatized, but some obscure... im trying to understand the magic hidden in no structured code xD Jun 13 '18 at 0:02
• @JLeonV. OK, I tried to structure it and pack everything into one macro. It is still rather ugly since I do not know what the rules of the game are. It would be much nicer with pgf keys, but I am afraid to give them silly names and what is more important not do the right things, i.e. invent options for things that never happen and do not have options for things that do happen...
– user121799
Jun 13 '18 at 0:52
• @marmot Done. I'm sorry im new here. Thank you again. Jun 13 '18 at 7:57
• @marmot I labeled the layers using the following code , \foreach \l [count=\x from 0] in {Input, Mapping, Bottelneck, De-mapping, Ouput} \node [align=center, above] at (\x*2,3.5) {\l \\ layer}; Jun 13 '18 at 8:48