Skip to content

Instantly share code, notes, and snippets.

@wchargin
Created September 16, 2020 18:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wchargin/9a1c0d495381b3ce2b110720a18df2e3 to your computer and use it in GitHub Desktop.
Save wchargin/9a1c0d495381b3ce2b110720a18df2e3 to your computer and use it in GitHub Desktop.
% 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}
@wchargin
Copy link
Author

Screenshot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment