TikZ绘图实例——LSTM元胞结构图

本文作者分享了学习TikZ的心得,并提供了使用TikZ绘制LSTM元胞结构的实例,通过类比前端开发,解释了TikZ绘图的结构,强调了TikZ在矢量图绘制中的强大功能和学习乐趣。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

总结一下最近学习 T i k Z \mathrm{Ti}k\mathrm{Z} TikZ时候的一些心得,以及使用 T i k Z \mathrm{Ti}k\mathrm{Z} TikZ绘制LSTM元胞结构的一个小例子。在之前的文章中,我曾经尝试过使用 T i k Z \mathrm{Ti}k\mathrm{Z} TikZ绘制组合数学中的棋盘格(有兴趣的话请看《LaTeX TikZ绘图包——组合数学中棋盘格的画法》),经过一周多的学习(啃文档),终于大概理解了 T i k Z \mathrm{Ti}k\mathrm{Z} TikZ的精妙,在一篇stackflow的问答中(How do I draw an LSTM cell in Tikz?

Windows 10 x64

MiKTeX 20.10+TeXworks

TikZ是什么?

T i k Z \mathrm{Ti}k\mathrm{Z} TikZ T i k Z \mathrm{Ti}k\mathrm{Z} TikZ ist kein Zeichenprogramm)是以PGF(portable graphic format)为后端的一个绘图前端,用于绘制矢量图(几何,图论等),由Till Tantau教授等开发,以 TeX \TeX TEX为引擎,在矢量图绘图方面十分强大,可惜学习曲线比较陡峭,而且目前没有相关的中文书籍(下面的官方文档中译版内容不全),所以只能多看多练,当然也可以借助 T i k Z E d t \mathrm{Ti}k\mathrm{ZEdt} TikZEdt编辑器可视化生成图形。

学习的心得体会

从一开始逐字逐句看文档,到后来结合文档中的具体例子一点一点实现,感觉自己对其绘图的语句有一点点理解了, T i k Z \mathrm{Ti}k\mathrm{Z} TikZ绘图的主要结构其实理解成web前端,内容(html)与样式(CSS)分离,这样可以方便地扩展图形,再到后来需要一些装饰,都可以在 T i k Z s e t \mathrm{Ti}k\mathrm{Zset} TikZset中实现,之后如果要再添加一些功能,就需要一些更高级的扩展包来实现了,这里类比一下JS应该不过分😆.

总之,引用stack exchange的一句话, T i k Z \mathrm{Ti}k\mathrm{Z} TikZ真的会让人上瘾!看那些精美的图形,是否你也跃跃欲试了呢?

LSTM元胞结构图的绘制

以下是一个 T i k Z \mathrm{Ti}k\mathrm{Z} TikZ绘图的小例子,参考了stackexchange网站的代码,加上了一些自己喜欢的配置(配色丑,见谅……),总体来说在代码实现上不难。

%cite by https://tex.stackexchange.com/questions/432312/how-do-i-draw-an-lstm-cell-in-tikz

\documentclass[tikz,border=10pt]{standalone}
% 使用宏包:bm用于加粗数学符号,ctex用于中文支持,xcolor用于配色
\usepackage{bm,ctex,xcolor}
% 使用TikZ内部的扩展包:calc计算两点间等分点,arrows.meta用于定制箭头样式,shapes用于椭圆的生成
\usetikzlibrary{calc, positioning, arrows.meta, shapes}


% 定义新命令 \vars{var1}{var2}用于符号的定制
\newcommand{\vars}[2]{${\bm#1}_{\bm#2}$}

\begin{document}

\begin{tikzpicture}[
    % 定义样式
    myfont/.style={
        font=\footnotesize\sffamily
    },
    frame/.style={% 外部边框(圆角矩形)的样式
        rectangle, 
        rounded corners=5mm, 
        draw,gray,
        fill=lime!45,
        very thick,
    },
    add/.style={% 加操作符的样式
        circle,
        draw, thick,
        fill=yellow!60,
        inner sep=.5pt,
        minimum height =3mm,
    },
    prod/.style={% 乘操作符的样式
        circle,
        draw, thick,
        fill=lightgray!40!blue!30,
        inner sep=.5pt,
        minimum height =3mm,
    },
    function/.style={% 信息处理函数(tanh)的样式
        ellipse,
        draw, thick,
        fill=cyan!30,
        inner sep=1pt
    },
    cell/.style={%C_t和C_{t-1}的样式
        circle,draw,fill=magenta!30,
        line width = .75pt,
        minimum width=8mm,
        inner sep=1pt,
    },
    hidden/.style={% h_t和h_{t-1}的样式
        circle,draw,fill=orange!50,
        line width = .75pt,
        minimum width=8mm,
        inner sep=1pt,
    },
    input/.style={% x_t的样式
        circle,draw,
        fill=teal!30,
        line width = .75pt,
        minimum width=8mm,
        inner sep=1pt,
    },
    actfunc/.style={% 激活函数的样式
        rectangle, draw, 
        fill=pink!30,
        minimum width=4.25mm,
        minimum height=3.75mm,
        inner sep=1pt,
        thick,
    },
    ArrowC1/.style={% 线段的圆角样式
        rounded corners=2mm,
        >=Stealth[round],
        very thick,
    },
    ArrowC2/.style={% 弧度略大的圆角样式
        rounded corners=3mm,
        >=Stealth[round],
        very thick,
    },
]


% 图形绘制部分  
    % 绘制外部圆角边框
    \node [frame, minimum height =4cm, minimum width=6cm] at (0,0) {};

    % 绘制激活函数结点
    \node [actfunc] (ibox1) at (-2,-0.8) {$\bm\sigma$};
    \node [actfunc] (ibox2) at (-1.35,-0.8) {$\bm\sigma$};
    \node [actfunc, minimum width=9mm] (ibox3) at (-0.45,-0.8) {$\bm\tanh$};
    \node [actfunc] (ibox4) at (0.5,-0.8) {$\bm\sigma$};

   % 绘制操作符结点
    \node [prod] (mux1) at (-2,1.5) {$\bm\times$};
    \node [add] (add1) at (-0.5,1.5) {$\bm+$};
    \node [prod] (mux2) at (-0.5,0) {$\bm\times$};
    \node [prod] (mux3) at (1.5,0) {$\bm\times$};
    \node [function] (func1) at (1.5,0.75) {$\bm\tanh$};

    % 绘制神经元外部输入节点
    \node[cell, label={[myfont]above:长时记忆输入}] (c) at (-4,1.5) {\vars{c}{t-1}};
    \node[hidden, label={[myfont]above:隐层输入}] (h) at (-4,-1.5) {\vars{h}{t-1}};
    \node[input, label={[myfont]right:输入}] (x) at (-2.5,-3) {\vars{x}{t}};

    % 绘制神经元外部输出节点
    \node[cell, label={[myfont]above:长时记忆输出}] (c2) at (4,1.5) {\vars{c}{t}};
    \node[hidden, label={[myfont]below:短时记忆输出}] (h2) at (4,-1.5) {\vars{h}{t}};
    \node[hidden, label={[myfont]left:输出}] (x2) at (2.5,3) {\vars{h}{t}};

% 绘制各节点之间的连接线
    % 使用相交和位移
    % 绘制C_{t-1}到C_t的线
    \draw [->, ArrowC1] (c) -- (mux1) -- (add1) -- (c2);

    % 绘制输入线段
    \draw [ArrowC2] (h) -| (ibox4);
    \draw [ArrowC1] (h) -| (ibox1); 
    \draw [ArrowC1] (h) -| (ibox2);
    \draw [ArrowC1] (h) -| (ibox3);
    \draw [ArrowC1] (x) -- (x |- h) -| (ibox1);

    % 内部线段(带箭头)
    \draw [->, ArrowC2] (ibox1) -- (mux1); 
    \node [label=left:$\bm{f_t}$,right=1.5pt] () at ($(ibox1)!.5!(mux1)$) {};
    \draw [->, ArrowC2] (ibox2) |- (mux2);
    \node [label=left:$\bm{i_t}$, right=2pt] () at (ibox2 |- mux2) {};
    \draw [->, ArrowC2] (ibox3) -- (mux2);
    \node [label=right:$\bm{\tilde{C}_t}$, left=.5pt] () at ($(ibox3)!.5!(mux2)$) {};
    \draw [->, ArrowC2] (ibox4) |- (mux3);
    \node [label=left:$\bm{o_t}$, right=2pt] () at (ibox4 |- mux3) {};
    \draw [->, ArrowC2] (mux2) -- (add1);
    \draw [->, ArrowC1] (add1) -| (func1);
    \draw [->, ArrowC2] (func1) -- (mux3);

    %输出线段
    \draw [->, ArrowC2] (mux3) |- (h2);
    %标记出现缺口线段的下端点
    \draw (c2 -| x2) ++(0,-0.15) coordinate (i1);
    \draw [-, ArrowC2] (h2 -| x2) -| (i1);
    \draw [->, ArrowC2] (i1)++(0,0.3) -- (x2);



\end{tikzpicture}
\end{document}

编译结果:

1

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zorchp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值