2

I would like to create a figure showing the structure of the critic in the DDPG environment, which consists of three connected neural networks. Here (TikZ: draw two Neural Networks side by side connected by a softmax layer) I found a suitable structure, which I wanted to adjust to my needs. However I fail at two points.

  • In the upper neural network I would like the first two hidden layers to include three dots indicating, that there are more neurons than actually on the figure. Additionally I need these two layers to appear bigger than the third hidden layer.
  • Behind the red layer on the right that connects both left networks I would like to include a output layer, that consists of a single neuron.

How do I accomplish this? Attached is the modified code and the figure so far.

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta, chains, graphs, ext.positioning-plus, ext.paths.ortho}
\ExplSyntaxOn \makeatletter % allowing matrices on chains
\tl_replace_once:Nnn \tikz@do@matrix@cont
  { \tikz@node@finish } { \tikz@alias \tikz@node@finish }
\makeatother \ExplSyntaxOff
\tikzset{
  node matrix/.style={
    row sep=y_node_dist, column sep=x_node_dist,
    every outer matrix/.append style={/pgf/inner sep=+0pt, /pgf/outer sep=+0pt, draw=none, fill=none, shape=rectangle},
    /utils/exec=\def\tikzmatrixnodecounter{\ifnum\pgfmatrixcurrentrow=1
      \the\pgfmatrixcurrentcolumn\else\the\pgfmatrixcurrentrow\fi},
    nodes/.style={node matrix/node/.append style={##1}}},
  node matrix/node/.style={
    node contents=, anchor=center, name/.expanded={\tikzmatrixname_\tikzmatrixnodecounter}},
  node matrix/place 1st node/.code args={#1,#2}{%
    \node[node matrix/node,nm \tikzmatrixnodecounter/.try,#1];},
  node matrix/place other nodes/.style args={#1,#2}{/tikz/node matrix/place oth node/.list={#2}},
  vertical   node matrix/.style={/tikz/node matrix/place oth node/.code={%
    \pgfmatrixendrow  \node[node matrix/node,nm \tikzmatrixnodecounter/.try,##1];}},
  horizontal node matrix/.style={/tikz/node matrix/place oth node/.code={%
    \pgfmatrixnextcell\node[node matrix/node,nm \tikzmatrixnodecounter/.try,##1];}}}
\newcommand*\tikzMatrixNodes[2][1]{%
  \matrix[every node matrix/.try,node matrix,#1]{
    \tikzset{node matrix/place 1st node={#2},node matrix/place other nodes={#2}}\\};}
\tikzset{
  color let/.code args={#1=#2}{\colorlet{#1}{#2}},
  color set/.style args={#1=#2/#3}{color let={#1fg=#2}, color let={#1bg=#3}},
  color use/.style={draw=#1bg, fill=#1fg}}

  
\begin{document}
\begin{tikzpicture}[
  >=Latex, thick, node distance=3mm and 10mm,
  layers/.style={circle, thick, draw, minimum size=+10mm, inner sep=+.1em},
  input/.style ={layers, color use=input},
  hidden/.style={layers, color use=hidden},
  output/.style={layers, color use=output},
  every node matrix/.style={vertical node matrix},
  every label/.append style={align=center},
  label distance=1mm,
  second to last/.style={
    nm #1/.style={node contents=\vdots, text height=2ex, fill=none, draw=none, minimum size=+0pt,inner sep=+0pt, shape=rectangle},
    row #1/.append style={row sep=.75*y_node_dist},
    row \pgfinteval{#1-1}/.append style={row sep=.75*y_node_dist}},
  color set/.list={input=green!60!black/green!30!black,
                   hidden=blue!50/blue,
                   output=red!80!black/red!40!black}
]
\begin{scope}[start chain=going right]
  \tikzMatrixNodes[
    label={[inputfg]input\\layer},
    on chain, second to last=4, name=input'top, % can't use chain name
    nodes={input, node contents=$Z_\tikzmatrixnodecounter$},
  ]{,,,,node contents=$Z_q$}
  
  \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain,  second to last=9, name=hidden'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}
  
    \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain,  second to last=10, name=hidden2'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}
  
      \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain,  second to last=5, name=hidden3'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}
  
  \tikzMatrixNodes[
    label={[outputfg]output\\layer},
    on chain,  second to last=3, name=output'top,
    nodes={output, node contents=$g_\tikzmatrixnodecounter$}
  ]{,,,node contents=$g_J$}


  
  \path[blue] graph[use existing nodes]{
                               {\foreach \x in {1,...,3,5} {input'top_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,5,6} {hidden'top_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,5,6} {hidden2'top_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,4,6} {hidden3'top_\x}}
       
       
       -- [complete bipartite] {\foreach \x in {1,2,4}     {output'top_\x}}
    };
\end{scope}
\begin{scope}[start chain=going right, yshift=-10.5cm]
  \tikzMatrixNodes[
    label={[inputfg]$q(s_1)$},
    on chain, second to last=4, name=input'bot, % can't use chain name
    nodes={input, node contents=$Z_\tikzmatrixnodecounter$},
  ]{,,,,node contents=$Z_q$}
  \tikzMatrixNodes[
    label={[hiddenfg]$w(s_1)$},
    on chain,  second to last=5, name=hidden'bot,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}

    \tikzMatrixNodes[
    label={[hiddenfg]$w(s_1)$},
    on chain,  second to last=5, name=hidden2'bot,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}
  
  \tikzMatrixNodes[
    label={[outputfg]$g(s_1)$},
    on chain,  second to last=3, name=output'bot,
    nodes={output, node contents=$g_\tikzmatrixnodecounter$}
  ]{,,,node contents=$g_J$}




  
  \path[yellow!50!black] graph[use existing nodes]{
                               {\foreach \x in {1,...,3,5} {input'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,4,6} {hidden'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,4,6} {hidden2'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,2,4}     {output'bot_\x}}
    };
\end{scope}

\tikzMatrixNodes[
  node distance=3mm and 20mm,
  right=of (output'top)(output'bot),
  second to last=3, name=output',
  nodes={output, node contents=$g_\tikzmatrixnodecounter$}
]{,,,node contents=$g_r$}

%single output neuron?

\graph[use existing nodes]{
  {\foreach \tb in {top, bot}{\foreach \x in {1,2,4}{output'\tb_\x}}}
  -- [complete bipartite]    {\foreach \x in {1,2,4}{output'_\x}}
};

\end{tikzpicture}
\end{document}

enter image description here

Here is a sketch of what I would like to change:

enter image description here

4
  • Where should the additional dots be in those two layers? They are added by the second to last key (which is a stupid name) where the value just specifies where the \vdots are added to the column of nodes. What do you mean by bigger? More circles? Bigger circles? Sep 8, 2023 at 23:05
  • Can you sketch out your second requirement? How should that look? Sep 8, 2023 at 23:06
  • I tried changing <code>second to last</code>, but at some point there is no difference if the value is 9 or 10, as you see in the code and figure. With bigger I mean, that it should be obvious that those two hidden layers are bigger than the third one, even though they are incomplete by those three dots. Here the first two hidden layers consist of 64 neurons, while the third hidden layer has 32. Btw: Nice, you are the one, who answeared the question I linked, right? :) Sep 9, 2023 at 0:05
  • Added the sketch Sep 9, 2023 at 0:08

1 Answer 1

4

I've renamed the second to last key to vdots in row which hopefully makes it a bit clearer what it does.

I've changed the subscripts m in the hidden layer to 64 and 32, since you have fixed values why not use them? I've also added two arrows that shows the difference a bit more?

The ⋮ are their own node so the big hidden layer now contain seven nodes instead of 6. The list entries of the \foreach for connecting all these nodes had to be adjusted accordingly.

The single output can simply added by placing another node right=of the output' nodes. I've chosen to align it vertically with the second one but you can of course change this.


In the second example I've used going north east for the chain placement rule so that the layers are top-aligned. The bigger hidden layers get an explicit 32 neuron, two ⋮s and again their final 64 neuron.

Comparend to the smaller hidden layer, I think this makes it a bit clearer that the sizes are very different. Of course, now the reader might wonder what that means for the input (q) and the output layer (J) where the 32 and/or 64 node are not really referenced.


Many of the edges cross the nodes, if you just want them to go behind the nodes you can load the backgrounds library and prefix the path that draws these edges with \scoped[on background layer].

However, in the second example I've added an alternative way how to visually connect all those neurons, it now also includes a dotted line to the ⋮ making clear that all those dozens of neurons are all connected.

I like the matrix-like arranged and connected neurons much better but maybe it seems now more organized than a neural network actually is?

Code 1

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta, chains, graphs, ext.positioning-plus, ext.paths.ortho}
\ExplSyntaxOn \makeatletter % allowing matrices on chains
\tl_replace_once:Nnn \tikz@do@matrix@cont
  { \tikz@node@finish } { \tikz@alias \tikz@node@finish }
\makeatother \ExplSyntaxOff
\tikzset{
  node matrix/.style={
    row sep=y_node_dist, column sep=x_node_dist,
    every outer matrix/.append style={/pgf/inner sep=+0pt, /pgf/outer sep=+0pt,
      draw=none, fill=none, shape=rectangle},
    /utils/exec=\def\tikzmatrixnodecounter{\ifnum\pgfmatrixcurrentrow=1
      \the\pgfmatrixcurrentcolumn\else\the\pgfmatrixcurrentrow\fi},
    nodes/.style={node matrix/node/.append style={##1}}},
  node matrix/node/.style={
    node contents=, anchor=center, name/.expanded={\tikzmatrixname_\tikzmatrixnodecounter}},
  node matrix/place 1st node/.code args={#1,#2}{%
    \node[node matrix/node,nm \tikzmatrixnodecounter/.try,#1];},
  node matrix/place other nodes/.style args={#1,#2}{/tikz/node matrix/place oth node/.list={#2}},
  vertical   node matrix/.style={/tikz/node matrix/place oth node/.code={%
    \pgfmatrixendrow  \node[node matrix/node,nm \tikzmatrixnodecounter/.try,##1];}},
  horizontal node matrix/.style={/tikz/node matrix/place oth node/.code={%
    \pgfmatrixnextcell\node[node matrix/node,nm \tikzmatrixnodecounter/.try,##1];}}}
\newcommand*\tikzMatrixNodes[2][1]{%
  \matrix[every node matrix/.try,node matrix,#1]{
    \tikzset{node matrix/place 1st node={#2},node matrix/place other nodes={#2}}\\};}
\tikzset{
  color let/.code args={#1=#2}{\colorlet{#1}{#2}},
  color set/.style args={#1=#2/#3}{color let={#1fg=#2}, color let={#1bg=#3}},
  color use/.style={draw=#1bg, fill=#1fg}}

\begin{document}
\begin{tikzpicture}[
  >=Latex, thick, node distance=3mm and 10mm,
  layers/.style={circle, thick, draw, minimum size=+10mm, inner sep=+.1em},
  input/.style ={layers, color use=input},
  hidden/.style={layers, color use=hidden},
  output/.style={layers, color use=output},
  every node matrix/.style={vertical node matrix},
  every label/.append style={align=center},
  label distance=1mm,
  vdots in row/.style={% ← changed name to vdots in row
    nm #1/.style={node contents=\vdots, text height=2ex, fill=none, draw=none,
      minimum size=+0pt, inner sep=+0pt, shape=rectangle},
    row #1/.append style={row sep=.75*y_node_dist},
    row \pgfinteval{#1-1}/.append style={row sep=.75*y_node_dist}},
  color set/.list={input=green!60!black/green!30!black,
                   hidden=blue!50/blue,
                   output=red!80!black/red!40!black}
]
\begin{scope}[start chain=going right]
  \tikzMatrixNodes[
    label={[inputfg]input\\layer},
    on chain, vdots in row=4, name=input'top, % can't use chain name
    nodes={input, node contents=$Z_\tikzmatrixnodecounter$},
  ]{,,,,node contents=$Z_q$}
  
  \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain, vdots in row=6, name=hidden'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,,node contents=$w_{64}^{(1)}$} % ← subscript 64

  \draw[<-] (hidden'top_6) to[out=180, in=70] +(-1,-2)
    node[below]{Here are 58 more neurons.}; % ←

  \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain, vdots in row=6, name=hidden2'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,,node contents=$w_{64}^{(1)}$} % ← subscript 64
  
      \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain, vdots in row=5, name=hidden3'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_{32}^{(1)}$} % ← subscript 32
  
  \draw[<-] (hidden3'top_5) to[out=180, in=70] +(-1,-2.25)
    node[below]{Here are only 27 more neurons.}; % ←

  \tikzMatrixNodes[
    label={[outputfg]output\\layer},
    on chain, vdots in row=3, name=output'top,
    nodes={output, node contents=$g_\tikzmatrixnodecounter$}
  ]{,,,node contents=$g_J$}

  \path[blue] graph[use existing nodes]{
                               {\foreach \x in {1,...,3,5} {input'top_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,5,7} {hidden'top_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,5,7} {hidden2'top_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,4,6} {hidden3'top_\x}}
       -- [complete bipartite] {\foreach \x in {1, 2, 4}   {output'top_\x}}
    };
\end{scope}
\begin{scope}[start chain=going right, yshift=-10.5cm]
  \tikzMatrixNodes[
    label={[inputfg]$q(s_1)$},
    on chain,vdots in row=4, name=input'bot, % can't use chain name
    nodes={input, node contents=$Z_\tikzmatrixnodecounter$},
  ]{,,,,node contents=$Z_q$}
  \tikzMatrixNodes[
    label={[hiddenfg]$w(s_1)$},
    on chain, vdots in row=5, name=hidden'bot,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}

    \tikzMatrixNodes[
    label={[hiddenfg]$w(s_1)$},
    on chain, vdots in row=5, name=hidden2'bot,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}
  
  \tikzMatrixNodes[
    label={[outputfg]$g(s_1)$},
    on chain, vdots in row=3, name=output'bot,
    nodes={output, node contents=$g_\tikzmatrixnodecounter$}
  ]{,,,node contents=$g_J$}

  
  \path[yellow!50!black] graph[use existing nodes]{
                               {\foreach \x in {1,...,3,5} {input'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,4,6} {hidden'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,4,6} {hidden2'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,2,4}     {output'bot_\x}}
    };
\end{scope}

\tikzMatrixNodes[
  node distance=3mm and 20mm,
  right=of (output'top)(output'bot),
  vdots in row=3, name=output',
  nodes={output, node contents=$g_\tikzmatrixnodecounter$}
]{,,,node contents=$g_r$}

% Add single output
% here I've chosen to align it vertically with output'_2
% alternatively do right=of output
\node[output, right=of output'_2] (single output) {};

\graph[use existing nodes]{
  {\foreach \tb in {top, bot}{\foreach \x in {1,2,4}{output'\tb_\x}}}
  -- [complete bipartite]    {\foreach \x in {1,2,4}{output'_\x}}
  -- single output % ← added edges from common output to single output
};
\end{tikzpicture}
\end{document}

Output 1

enter image description here

Code 2

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta, calc, chains, graphs, ext.positioning-plus, ext.paths.ortho}
\ExplSyntaxOn \makeatletter % allowing matrices on chains
\tl_replace_once:Nnn \tikz@do@matrix@cont
  { \tikz@node@finish } { \tikz@alias \tikz@node@finish }
\makeatother \ExplSyntaxOff
\tikzset{
  node matrix/.style={
    row sep=y_node_dist, column sep=x_node_dist,
    every outer matrix/.append style={/pgf/inner sep=+0pt, /pgf/outer sep=+0pt,
      draw=none, fill=none, shape=rectangle},
    /utils/exec=\def\tikzmatrixnodecounter{\ifnum\pgfmatrixcurrentrow=1
      \the\pgfmatrixcurrentcolumn\else\the\pgfmatrixcurrentrow\fi},
    nodes/.style={node matrix/node/.append style={##1}}},
  node matrix/node/.style={
    node contents=, anchor=center, name/.expanded={\tikzmatrixname_\tikzmatrixnodecounter}},
  node matrix/place 1st node/.code args={#1,#2}{%
    \node[node matrix/node,nm \tikzmatrixnodecounter/.try,#1];},
  node matrix/place other nodes/.style args={#1,#2}{/tikz/node matrix/place oth node/.list={#2}},
  vertical   node matrix/.style={/tikz/node matrix/place oth node/.code={%
    \pgfmatrixendrow  \node[node matrix/node,nm \tikzmatrixnodecounter/.try,##1];}},
  horizontal node matrix/.style={/tikz/node matrix/place oth node/.code={%
    \pgfmatrixnextcell\node[node matrix/node,nm \tikzmatrixnodecounter/.try,##1];}}}
\newcommand*\tikzMatrixNodes[2][1]{%
  \matrix[every node matrix/.try,node matrix,#1]{
    \tikzset{node matrix/place 1st node={#2},node matrix/place other nodes={#2}}\\};}
\tikzset{
  color let/.code args={#1=#2}{\colorlet{#1}{#2}},
  color set/.style args={#1=#2/#3}{color let={#1fg=#2}, color let={#1bg=#3}},
  color use/.style={draw=#1bg, fill=#1fg}}

\begin{document}
\begin{tikzpicture}[
  >=Latex, thick, node distance=3mm and 10mm,
  layers/.style={circle, thick, draw, minimum size=+10mm, inner sep=+.1em},
  input/.style ={layers, color use=input},
  hidden/.style={layers, color use=hidden},
  output/.style={layers, color use=output},
  every node matrix/.style={vertical node matrix},
  every label/.append style={align=center},
  label distance=1mm,
  vdots in row/.style={% ← changed name to vdots in row
    nm #1/.style={node contents=\vdots, text height=2ex, fill=none, draw=none,
      minimum size=+0pt, inner sep=+0pt, shape=rectangle},
    row #1/.append style={row sep=.75*y_node_dist},
    row \pgfinteval{#1-1}/.append style={row sep=.75*y_node_dist}},
  color set/.list={input=green!60!black/green!30!black,
                   hidden=blue!50/blue,
                   output=red!80!black/red!40!black}
]
\begin{scope}[start chain=going north right]
  \tikzMatrixNodes[
    label={[inputfg]input\\layer},
    on chain, vdots in row=4, name=input'top, % can't use chain name
    nodes={input, node contents=$Z_\tikzmatrixnodecounter$},
  ]{,,,,node contents=$Z_q$}
  
  \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain, vdots in row/.list={5, 7}, name=hidden'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_{32}^{(1)}$,,node contents=$w_{64}^{(1)}$} % ← subscripts

  \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain, vdots in row/.list={5, 7}, name=hidden2'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_{32}^{(1)}$,,node contents=$w_{64}^{(1)}$} % ← subscript 64
  
      \tikzMatrixNodes[
    label={[hiddenfg]hidden layer},
    on chain, vdots in row=5, name=hidden3'top,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_{32}^{(1)}$} % ← subscript 32
  
  \tikzMatrixNodes[
    label={[outputfg]output\\layer},
    on chain, vdots in row=3, name=output'top,
    nodes={output, node contents=$g_\tikzmatrixnodecounter$}
  ]{,,,node contents=$g_J$}

  \path[blue, horizontal vertical horizontal] graph[use existing nodes]{
                                                           {\foreach \x in {1,...,3,5} {input'top_\x}}
       -- [complete bipartite, edge node=coordinate(ih1) ] {\foreach \x in {1,...,4,6,8} {hidden'top_\x}}
       -- [complete bipartite, edge node=coordinate(h1h2)] {\foreach \x in {1,...,4,6,8} {hidden2'top_\x}}
       -- [complete bipartite, edge node=coordinate(h2h3)] {\foreach \x in {1,...,4,6} {hidden3'top_\x}}
       -- [complete bipartite, edge node=coordinate(h3o) ] {\foreach \x in {1, 2, 4}   {output'top_\x}}
    };
  \draw[blue, densely dotted, */.style args={#1:#2}{
    to path=(\tikztostart_1.south #2|-\tikztostart_#1) coordinate (@)
    -- (@-|\tikztotarget)}] foreach \s/\t/\d/\L in {input/ih1/east/4,
      hidden/ih1/west/{5, 7}, hidden/h1h2/east/{5, 7},
      hidden2/h1h2/west/{5, 7}, hidden2/h2h3/east/{5, 7},
      hidden3/h2h3/west/5, hidden3/h3o/east/5,
      output/h3o/west/3}
        \foreach \l in \L {(\s'top) to[*/.expand once=\l:\d] (\t)};
\end{scope}
\begin{scope}[start chain=going north right, yshift=-10.5cm]
  \tikzMatrixNodes[
    label={[inputfg]$q(s_1)$},
    on chain,vdots in row=4, name=input'bot, % can't use chain name
    nodes={input, node contents=$Z_\tikzmatrixnodecounter$},
  ]{,,,,node contents=$Z_q$}
  \tikzMatrixNodes[
    label={[hiddenfg]$w(s_1)$},
    on chain, vdots in row=5, name=hidden'bot,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}

    \tikzMatrixNodes[
    label={[hiddenfg]$w(s_1)$},
    on chain, vdots in row=5, name=hidden2'bot,
    nodes={hidden, node contents=$w_\tikzmatrixnodecounter^{(1)}$}
  ]{,,,,,node contents=$w_m^{(1)}$}
  
  \tikzMatrixNodes[
    label={[outputfg]$g(s_1)$},
    on chain, vdots in row=3, name=output'bot,
    nodes={output, node contents=$g_\tikzmatrixnodecounter$}
  ]{,,,node contents=$g_J$}

  
  \path[yellow!50!black] graph[use existing nodes]{
                               {\foreach \x in {1,...,3,5} {input'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,4,6} {hidden'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,...,4,6} {hidden2'bot_\x}}
       -- [complete bipartite] {\foreach \x in {1,2,4}     {output'bot_\x}}
    };
\end{scope}

\tikzMatrixNodes[
  node distance=3mm and 20mm,
  right=of (output'top)(output'bot),
  vdots in row=3, name=output',
  nodes={output, node contents=$g_\tikzmatrixnodecounter$}
]{,,,node contents=$g_r$}

% Add single output
% here I've chosen to align it vertically with output'_2
% alternatively do right=of output
\node[output, right=of output'_2] (single output) {};

\graph[use existing nodes]{
  {\foreach \tb in {top, bot}{\foreach \x in {1,2,4}{output'\tb_\x}}}
  -- [complete bipartite]    {\foreach \x in {1,2,4}{output'_\x}}
  -- single output % added edges from common output to single output
};

\end{tikzpicture}
\end{document}

Output 2

enter image description here

1
  • 1
    Wow, thanks so much! Sep 9, 2023 at 9:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .