Created
September 16, 2020 18:49
-
-
Save wchargin/9a1c0d495381b3ce2b110720a18df2e3 to your computer and use it in GitHub Desktop.
diagram from https://arxiv.org/pdf/1705.02735.pdf#page=5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% Overview figure for | |
% ``Combating human trafficking with multimodal deep models,'' | |
% submitted to ACL 2017. | |
% Figure by William Chargin; send any comments to wchargin@gmail.com. | |
\documentclass[margin=2mm]{standalone} | |
\usepackage{amsmath} | |
\usepackage{amsfonts} | |
\usepackage{tikz} | |
\usetikzlibrary{positioning,decorations.pathreplacing} | |
\renewcommand{\Pr}{\textrm{P}} | |
\newcommand*{\vdotsalign}{\raisebox{1.25ex}{$\vdots$}} | |
\begin{document} | |
% Usage: \cube{origin}{width}{height}{extrudeX}{extrudeY}{label}{fill options} | |
% Construct a cube with front-top-left corner at #1, which should be a | |
% TikZ coordinate---e.g., (1cm, 2cm) or (my node). The label will be | |
% placed in the center of the cube. The fill options (e.g., fill=white) | |
% control the background color of the cube. | |
\def\cube#1#2#3#4#5#6#7{% | |
\path[#7] | |
#1 -- | |
++(#4, #5) -- | |
++(#2, 0) -- | |
++(0, -#3) -- | |
++(-#4, -#5) -- | |
++(-#2, 0) -- | |
cycle | |
; | |
\draw #1 -- ++(#2, 0) -- ++(0, -#3) -- ++(-#2, 0) -- cycle; | |
\draw #1 -- ++(#4, #5) -- ++(#2, 0) -- ++(0, -#3) -- ++(-#4, -#5); | |
\draw #1 ++(#2, 0) -- ++(#4, #5); | |
\path #1 rectangle node[align=center, font=\small] {#6} ++(#2, -#3); | |
} | |
\def\fillcube#1#2#3#4#5#6{\cube{#1}{#2}{#3}{#4}{#5}{#6}{fill=white}} | |
\def\emptycube#1#2#3#4#5#6{\cube{#1}{#2}{#3}{#4}{#5}{#6}{opacity=0}} | |
% Usage: \boxedletter{x}. Emulate a fancy Unicode symbol, but with | |
% consistent height and mostly consistent spacing. | |
\def\boxedletter#1{\fbox{\textsc{\vphantom{m}\smash{#1}}}} | |
% Here are some styles for easy modification. | |
\tikzset{% | |
neuron/.style={% | |
circle, | |
minimum width=2mm, | |
inner sep=0, | |
draw=black, | |
fill=black!30!white, | |
}, | |
convolution box/.style={% | |
% This box is the ``conv'' prism inside the boxes. | |
fill=black!15!white, | |
}, | |
small label/.style={% | |
font=\footnotesize, | |
align=center, | |
}, | |
sideways label/.style={% | |
rotate=30, | |
anchor=east, | |
xshift=0.2cm, | |
yshift=-0.1cm, | |
}, | |
} | |
\begin{tikzpicture}[>=stealth] | |
% This scope block contains the upper-left portion of the figure. | |
\begin{scope} | |
\def\lstmSpacing{0.6cm} | |
% | |
% Change the words here to change the initial sentence. | |
\foreach \word/\j in {% | |
{d0ll@r}/0,% | |
{to}/1, | |
{\vdotsalign}/2,% | |
{\boxedletter{g}\boxedletter{r}\boxedletter{8}}/3,% | |
{skype}/4% | |
}{% | |
\node[left] at (0.5cm, -\lstmSpacing * \j) {\word}; | |
}; | |
% | |
% usage: \makeLSTM{index}{LSTM label name}{neuron label name} | |
\def\makeLSTM#1#2#3{% | |
\def\j{#1} | |
\def\lstmHeight{0.25cm} | |
\def\lstmWidth{2cm} | |
\path [fill=white, draw=black] | |
(1cm, -\j * \lstmSpacing + \lstmHeight / 2) rectangle ++(\lstmWidth, -\lstmHeight); | |
\draw [->] (0.5cm, -\j * \lstmSpacing) -- ++(0.5cm, 0); | |
\foreach \x in {1.25cm,1.5cm,2.5cm,2.75cm}{% | |
\draw (\x, -\j * \lstmSpacing + \lstmHeight / 2) -- ++(0, -\lstmHeight); | |
} | |
\node at (2cm, -\j * \lstmSpacing) {$\cdots\unkern$}; | |
\node [draw=black, fill=white, small label] (#2) | |
at (4cm, -\j * \lstmSpacing) {LSTM}; | |
\draw [->] (1cm + \lstmWidth, -\j * \lstmSpacing) -- (#2); | |
\node [neuron] (#3) at (5.5cm, -\j * \lstmSpacing) {}; | |
} | |
\makeLSTM{0}{lstm 1}{lstm node 1} | |
\makeLSTM{1}{lstm 2}{lstm node 2} | |
\makeLSTM{3}{lstm 3}{lstm node 3} | |
\makeLSTM{4}{lstm 4}{lstm node 4} | |
\draw [decorate, decoration={brace, amplitude=4pt, raise=0.2cm}] | |
(lstm node 1) -- (lstm node 4); | |
\coordinate (lstm anchor) at (6cm, -2 * \lstmSpacing); | |
\foreach \i in {1,2,3,4}{% | |
\foreach \j in {1,2,3,4}{% | |
\draw (lstm \i.east) -- (lstm node \j); | |
} | |
} | |
\draw [->] (lstm 1) -- (lstm 2); | |
\draw [->] (lstm 3) -- (lstm 4); | |
\node [above=0.15cm of lstm node 1] {$h_l \in \mathbb{R}^{300}$}; | |
\node [align=center] at (2cm, 0.7cm) {Trafficking \\ embedding}; | |
\node at (2cm, -2 * \lstmSpacing) {\vdotsalign}; | |
\node at (4cm, -2 * \lstmSpacing) {\vdotsalign}; | |
% | |
% Swap the comments on these next two lines to show a dotted arrow | |
% between the LSTM gap, instead of just vdots. | |
%\draw [dotted, ->] (lstm 2) -- (lstm 3); | |
\node at (5.5cm, -2 * \lstmSpacing) {\vdotsalign}; | |
% | |
% Swap the comments on these next two lines to change the node text. | |
%\node [below=0 of lstm node 4, small label] {$300$ \\ sigmoid}; | |
\node [below=0 of lstm node 4, small label] {$300 \sigma$}; | |
\end{scope} | |
% This scope block contains the lower-left portion of the figure. | |
\begin{scope}[yshift=-4cm] | |
% | |
% Modify the following settings to change the appearance of the | |
% images. In particular, you can make them darker by adjusting the | |
% \imageIntensity. | |
\def\imageWidth{0.4cm} | |
\def\imageHeight{0.8cm} | |
\def\imageColor{black} | |
\def\imageIntensity{0.05} | |
\foreach \i in {0,1,2,3,4}{% | |
\pgfmathtruncatemacro{\iplusone}{\i + 1}; | |
\pgfmathtruncatemacro{\thisIntensity}{100*\imageIntensity*(\i+1)}; | |
\edef\thisImageColor{\imageColor!\thisIntensity!white}, | |
\node at (0, \i * -0.45cm + 0.25cm) {$\hat{\imath}_{\iplusone}$}; | |
\fill [ | |
color=\thisImageColor, | |
draw=black, | |
xshift=\i * 0.1cm + 0.2cm, | |
yshift=\i * -0.3cm + 0.25cm, yslant=0.5, | |
] | |
(0, 0) -- | |
++(\imageWidth, 0) -- | |
++(0, -\imageHeight) -- | |
++(-\imageWidth, 0) -- | |
cycle | |
; | |
} | |
\foreach \i in {0,1,2,3,4}{% | |
\pgfmathsetmacro{\x}{1.25 - 0.1*\i}; | |
\pgfmathsetmacro{\y}{-0.5 + 0.3*(\i-2)}; | |
\typeout{\y} | |
\draw [->] (\x cm, \y cm) -- (1.75cm, \y cm); | |
} | |
\coordinate (TVGG origin) at (1.75cm, 0.5cm); | |
\path (TVGG origin) ++ (2.25cm, 0.25cm) coordinate (TVGG top right); | |
\path (TVGG origin) ++ (2.25cm, -1.75cm) coordinate (TVGG bottom right); | |
\path (TVGG origin) ++ (1.75cm, 0) coordinate (TVGG front top right); | |
\path (TVGG origin) ++ (1.75cm, -2cm) coordinate (TVGG front bottom right); | |
\fillcube{(TVGG origin)}{1.75cm}{2cm}{0.5cm}{0.25cm}{Trafficking \\ VGG}; | |
\foreach \i in {1,2,3}{% | |
\pgfmathsetmacro{\x}{4.5 + 0.5 * (\i - 1)}; | |
\node at (\x, -0.5cm) {\vdotsalign}; | |
\foreach \j in {1,2,4,5}{% | |
\pgfmathsetmacro{\y}{-0.5 + 0.4 * (\j - 3)}; | |
\node [neuron] (node-\i-\j) at (\x, \y) {}; | |
} | |
} | |
\foreach \i/\direction in {1/below left,2/below,3/below right}{% | |
% Here are two alternatives: one uses ``200 \sigma'', and the | |
% other uses ``250 \\ sigmoid'' but requires that the labels be | |
% positioned further from the nodes. Swap the comments to change | |
% which one is in use. | |
\node [below=0 of node-\i-1, small label, sideways label] {$200 \sigma$}; | |
%\node [\direction=0 of node-\i-1, small label] {$200$ \\ sigmoid}; | |
} | |
\foreach \i in {1,2}{% | |
\pgfmathtruncatemacro{\nexti}{\i + 1}; | |
\foreach \j in {1,2,4,5}{% | |
\foreach \k in {1,2,4,5}{% | |
\draw (node-\i-\j) -- (node-\nexti-\k); | |
} | |
} | |
} | |
\draw [dashed] (TVGG top right) -- (node-1-5); | |
\draw [dashed] (TVGG bottom right) -- (node-1-1); | |
\draw [dashed] (TVGG front top right) -- (node-1-5); | |
\draw [dashed] (TVGG front bottom right) -- (node-1-1); | |
% | |
\coordinate (hV) at (5.75cm, -0.5cm); | |
\node [below right] at (hV) {$h_v \in \mathbb{R}^{5 \times 200}$}; | |
\end{scope} | |
% This scope block contains the right-hand portion of the figure. | |
\begin{scope}[xshift=7cm] | |
\begin{scope}[xshift=0.25cm,yshift=-1.75cm] | |
\fillcube{(0, 0)}{1cm}{2cm}{0.5cm}{1cm}{}; | |
\cube{(0.425cm, 0.85cm)}{1cm}{0.3cm}{0.075cm}{0.15cm}{\footnotesize conv}{convolution box}; | |
\emptycube{(0, 0)}{1cm}{2cm}{0.5cm}{1cm}{}; | |
\node [above] at (1cm, 1cm) {$h_m \in \mathbb{R}^{5 \times 200 \times 300}$}; | |
% | |
\coordinate (hM top right) at (3cm, 1cm); | |
\draw [->] (lstm anchor) to[in=180, out=0] (-0.1cm, -0.9cm); | |
\draw [->] (hV) to[in=180, out=0] (-0.1cm, -1.1cm); | |
\node at (-0.5cm, -1cm) {$\otimes$}; | |
% | |
\node [below, small label] at (0.5cm, -2cm) {$5 \times 200 \times 300$}; | |
% | |
\draw [->] (1.5cm, -0.5cm) -- node[above, small label] {max \\ pooling} ++(1.2cm, 0); | |
\fillcube{(2.7cm, 0cm)}{1cm}{1cm}{0.375cm}{0.75cm}{}; | |
\cube{(3.0cm, 0.6cm)}{1cm}{0.3cm}{0.075cm}{0.15cm}{\footnotesize conv}{convolution box}; | |
\emptycube{(2.7cm, 0cm)}{1cm}{1cm}{0.375cm}{0.75cm}{}; | |
\node [below, small label] at (3.2cm, -1cm) {$5 \times 100 \times 150$}; | |
% | |
\draw [->] (4.075cm, 0) -- node[above, small label] {max \\ pooling} ++(1.2cm, 0); | |
\draw [decorate, decoration={brace, amplitude=4pt, mirror, raise=-0.1cm}] | |
(5.4cm, 1.5cm) -- ++(0, -3cm); | |
\node [neuron] (output) at (6.2cm, 0) {}; | |
\foreach \i in {-4,-3,-2,2,3,4}{% | |
\pgfmathsetmacro{\endY}{0.35*\i}; | |
\node [neuron] (dense-\i) at (5.65cm, \endY) {}; | |
\draw [->] (dense-\i) -- (output); | |
} | |
\node [below=0 of dense--4, small label] {$150$ linear}; | |
\node (dense dots) at (5.65cm, 0) {\vdotsalign}; | |
\draw [->, dotted] (dense dots) -- (output); | |
\draw [->] (output) -- ++(1cm, 0); | |
\node [below right=0 of output, small label] {$\Pr[\tau \mid h_m; W_d]$}; | |
\node [above right=0 of output] {$\sigma$}; | |
\end{scope} | |
\end{scope} | |
\end{tikzpicture} | |
\end{document} |
Author
wchargin
commented
Sep 16, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment