我想创建一个图来展示 DDPG 环境中批评家的结构,它由三个相连的神经网络组成。这里(TikZ:并排绘制两个神经网络,并通过 softmax 层连接)我找到了一个合适的结构,我想根据自己的需要进行调整。然而,有两点我失败了。
- 在上层神经网络中,我希望前两个隐藏层包含三个点,表示神经元的数量比图中实际的多。此外,我需要这两个层看起来比第三个隐藏层更大。
- 在连接左侧两个网络的右侧红色层后面,我想包含一个由单个神经元组成的输出层。
我该如何实现这一点?附件是修改后的代码和迄今为止的图表。
\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}
以下是我想更改的内容的草图:
答案1
我已将该second to last
键重命名为vdots in row
,希望可以更清楚地说明它的作用。
我改变了下标米在隐藏层中为 64 和 32,既然你有固定值,为什么不使用它们?我还添加了两个箭头,以显示更多差异?
⋮ 是它们自己的节点,因此大隐藏层现在包含 7 个节点而不是 6 个。用于连接所有这些节点的列表条目\foreach
必须进行相应调整。
right=of
只需将另一个节点放置在节点上即可添加单个输出output'
。我选择将其与第二个节点垂直对齐,但您当然可以更改这一点。
在第二个示例中,我使用了going north east
链式布局规则,以便层顶部对齐。较大的隐藏层获得显式 32 个神经元、两个 ⋮ 以及最终的 64 个神经元。
与较小的隐藏层相比,我认为这更清楚地表明了大小的差异。当然,现在读者可能想知道这对输入意味着什么(问)和输出层(J) 其中 32 和/或 64 节点实际上并未被引用。
许多边与节点交叉,如果您只想让它们位于节点后面,您可以加载库backgrounds
并在绘制这些边的路径前加上前缀\scoped[on background layer]
。
然而,在第二个例子中,我添加了一种替代方法来直观地连接所有这些神经元,它现在还包括一条指向 ⋮ 的虚线,清楚地表明所有这几十个神经元都是连接在一起的。
我更喜欢矩阵状排列和连接的神经元,但现在它可能看起来比神经网络实际上更有条理?
代码 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}
输出 1
代码 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}