TeXでニューラルネットワークのネットワーク構成図を描画する方法

$\TeX$でニューラルネットワークのネットワーク構成図を描画する方法についてまとめたいと思います。

# 概要
TikZと呼ばれる$\TeX$用の描画パッケージを用いて描画します。
ベクター画像として描画されるため、拡大縮小による図の乱れが発生せず、図内にある文字がコピペ可能になるという利点があります。
また、相対位置による位置の指定やforeachが使えるため (具体例は以下の[描画例](#描画例)や[Tikz の foreach を使う練習 - Qiita](https://qiita.com/yanagi4q/items/86692fce62fdf6bb83ef)参照)、描画処理を効率的に記述できます。

# 描画例
双方向LSTM (Bi-directional LSTM / LSTMについては[わかるLSTM ～ 最近の動向と共に - Qiita](https://qiita.com/t_Signull/items/21b82be280b46f467d1b)参照) のネットワーク構成図を描画してみたいと思います。

## コード
`TODO`部の指示に従って書き換えを行い、コンパイルします。

```tex
% 古いパッケージや記法のチェック用
% (コンパイル時に古いパッケージや記法を『Package nag Warning:』で始まる警告の形で指摘してくれるので, この警告が少なくなるように記述すると良い)
\RequirePackage[l2tabu, orthodox]{nag}

% latexコマンドでのコンパイル用
% TODO: 欧文の場合, 以下のコメントアウトを解除
% \documentclass{article}

% platexコマンドでのコンパイル用
% TODO: 和文の場合, 以下のコメントアウトを解除
% \documentclass[dvipdfmx]{jsarticle}

% ネットワーク構成図描画用
\usepackage{tikz}

% 省略記号
\def\ellipsis{$\cdots$}

\begin{document}
% ネットワーク構成図
\begin{figure}[tbp]
\centering

% ノード間の距離
\def\nodeDistance{1.1cm}

% 曲線の始点の角度 (°)
\def\angleStartCurve{360 * 9 / 56}

\begin{tikzpicture}[shorten >= 1pt, ->, node distance=\nodeDistance]
% 変数や省略部のスタイル
\tikzset{var/.style={minimum size=15pt}};

% ノードのスタイル
\tikzset{neuron/.style={var, draw, circle}};

% 入力部を描画
\node[var] (I-n) {$x_n$};
\node[var, left of=I-n] (I-3) {\ellipsis};
\foreach \i/\j in {2/3, 1/2}
{
    \node[var, left of=I-\j] (I-\i) {$x_\i$};
}

% 省略部のノードや変数を描画
\foreach \f/\t in {I/F-LSTM, F-LSTM/B-LSTM, B-LSTM/L-S}
{
    \node[var, above of=\f-3] (\t-3) {\ellipsis};
}
\node[var, above of=L-S-3] (O-3) {\ellipsis};

\foreach \n in {1, 2, n}
{
    % 表示されるノードや変数を描画
    \foreach \o/\f/\t in {neuron/I/F-LSTM, neuron/F-LSTM/B-LSTM, neuron/B-LSTM/L-S}
    {
        \node[\o, above of=\f-\n] (\t-\n) {};
    }
    \node[var, above of=L-S-\n] (O-\n) {$y_\n$};

    % 縦方向の線を描画
    \draw (I-\n) to [out=\angleStartCurve, in=360 - \angleStartCurve] (B-LSTM-\n);
    \draw (F-LSTM-\n) to [out=180 - \angleStartCurve, in=180 + \angleStartCurve] (L-S-\n);
    \foreach \f/\t in {I/F-LSTM, B-LSTM/L-S, L-S/O}
    {
        \path (\f-\n) edge (\t-\n);
    }
}

% 横方向の線を描画
\foreach \i/\j in {1/2, 2/3, 3/n}
{
    \foreach \n/\f/\t in {F-LSTM/\i/\j, B-LSTM/\j/\i}
    {
        \path (\n-\f) edge (\n-\t);
    }
}

% 注釈を描画
\foreach \f/\n in {I/Input, B-LSTM/Backward LSTM, F-LSTM/Foward LSTM, L-S/Linear, O/Output}
{
    \node[node distance=2 * \nodeDistance and \nodeDistance, text width=9em, text centered, right of=\f-n] (A-\f) {\n};
}
\end{tikzpicture}
\caption{Bi-directional LSTM}
\label{Fig:Bi-directional LSTM}
\end{figure}
\end{document}
```

## コンパイル結果
![Screenshot from 2018-07-14 04-14-42_.png](https://qiita-image-store.s3.amazonaws.com/0/52291/0891bb74-e657-9d29-9d5b-632821db7b18.png)

# CloudLaTeXテンプレート
上記のコードをベースにしたLaTeXのテンプレートが以下で配布されています。
https://cloudlatex.io/templates/168

# 参考文献
* [Neural network | TikZ example](http://www.texample.net/tikz/examples/neural-network/)
* [TeXに直接作図しよう！3 – 人ごとな独り言](http://hitgot.org/archives/drawing-in-tex-by-tikz-3/)
* [TikZ で“インラインな”図を描く - Qiita](https://qiita.com/zr_tex8r/items/61d14cec3f54972578ea)
* [How to add caption for a TikZ picture? - TeX - LaTeX Stack Exchange](https://tex.stackexchange.com/questions/24000/how-to-add-caption-for-a-tikz-picture)
* [TikZ — Tasuku Soma's webpage](https://www.opt.mist.i.u-tokyo.ac.jp/~tasuku/tikz.html)
* [オプション - TikZを使ってみよう！ - Cute.Guides at 九州大学 Kyushu University](https://guides.lib.kyushu-u.ac.jp/c.php?g=774891&p=5559141)
* [TikZ - TeX Wiki](https://texwiki.texjp.org/?TikZ)