答案1
这应该可以帮助您入门。我为每种类型的神经元创建了样式,因此您可以根据需要轻松更改样式和间距,而无需接触大量代码。这些样式定义都有详尽的注释,因此您可以看到每一行的作用。
\documentclass[border=5pt]{standalone}
\renewcommand{\vec}[1]{\mathbf{#1}} % re-style the vector
\usepackage{tikz}
\usetikzlibrary{
arrows.meta, % for Straight Barb arrow tip
fit, % to fit the group box around the central neurons
positioning, % for relative positioning of the neurons
}
\tikzset{
neuron/.style={ % style for each neuron
circle,draw,thick, % drawn as a thick circle
inner sep=0pt, % no built-in padding between the text and the circle shape
minimum size=3.5em, % make each neuron the same size regardless of the text inside
node distance=1ex and 2em, % spacing between neurons (y and x)
},
group/.style={ % style for the groups of neurons
rectangle,draw,thick, % drawn as a thick rectangle
inner sep=0pt, % no padding between the node contents and the rectangle shape
},
io/.style={ % style for the inputs/outputs
neuron, % inherit the neuron style
fill=gray!15, % add a fill color
},
conn/.style={ % style for the connections
-{Straight Barb[angle=60:2pt 3]}, % simple barbed arrow tip
thick, % draw in a thick weight to match other drawing elements
},
}
\begin{document}
\begin{tikzpicture}
\node[neuron] (ht1) {$h_t^1$};
\node[neuron,below=of ht1] (htm) {$h_t^{n-m}$};
\node[neuron,below=of htm] (htn) {$h_t^n$};
\node[group,fit={(ht1) (htm) (htn)}] (gr1) {};
\node[neuron,left=of ht1] (ht-1) {$h_{t-1(2)}^1$};
\node[io,above=2em of ht1] (yt) {$y_t$};
\node[io,below=2em of htn] (vt) {$\vec{v}_t$};
\draw[conn] (ht1) -- (yt);
\draw[conn] (vt) -- (htn);
\foreach \destination in {ht1,htm,htn} { % the for loop idea can be expanded to draw the entire diagram quickly
\draw[conn] (ht-1.east) -- (\destination.west);
}
\end{tikzpicture}
\end{document}
结果如下:
好吧,内容有点多!让我们来分析一下。
每个神经元都绘制为一个节点,节点名称放在括号中,节点文本放在花括号中,例如:
\node[neuron] (ht1) {$h_t^1$};
% ^-style ^-name ^-node text
一旦放置了第一个节点,所有其他节点都可以相对于它定位,而无需使用该positioning
库手动计算坐标:
\node[neuron,below=of ht1] (htm) {$h_t^{n-m}$};
% ^-this node should be placed below the first node (ht1)
间距由键的值控制node distance
,我在样式的定义中设置了该值neuron
。
使用库创建围绕中央神经元的组框,fit
以确定节点大小以适合现有节点列表,如下所示:
\node[group,fit={(ht1) (htm) (htn)}] (gr1) {};
% ^-style ^- list of nodes to fit ^-empty node text for this one
这个节点(gr1)
有一个空文本,因为我们只希望该节点能够框住神经元列表,所以我们不需要其中的任何新文本。
一旦绘制了所有神经元,我们就可以用\draw
语句将它们连接起来,这些语句在括号中的两个坐标(此处称为坐标)之间创建描边路径。一个例子:
\draw[conn] (ht1) -- (yt);
% ^ ^-start ^-finish
% `-apply connection style
单独绘制所有这些很快就会变得乏味。幸运的是,Ti钾Z 提供了 for 循环的概念,我用它来创建其他箭头:
\foreach \destination in {ht1,htm,htn} {
\draw[conn] (ht-1.east) -- (\destination.west);
}
我补充.east
说.west
,锚点在我们要绘制的节点上。这会导致绘制到节点边缘上的特定点的连接。如果您不添加这些,箭头将以直线形式从节点中心绘制到节点中心(请注意我在第一个示例中不添加锚点)。
循环思想\foreach
可以扩展,以便高效地绘制完整图表中的许多神经元。你可以查看示例:神经网络是一个很好的例子。
钛钾Z 有出色的文档,但乍一看可能让人不知所措。如果您不明白我为什么这样做,请在手册中搜索宏名称或键名称,以了解其工作原理和功能。您可以在 PC 上通过在texdoc tikz
终端或命令提示符下键入来访问手册。或者,您可以在线访问http://texdoc.net/pkg/tikz(警告:这是一个很大的 PDF 文件)。希望这能帮助您入门!:-)
答案2
实际上不需要太多代码:
\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{fit,positioning,arrows.meta}
\tikzset{neuron/.style={shape=circle, minimum size=1.25cm,
inner sep=0, draw, font=\small}, io/.style={neuron, fill=gray!20}}
\begin{document}
\begin{tikzpicture}[x=2cm, y=1.5cm, >=Stealth]
\foreach \jlabel [count=\j, evaluate={\k=int(mod(\j-1,3)); \jj=int(\j-1);}]
in {t-1, t-1(1), t-1(2), t, t(1), t(2), t+1}{
\foreach \ilabel [count=\i] in {1, n-m, n}
\node [neuron] at (\j, 1-\i) (h-\i-\j){$h_{\jlabel}^{\ilabel}$};
\ifcase\k
\node [fit=(h-1-\j) (h-3-\j), inner sep=0, draw] (b-\j) {};
\node [io, above=of b-\j] (y-\j) {$y_{\jlabel}$};
\node [io, below=of b-\j] (v-\j) {$v_{\jlabel}$};
\draw [->] (v-\j) -- (b-\j);
\draw [->] (b-\j) -- (y-\j);
\fi
\ifnum\j>1
\foreach\i in {1, 2, 3}
\foreach \ii in {1, 2, 3}
\draw [->] (h-\i-\jj.east) -- (h-\ii-\j.west);
\fi
}
\node [left=of h-2-1] {\ldots};
\node [right=of h-2-7] {\ldots};
\end{tikzpicture}
\end{document}