我正在尝试重新创建这个形象MADE 网络在 TikZ 中。
这是我目前所拥有的。
任何关于如何绘制掩码矩阵以及如何将 MADE 网络神经元内的数字合并到drawLayers
宏中的建议都将不胜感激。(这些数字表示影响相关神经元的最大输入单元数量。)
\documentclass[tikz]{standalone}
\usetikzlibrary{positioning}
\newcommand\drawLayers[2]{
% #1 (str): namespace
% #2 (list[int]): number of nodes in each layer
\foreach \neurons [count=\lyrIdx] in #2
\foreach \n in {1,...,\neurons}
\node[neuron] (#1-\lyrIdx-\n) at (1.5*\lyrIdx, \neurons/2-\n) {};
}
\newcommand\denselyConnectNodes[2]{
% #1 (str): namespace
% #2 (list[int]): number of nodes in each layer
\foreach \n [count=\lyrIdx, remember=\lyrIdx as \previdx, remember=\n as \prevn] in #2 {
\foreach \y in {1,...,\n} {
\ifnum \lyrIdx > 1
\foreach \x in {1,...,\prevn}
\draw (#1-\previdx-\x) -- (#1-\lyrIdx-\y);
\fi
}
}
}
\newcommand\connectSomeNodes[2]{
% #1 (str): namespace
% #2 (list[list[list[int]]]): for each node in each layer, list all connected nodes in the next layer
\foreach \layer [count=\lyrIdx, evaluate=\lyrIdx as \nextLyr using int(\lyrIdx+1)] in #2
\foreach \neuron [count=\nIdx] in \layer
\foreach \edge in \neuron
\draw (#1-\lyrIdx-\nIdx) -- (#1-\nextLyr-\edge);
}
\begin{document}
\begin{tikzpicture}[
shorten >=1pt, shorten <=1pt, ->,
neuron/.style={circle, draw, minimum size=4ex, thick},
legend/.style={font=\large\bfseries},
]
% Fully-connected neural net
\drawLayers{fcnn}{{3, 4, 4, 3}}
\denselyConnectNodes{fcnn}{{3, 4, 4, 3}}
\path (fcnn-1-1) -- (fcnn-2-1) node[midway, above=1ex] {$W_1$};
\path (fcnn-2-1) -- (fcnn-3-1) node[midway, above=1ex] {$W_2$};
\path (fcnn-3-1) -- (fcnn-4-1) node[midway, above=1ex] {$V$};
% MADE net
\begin{scope}[xshift=10cm]
\drawLayers{made}{{3, 4, 4, 3}}
\connectSomeNodes{made}{{
{{}, {1,2,3,4}, {1,3,4}},
{{2,3}, {1,2,3,4}, {2,3}, {2,3}},
{{1,3}, {1}, {1}, {1,3}},
}}
\end{scope}
% Input + output labels
\foreach \label [count=\c] in {{$p(x_1|x_2,x_3)$}, $p(x_2)$, $p(x_3|x_2)$} {
\node[left=0 of fcnn-1-\c] {$x_\c$};
\node[right=0 of fcnn-4-\c] {$\hat x_\c$};
\node[left=0 of made-1-\c] {$x_\c$};
\node[right=0 of made-4-\c] {\label};
}
\node[legend, below=0.5 of fcnn-3-4] {autoencoder};
\node[legend, below=0.5 of made-2-4] {MADE};
\end{tikzpicture}
\end{document}
答案1
回答我自己的问题,这是完整的图像:
% TikZ-reproduction of fig. 1 from the paper MADE: Masked Autoencoder for Distribution Estimation (https://arxiv.org/abs/1502.03509).
\documentclass[tikz]{standalone}
\usepackage{xstring}
\usetikzlibrary{calc,positioning}
\newcommand\drawNodes[2]{
% #1 (str): namespace
% #2 (list[list[str]]): list of labels to print in the node of each neuron
\foreach \neurons [count=\lyrIdx] in #2 {
\StrCount{\neurons}{,}[\arrlength] % uses the xstring package
\foreach \n [count=\nIdx] in \neurons
\node[neuron] (#1-\lyrIdx-\nIdx) at (\arrlength/2-\nIdx, 1.5*\lyrIdx) {\n};
}
}
\newcommand\denselyConnectNodes[2]{
% #1 (str): namespace
% #2 (list[int]): number of nodes in each layer
\foreach \n [count=\lyrIdx, remember=\lyrIdx as \previdx, remember=\n as \prevn] in #2 {
\foreach \y in {1,...,\n} {
\ifnum \lyrIdx > 1
\foreach \x in {1,...,\prevn}
\draw[->] (#1-\previdx-\x) -- (#1-\lyrIdx-\y);
\fi
}
}
}
\newcommand\connectSomeNodes[2]{
% #1 (str): namespace
% #2 (list[list[list[int]]]): for each node in each layer, list all connected nodes in the next layer
\foreach \layer [count=\lyrIdx, evaluate=\lyrIdx as \nextLyr using int(\lyrIdx+1)] in #2
\foreach \neuron [count=\nIdx] in \layer
\foreach \edge in \neuron
\draw[->] (#1-\lyrIdx-\nIdx) -- (#1-\nextLyr-\edge);
}
\begin{document}
\begin{tikzpicture}[
shorten >=1pt, shorten <=1pt,
neuron/.style={circle, draw, minimum size=4ex, thick},
legend/.style={font=\large\bfseries},
]
% Fully-connected neural net
\drawNodes{fcnn}{{{,,}, {,,,}, {,,,}, {,,}}}
\denselyConnectNodes{fcnn}{{3, 4, 4, 3}}
\path (fcnn-1-1) -- (fcnn-2-1) node[midway, right=1ex] (W1) {$W_1$};
\path (fcnn-2-1) -- (fcnn-3-1) node[midway, right=1ex] (W2) {$W_2$};
\path (fcnn-3-1) -- (fcnn-4-1) node[midway, right=1ex] (V) {$V$};
% MADE net
\begin{scope}[xshift=93mm]
\drawNodes{made}{{{3,1,2}, {2,1,2,2}, {1,2,2,1}, {3,1,2}}}
\connectSomeNodes{made}{{
{{}, {1,2,3,4}, {1,3,4}},
{{2,3}, {1,2,3,4}, {2,3}, {2,3}},
{{1,3}, {1}, {1}, {1,3}},
}}
\end{scope}
% Input + output labels
\foreach \idx in {1,2,3} {
\node[below=0 of fcnn-1-\idx] {$x_\idx$};
\node[above=0 of fcnn-4-\idx] {$\hat x_\idx$};
\node[below=0 of made-1-\idx] {$x_\idx$};
}
% MADE output labels
\node[xshift=2.5ex, above=0 of made-4-1] {$p(x_3|x_2)$};
\node[above=0 of made-4-2] {$p(x_2)$};
\node[xshift=-4ex, above=0 of made-4-3] {$p(x_1|x_2,x_3)$};
% Bottom legend
\node[legend, below=of fcnn-1-2] (encoder) {autoencoder};
\node[legend, below=of made-1-2] (made) {MADE};
\node[legend, right=27mm of encoder] (masks) {masks};
\node[legend, yshift=-1pt] (masks) at ($(encoder)!0.55!(masks)$) {\texttimes};
\node[legend, yshift=-1pt] (masks) at ($(masks)!0.65!(made)$) {$\longrightarrow$};
% Mask matrices
\begin{scope}[shift={(35mm,49mm)}, scale=0.4]
\draw (0,0) grid (4,3);
\node at (-1.8,1.5) {$M_V =$};
\fill[black] (0,1) rectangle ++(4,1);
\fill[black] (1,0) rectangle ++(2,1);
\begin{scope}[yshift=-5cm]
\draw (0,0) grid (4,4);
\node at (-1.8,2) {$M_{W_2} =$};
\fill[black] (0,0) rectangle ++(1,1);
\fill[black] (0,3) rectangle ++(1,1);
\fill[black] (2,0) rectangle ++(2,1);
\fill[black] (2,3) rectangle ++(2,1);
\end{scope}
\begin{scope}[yshift=-10cm]
\draw (0,0) grid (3,4);
\node at (-1.8,2) {$M_{W_1} =$};
\fill[black] (0,0) rectangle ++(1,4);
\fill[black] (2,2) rectangle ++(1,1);
\end{scope}
\end{scope}
\end{tikzpicture}
\end{document}
答案2
我改编了代码金章洙的平面隔断。通过创建两个命令,其中一个命令称为mask
从下到上逐行创建掩码。
\documentclass[]{article}
\usepackage{tikz}
\newcounter{x}
\newcounter{y}
\newcommand\square[3]{
\fill[fill=#1, draw=black] (#2,#3) rectangle(#2+1,#3+1);
}
\newcommand\mask[1]{
\setcounter{y}{-1}
\foreach \a in {#1} {
\addtocounter{y}{1}
\setcounter{x}{-1}
\foreach \b in \a {
\addtocounter{x}{1}
\ifnum \b>0
\square{black}{\value{x}}{\value{y}}
\else
\square{white}{\value{x}}{\value{y}}
\fi
}
}
}
\begin{document}
\tikzset{x={(.5,0)},y={(0,.5)}}
\begin{tikzpicture}
\begin{scope}[local bounding box=figW1]
\mask{{1,0,0},{1,0,0},{1,0,1},{1,0,0}}
\node[anchor=west,font=\bf] at (figW1.east){$=M^{W^1}$};
\end{scope}
\begin{scope}[yshift=3cm,local bounding box=figW2]
\mask{{1,0,1,1},{0,0,0,0},{0,0,0,0},{1,0,1,1}}
\node[anchor=west,font=\bf] at (figW2.east){$=M^{W^2}$};
\end{scope}
\begin{scope}[yshift=6cm,local bounding box=figV]
\mask{{0,1,1,0},{1,1,1,1},{0,0,0,0}}
\node[anchor=west,font=\bf] at (figV.east){$=M^{V}$};
\end{scope}
\end{tikzpicture}
\end{document}