本文主要浅谈 Python 库 sane_tikz 怎么将 Pyhon 绘图代码转成直接可编译的 TikZ( LaTeX)代码,以下测试内容已经默认你下载好 Python 并且安装了 sane_tikz 包(不清楚的见:sane_tikz),相关资源来自:
transformergithub.com/negrinho/sane_tikz/blob/master/examples/transformer.py
下面我们看看怎么使用这个宏包去绘图并输出 TikZ 绘图代码。
Step1:引入 sane_tikz 库及根据绘图需要的其他库
import sane_tikz.core as stz
import sane_tikz.formatting as fmt
import numpy as np
import math
Step2:定义一些绘图参数(线条、长、宽、间距等)
width = 2.5
line_width = 3.0 * fmt.standard_line_width
rectangle_roundness = 0.1
connector_roundness = 0.2
to_add_norm_spacing = 0.15
per_line_height = 0.40
percent_width_trident_spacing = 0.45
plus_circle_radius = 0.2
sine_circle_radius = 2 * plus_circle_radius
spacing_between_text_and_arrows = 0.0
arrow_length = 0.6
residual_spacing = 2.0
trident_alpha = 0.75
trident_spacing = 0.4
spacing_between_towers = 1.5
bbox_spacing = 0.45
bbox_roundness = 0.3
Step3:设置绘图颜色、填充等
name2color = {
"emb_color": (252, 224, 225),
"multi_head_attention_color": (252, 226, 187),
"add_norm_color": (242, 243, 193),
"ff_color": (194, 232, 247),
"softmax_color": (203, 231, 207),
"linear_color": (220, 223, 240),
"gray_bbox_color": (243, 243, 244)
}
s_arr = fmt.combine_tikz_strs(
[fmt.line_width(line_width),
fmt.arrow_heads("end")])
s_lw = fmt.combine_tikz_strs([fmt.line_width(line_width)])
s_con = s_bbox = fmt.combine_tikz_strs([
fmt.arrow_heads("end"),
fmt.line_width(line_width),
fmt.rounded_corners(connector_roundness)
])
s_bbox = fmt.combine_tikz_strs([
fmt.fill_color("gray_bbox_color"),
fmt.line_width(line_width),
fmt.rounded_corners(bbox_roundness)
])
Step4:定义图圆角矩形的颜色填充、字体填充,关联关系,圆的形式等(函数)
def trident_coords(e):
top_left_cs, bottom_right_cs = stz.bbox(e)
center_cs = stz.bottom_center_coords(top_left_cs, bottom_right_cs)
left_cs = stz.translate_coords_horizontally(center_cs,
-trident_alpha * width / 2.0)
right_cs = stz.translate_coords_horizontally(center_cs,
trident_alpha * width / 2.0)
cs_lst = [left_cs, center_cs, right_cs]
translated_cs_lst = [
stz.translate_coords_vertically(cs, -trident_spacing) for cs in cs_lst
]
return cs_lst, translated_cs_lst
def lst2str(s_lst):
return " \\vspace{-0.05cm} \\linebreak ".join(s_lst)
def rectangle(height, color_name):
s_fmt = fmt.combine_tikz_strs([
fmt.line_width(line_width),
fmt.fill_color(color_name),
fmt.rounded_corners(rectangle_roundness)
])
return stz.rectangle_from_width_and_height([0, 0], height, width, s_fmt)
def rectangle_with_text(color_name, s_lst):
height = 0.1 + per_line_height * len(s_lst)
s_width = fmt.combine_tikz_strs([fmt.text_width(width), "align=center"])
r = rectangle(height, color_name)
cs = stz.center_coords(r)
s = " \\vspace{-0.05cm} \\linebreak ".join(s_lst)
t = stz.latex(cs, s, s_width)
return [r, t]
def rectangle_with_add_norm(color_name, s_lst):
r1 = rectangle_with_text("add_norm_color", ["Add \\& Norm"])
r2 = rectangle_with_text(color_name, s_lst)
top_left_cs, bottom_right_cs = stz.bbox(r2)
cs = stz.translate_coords_vertically(
stz.top_center_coords(top_left_cs, bottom_right_cs),
to_add_norm_spacing)
stz.translate_bbox_bottom_center_to_coords(r1, cs)
c = connect_straight_vertical(r2, r1)
return [r1, r2, c]
def connect_straight_vertical(e_from, e_to):
from_cs = stz.coords_from_bbox_with_fn(e_from, stz.top_center_coords)
to_cs = stz.coords_from_bbox_with_fn(e_to, stz.bottom_center_coords)
return stz.line_segment(from_cs, to_cs, s_lw)
def connect_straight_horizontal(e_from, e_to):
from_cs = stz.coords_from_bbox_with_fn(e_from, stz.right_center_coords)
to_cs = stz.coords_from_bbox_with_fn(e_to, stz.left_center_coords)
return stz.line_segment(from_cs, to_cs, s_lw)
def connect_straight_with_arrow(e_from, e_to):
from_cs = stz.coords_from_bbox_with_fn(e_from, stz.top_center_coords)
to_cs = stz.coords_from_bbox_with_fn(e_to, stz.bottom_center_coords)
return stz.line_segment(from_cs, to_cs, s_arr)
def connect_residual(e_with_addnorm, bottom_spacing, side_spacing):
from_cs = stz.coords_from_bbox_with_fn(e_with_addnorm,
stz.bottom_center_coords)
from_cs = stz.translate_coords_vertically(from_cs, -bottom_spacing)
if side_spacing < 0:
to_cs = stz.coords_from_bbox_with_fn(e_with_addnorm[0],
stz.left_center_coords)
else:
to_cs = stz.coords_from_bbox_with_fn(e_with_addnorm[0],
stz.right_center_coords)
cs = stz.translate_coords_horizontally(from_cs, side_spacing)
return stz.open_path([from_cs, cs, [cs[0], to_cs[1]], to_cs], s_con)
def circle_with_sine():
r = sine_circle_radius
alpha = 0.6 * r
delta = 0.02
circle = stz.circle([0, 0], r, s_lw)
k = 2.0 * math.pi
xs = np.linspace(0.0, k)
ys = np.sin(xs)
cs_lst = []
for x, y in zip(xs, ys):
cs_lst.append([
stz.axis_value_to_canvas_value(-r + delta, 0.0, r - delta, k, x),
stz.axis_value_to_canvas_value(-r + delta, -r / alpha, r - delta,
r / alpha, y)
])
sine = stz.open_path(cs_lst, s_lw)
return [circle, sine]
def circle_with_plus():
r = plus_circle_radius
circle = stz.circle([0, 0], r, s_lw)
plus = [
stz.centered_horizontal_line_segment([0, 0], 1.6 * r, s_lw),
stz.centered_vertical_line_segment([0, 0], 1.6 * r, s_lw),
]
return [circle, plus]
def arrow_in(e):
to_cs = stz.coords_from_bbox_with_fn(e, stz.bottom_center_coords)
from_cs = stz.translate_coords_vertically(to_cs, -arrow_length)
return stz.line_segment(from_cs, to_cs, s_arr)
def arrow_out(e):
from_cs = stz.coords_from_bbox_with_fn(e, stz.top_center_coords)
to_cs = stz.translate_coords_vertically(from_cs, arrow_length)
return stz.line_segment(from_cs, to_cs, s_arr)
Step5:绘制左和右半部分图,并链接起来
### left tower
ier = rectangle_with_text("emb_color", ["Input", "Embedding"])
cl = circle_with_plus()
sl = circle_with_sine()
mha1_an = rectangle_with_add_norm("multi_head_attention_color",
["Multi-Head", "Attention"])
ff1_an = rectangle_with_add_norm("ff_color", ["Feed", "Forward"])
stz.place_above_and_align_to_the_center(cl, ier, 0.4)
stz.place_to_the_left_and_align_to_the_center(sl, cl, 0.3)
stz.place_above_and_align_to_the_center(mha1_an, cl, 1.33)
stz.place_above_and_align_to_the_center(ff1_an, mha1_an, 1.0)
### right tower
oer = rectangle_with_text("emb_color", ["Output", "Embedding"])
cr = circle_with_plus()
sr = circle_with_sine()
mha2_an = rectangle_with_add_norm("multi_head_attention_color",
["Multi-Head", "Attention"])
mmha_an = rectangle_with_add_norm("multi_head_attention_color",
["Masked", "Multi-Head", "Attention"])
ff2_an = rectangle_with_add_norm("ff_color", ["Feed", "Forward"])
linear = rectangle_with_text("linear_color", ["Linear"])
softmax = rectangle_with_text("softmax_color", ["Softmax"])
stz.place_to_the_right_and_align_to_the_bottom(oer, ier, spacing_between_towers)
stz.place_above_and_align_to_the_center(cr, oer, 0.4)
stz.place_to_the_right_and_align_to_the_center(sr, cr, 0.3)
stz.place_above_and_align_to_the_center(mmha_an, cr, 1.33)
stz.place_above_and_align_to_the_center(mha2_an, mmha_an, 1.0)
stz.place_above_and_align_to_the_center(ff2_an, mha2_an, 1.0)
stz.place_above_and_align_to_the_center(ff2_an, mha2_an, 1.0)
stz.place_above_and_align_to_the_center(linear, ff2_an, 0.6)
stz.place_above_and_align_to_the_center(softmax, linear, 0.6)
#####
connections = [
connect_straight_with_arrow(mha1_an, ff1_an),
connect_straight_with_arrow(mha2_an, ff2_an),
connect_straight_with_arrow(ff2_an, linear),
connect_straight_with_arrow(linear, softmax),
connect_straight_with_arrow(ier, cl),
connect_straight_with_arrow(cl, mha1_an),
connect_straight_with_arrow(cr, mmha_an),
connect_straight_with_arrow(oer, cr),
connect_straight_horizontal(sl, cl),
connect_straight_horizontal(cr, sr)
]
connections.extend([
connect_residual(ff1_an, 0.6, -residual_spacing),
connect_residual(mha1_an, 0.6, -residual_spacing),
connect_residual(mmha_an, 0.6, residual_spacing),
connect_residual(mha2_an, 0.6, residual_spacing),
connect_residual(ff2_an, 0.6, residual_spacing)
])
Step6:绘制左和右半部分框起来的大图
### bounding boxes
b = stz.bbox([ff1_an, mha1_an, connections[-4]])
bb1 = stz.rectangle_from_additive_resizing(b[0], b[1], bbox_spacing,
bbox_spacing, s_bbox)
b = stz.bbox([ff2_an, mmha_an, connections[-2], connections[-3]])
bb2 = stz.rectangle_from_additive_resizing(b[0], b[1], bbox_spacing,
bbox_spacing, s_bbox)
Step7:带箭头链接线
### trident connections
tri_cs, translated_tri_cs = trident_coords(mha1_an)
e1 = stz.open_path([
translated_tri_cs[1],
stz.bottom_left_coords(translated_tri_cs[1], tri_cs[0]), tri_cs[0]
], s_con)
e2 = stz.open_path([
translated_tri_cs[1],
stz.bottom_right_coords(translated_tri_cs[1], tri_cs[2]), tri_cs[2]
], s_con)
connections.extend([e1, e2])
tri_cs, translated_tri_cs = trident_coords(mmha_an)
e1 = stz.open_path([
translated_tri_cs[1],
stz.bottom_left_coords(translated_tri_cs[1], tri_cs[0]), tri_cs[0]
], s_con)
e2 = stz.open_path([
translated_tri_cs[1],
stz.bottom_right_coords(translated_tri_cs[1], tri_cs[2]), tri_cs[2]
], s_con)
connections.extend([e1, e2])
tri_cs, translated_tri_cs = trident_coords(mha2_an)
# the leftmost two
from_cs = stz.coords_from_bbox_with_fn(ff1_an, stz.top_center_coords)
mid_cs = stz.midway_coords(stz.bbox(bb1)[1], stz.bbox(bb2)[0])
to_cs = translated_tri_cs[0]
cs = stz.translate_coords_vertically(from_cs, 1.0)
e1 = stz.open_path([
from_cs, cs, [mid_cs[0], cs[1]], [mid_cs[0], to_cs[1]],
translated_tri_cs[0], tri_cs[0]
], s_con)
e2 = stz.open_path([
from_cs, cs, [mid_cs[0], cs[1]], [mid_cs[0], to_cs[1]],
translated_tri_cs[1], tri_cs[1]
], s_con)
# the rightmost one
from_cs = stz.coords_from_bbox_with_fn(mmha_an, stz.top_center_coords)
e3 = stz.open_path(
[from_cs, translated_tri_cs[1], translated_tri_cs[2], tri_cs[2]], s_con)
connections.extend([e1, e2, e3])
arrows = [arrow_in(ier), arrow_in(oer), arrow_out(softmax)]
Step8:框内文字填充
### annotations
# arrow text
s_fmt = fmt.combine_tikz_strs(
[fmt.text_width(width), "anchor=north", "align=center"])
cs = stz.translate_coords_vertically(
stz.coords_from_bbox_with_fn(arrows[0], stz.bottom_center_coords),
-spacing_between_text_and_arrows)
a1 = stz.latex(cs, "Inputs", s_fmt)
cs = stz.translate_coords_vertically(
stz.coords_from_bbox_with_fn(arrows[1], stz.bottom_center_coords),
-spacing_between_text_and_arrows)
a2 = stz.latex(cs, lst2str(["Outputs", "(shifted right)"]), s_fmt)
s_fmt = fmt.combine_tikz_strs(
[fmt.text_width(width), "anchor=south", "align=center"])
cs = stz.translate_coords_vertically(
stz.coords_from_bbox_with_fn(arrows[2], stz.top_center_coords),
spacing_between_text_and_arrows)
a3 = stz.latex(cs, lst2str(["Output", "Probabilities"]), s_fmt)
Step9:边上问题填充
# side text
spacing = 0.2
cs = stz.coords_from_bbox_with_fn(bb1, stz.left_center_coords)
a4 = stz.latex([cs[0] - spacing, cs[1]], "$N\\times$",
fmt.anchor("right_center"))
cs = stz.coords_from_bbox_with_fn(bb2, stz.right_center_coords)
a5 = stz.latex([cs[0] + spacing, cs[1]], "$N\\times$",
fmt.anchor("left_center"))
s_fn = lambda side: fmt.combine_tikz_strs(
[fmt.text_width(2.0), fmt.anchor(side + "_center")])
cs = stz.coords_from_bbox_with_fn(sl, stz.left_center_coords)
a6 = stz.latex([cs[0] + 0.3, cs[1]], lst2str(["Positional", "Encoding"]),
s_fn("right"))
cs = stz.coords_from_bbox_with_fn(sr, stz.right_center_coords)
a7 = stz.latex([cs[0] + 0.2, cs[1]], lst2str(["Positional", "Encoding"]),
s_fn("left"))
annotations = [a1, a2, a3, a4, a5, a6, a7]
Step10:最后整合所有的图,生成 transformer.tex 文件:
# all
e = [
bb1, bb2, ier, oer, mha1_an, mha2_an, mmha_an, ff1_an, ff2_an, linear,
softmax, cl, cr, sl, sr, connections, arrows, annotations
]
stz.draw_to_tikz_standalone(e, "transformer.tex", name2color)
最后我们得到直接可编译的 transformer.tex 文件:
\documentclass{standalone}
\usepackage[T1]{fontenc}\usepackage{tikz}
\usepackage{amsmath, amsfonts}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{tikzpicture}
\definecolor{emb_color}{RGB}{252,224,225}
\definecolor{multi_head_attention_color}{RGB}{252,226,187}
\definecolor{add_norm_color}{RGB}{242,243,193}
\definecolor{ff_color}{RGB}{194,232,247}
\definecolor{softmax_color}{RGB}{203,231,207}
\definecolor{linear_color}{RGB}{220,223,240}
\definecolor{gray_bbox_color}{RGB}{243,243,244}
\draw[fill=gray_bbox_color, line width=0.046875cm, rounded corners=0.300000cm] (-0.975000, 6.455000) -- (2.725000, 6.455000) -- (2.725000, 1.305000) -- (-0.975000, 1.305000) -- cycle;
\draw[fill=gray_bbox_color, line width=0.046875cm, rounded corners=0.300000cm] (3.775000, 9.405000) -- (7.475000, 9.405000) -- (7.475000, 1.305000) -- (3.775000, 1.305000) -- cycle;
\draw[line width=0.046875cm, fill=emb_color, rounded corners=0.100000cm] (0.000000, 0.000000) -- (2.500000, 0.000000) -- (2.500000, -0.900000) -- (0.000000, -0.900000) -- cycle;
\node[text width=2.500000cm, align=center] at (1.250000,-0.450000) {Input \vspace{-0.05cm} \linebreak Embedding};
\draw[line width=0.046875cm, fill=emb_color, rounded corners=0.100000cm] (4.000000, 0.000000) -- (6.500000, 0.000000) -- (6.500000, -0.900000) -- (4.000000, -0.900000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,-0.450000) {Output
\vspace{-0.05cm} \linebreak Embedding};
\draw[line width=0.046875cm, fill=add_norm_color, rounded corners=0.100000cm] (0.000000, 3.680000) -- (2.500000, 3.680000) -- (2.500000, 3.180000) -- (0.000000, 3.180000) -- cycle;
\node[text width=2.500000cm, align=center] at (1.250000,3.430000) {Add \& Norm};
\draw[line width=0.046875cm, fill=multi_head_attention_color, rounded corners=0.100000cm] (0.000000, 3.030000) -- (2.500000, 3.030000) -- (2.500000, 2.130000) -- (0.000000, 2.130000) -- cycle;
\node[text width=2.500000cm, align=center] at (1.250000,2.580000) {Multi-Head \vspace{-0.05cm} \linebreak Attention};
\draw[line width=0.046875cm] (1.250000, 3.030000) -- (1.250000, 3.180000);
\draw[line width=0.046875cm, fill=add_norm_color, rounded corners=0.100000cm] (4.000000, 6.630000) -- (6.500000, 6.630000) -- (6.500000, 6.130000) -- (4.000000, 6.130000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,6.380000) {Add \& Norm};
\draw[line width=0.046875cm, fill=multi_head_attention_color, rounded corners=0.100000cm] (4.000000, 5.980000) -- (6.500000, 5.980000) -- (6.500000, 5.080000) -- (4.000000, 5.080000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,5.530000) {Multi-Head \vspace{-0.05cm} \linebreak Attention};
\draw[line width=0.046875cm] (5.250000, 5.980000) -- (5.250000, 6.130000);
\draw[line width=0.046875cm, fill=add_norm_color, rounded corners=0.100000cm] (4.000000, 4.080000) -- (6.500000, 4.080000) -- (6.500000, 3.580000) -- (4.000000, 3.580000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,3.830000) {Add \& Norm};
\draw[line width=0.046875cm, fill=multi_head_attention_color, rounded corners=0.100000cm] (4.000000, 3.430000) -- (6.500000, 3.430000) -- (6.500000, 2.130000) -- (4.000000, 2.130000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,2.780000) {Masked \vspace{-0.05cm} \linebreak Multi-Head \vspace{-0.05cm} \linebreak Attention};
\draw[line width=0.046875cm] (5.250000, 3.430000) -- (5.250000, 3.580000);
\draw[line width=0.046875cm, fill=add_norm_color, rounded corners=0.100000cm] (0.000000, 6.230000) -- (2.500000, 6.230000) -- (2.500000, 5.730000) -- (0.000000, 5.730000) -- cycle;
\node[text width=2.500000cm, align=center] at (1.250000,5.980000) {Add \& Norm};
\draw[line width=0.046875cm, fill=ff_color, rounded corners=0.100000cm] (0.000000, 5.580000) -- (2.500000, 5.580000) -- (2.500000, 4.680000) -- (0.000000, 4.680000) -- cycle;
\node[text width=2.500000cm, align=center] at (1.250000,5.130000) {Feed \vspace{-0.05cm} \linebreak Forward};
\draw[line width=0.046875cm] (1.250000, 5.580000) -- (1.250000, 5.730000);
\draw[line width=0.046875cm, fill=add_norm_color, rounded corners=0.100000cm] (4.000000, 9.180000) -- (6.500000, 9.180000) -- (6.500000, 8.680000) -- (4.000000, 8.680000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,8.930000) {Add
\& Norm};
\draw[line width=0.046875cm, fill=ff_color, rounded corners=0.100000cm] (4.000000, 8.530000) -- (6.500000, 8.530000) -- (6.500000, 7.630000) -- (4.000000, 7.630000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,8.080000) {Feed \vspace{-0.05cm} \linebreak Forward};
\draw[line width=0.046875cm] (5.250000, 8.530000) -- (5.250000, 8.680000);
\draw[line width=0.046875cm, fill=linear_color, rounded corners=0.100000cm] (4.000000, 10.280000) -- (6.500000, 10.280000) -- (6.500000, 9.780000) -- (4.000000, 9.780000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,10.030000) {Linear};
\draw[line width=0.046875cm, fill=softmax_color, rounded corners=0.100000cm] (4.000000, 11.380000) -- (6.500000, 11.380000) -- (6.500000, 10.880000) -- (4.000000, 10.880000) -- cycle;
\node[text width=2.500000cm, align=center] at (5.250000,11.130000) {Softmax};
\draw[line width=0.046875cm] (1.250000, 0.600000) circle (0.200000);
\draw[line width=0.046875cm] (1.410000, 0.600000) -- (1.090000, 0.600000);
\draw[line width=0.046875cm] (1.250000, 0.760000) -- (1.250000, 0.440000);
\draw[line width=0.046875cm] (5.250000, 0.600000) circle (0.200000);
\draw[line width=0.046875cm] (5.410000, 0.600000) -- (5.090000, 0.600000);
\draw[line width=0.046875cm] (5.250000, 0.760000) -- (5.250000, 0.440000);
\draw[line width=0.046875cm] (0.350000, 0.600000) circle (0.400000);
\draw[line width=0.046875cm] (-0.030000, 0.600000) -- (-0.014490, 0.629156) -- (0.001020, 0.657833) -- (0.016531, 0.685561) -- (0.032041, 0.711884) -- (0.047551, 0.736369) -- (0.063061, 0.758616) -- (0.078571, 0.778258) -- (0.094082, 0.794973) -- (0.109592, 0.808486) -- (0.125102, 0.818576) -- (0.140612, 0.825077) -- (0.156122, 0.827883) -- (0.171633, 0.826946) -- (0.187143, 0.822284) -- (0.202653, 0.813971) -- (0.218163, 0.802145) -- (0.233673, 0.786999) -- (0.249184, 0.768783) -- (0.264694, 0.747796) -- (0.280204, 0.724382) -- (0.295714, 0.698925) -- (0.311224, 0.671845) -- (0.326735, 0.643584) -- (0.342245, 0.614608) -- (0.357755, 0.585392) -- (0.373265, 0.556416) -- (0.388776, 0.528155) -- (0.404286, 0.501075) -- (0.419796, 0.475618) -- (0.435306, 0.452204) -- (0.450816, 0.431217) -- (0.466327, 0.413001) -- (0.481837, 0.397855) -- (0.497347, 0.386029) -- (0.512857, 0.377716) -- (0.528367, 0.373054) -- (0.543878, 0.372117) -- (0.559388, 0.374923) -- (0.574898, 0.381424) -- (0.590408, 0.391514) -- (0.605918, 0.405027) -- (0.621429, 0.421742) -- (0.636939, 0.441384) -- (0.652449, 0.463631) -- (0.667959, 0.488116) -- (0.683469, 0.514439) -- (0.698980, 0.542167) -- (0.714490, 0.570844) -- (0.730000, 0.600000);
\draw[line width=0.046875cm] (6.150000, 0.600000) circle (0.400000);
\draw[line width=0.046875cm] (5.770000, 0.600000) -- (5.785510, 0.629156) -- (5.801020, 0.657833) -- (5.816531, 0.685561) -- (5.832041, 0.711884) -- (5.847551, 0.736369) -- (5.863061, 0.758616) -- (5.878571, 0.778258) -- (5.894082, 0.794973) -- (5.909592, 0.808486) -- (5.925102, 0.818576) -- (5.940612, 0.825077) -- (5.956122, 0.827883) -- (5.971633, 0.826946) -- (5.987143, 0.822284) -- (6.002653, 0.813971) -- (6.018163, 0.802145) -- (6.033673, 0.786999) -- (6.049184, 0.768783) -- (6.064694, 0.747796) -- (6.080204, 0.724382) -- (6.095714, 0.698925) -- (6.111224, 0.671845) -- (6.126735, 0.643584) -- (6.142245, 0.614608) -- (6.157755, 0.585392) -- (6.173265, 0.556416) -- (6.188776, 0.528155) -- (6.204286, 0.501075) -- (6.219796, 0.475618) -- (6.235306, 0.452204) -- (6.250816, 0.431217) -- (6.266327, 0.413001) -- (6.281837, 0.397855) -- (6.297347, 0.386029) -- (6.312857, 0.377716) -- (6.328367, 0.373054) -- (6.343878, 0.372117) -- (6.359388, 0.374923) -- (6.374898, 0.381424) -- (6.390408, 0.391514) -- (6.405918, 0.405027) -- (6.421429, 0.421742) -- (6.436939, 0.441384) -- (6.452449, 0.463631) -- (6.467959, 0.488116) -- (6.483469, 0.514439) -- (6.498980, 0.542167) -- (6.514490, 0.570844) -- (6.530000, 0.600000);
\draw[line width=0.046875cm, -latex] (1.250000, 3.680000) -- (1.250000, 4.680000);
\draw[line width=0.046875cm, -latex] (5.250000, 6.630000) -- (5.250000, 7.630000);
\draw[line width=0.046875cm, -latex] (5.250000, 9.180000) -- (5.250000, 9.780000);
\draw[line width=0.046875cm, -latex] (5.250000, 10.280000) -- (5.250000, 10.880000);
\draw[line width=0.046875cm, -latex] (1.250000, 0.000000) -- (1.250000, 0.400000);
\draw[line width=0.046875cm, -latex] (1.250000, 0.800000) -- (1.250000, 2.130000);
\draw
[line width=0.046875cm, -latex] (5.250000, 0.800000) -- (5.250000, 2.130000);
\draw[line width=0.046875cm, -latex] (5.250000, 0.000000) -- (5.250000, 0.400000);
\draw[line width=0.046875cm] (0.750000, 0.600000) -- (1.050000, 0.600000);
\draw[line width=0.046875cm] (5.450000, 0.600000) -- (5.750000, 0.600000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (1.250000, 4.080000) -- (-0.750000, 4.080000) -- (-0.750000, 5.980000) -- (0.000000, 5.980000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (1.250000, 1.530000) -- (-0.750000, 1.530000) -- (-0.750000, 3.430000) -- (0.000000, 3.430000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (5.250000, 1.530000) -- (7.250000, 1.530000) -- (7.250000, 3.830000) -- (6.500000, 3.830000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (5.250000, 4.480000) -- (7.250000, 4.480000) -- (7.250000, 6.380000) -- (6.500000, 6.380000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (5.250000, 7.030000) -- (7.250000, 7.030000) -- (7.250000, 8.930000) -- (6.500000, 8.930000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (1.250000, 1.730000) -- (0.312500, 1.730000) -- (0.312500, 2.130000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (1.250000, 1.730000) -- (2.187500, 1.730000) -- (2.187500, 2.130000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (5.250000, 1.730000) -- (4.312500, 1.730000) -- (4.312500, 2.130000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (5.250000, 1.730000) -- (6.187500, 1.730000) -- (6.187500, 2.130000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (1.250000, 6.230000) -- (1.250000, 7.230000) -- (3.250000, 7.230000) -- (3.250000, 4.680000) -- (4.312500, 4.680000) -- (4.312500, 5.080000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (1.250000, 6.230000) -- (1.250000, 7.230000) -- (3.250000, 7.230000) -- (3.250000, 4.680000) -- (5.250000, 4.680000) -- (5.250000, 5.080000);
\draw[-latex, line width=0.046875cm, rounded corners=0.200000cm] (5.250000, 4.080000) -- (5.250000, 4.680000) -- (6.187500, 4.680000) -- (6.187500, 5.080000);
\draw[line width=0.046875cm, -latex] (1.250000, -1.500000) -- (1.250000, -0.900000);
\draw[line width=0.046875cm, -latex] (5.250000, -1.500000) -- (5.250000, -0.900000);
\draw[line width=0.046875cm, -latex] (5.250000, 11.380000) -- (5.250000, 11.980000);
\node[text width=2.500000cm, anchor=north, align=center] at (1.250000,-1.500000) {Inputs};
\node[text width=2.500000cm, anchor=north, align=center] at (5.250000,-1.500000) {Outputs \vspace{-0.05cm} \linebreak (shifted right)};
\node[text width=2.500000cm, anchor=south, align=center] at (5.250000,11.980000) {Output \vspace{-0.05cm} \linebreak Probabilities};
\node[anchor=east] at (-1.175000,3.880000) {$N\times$};
\node[anchor=west] at (7.675000,5.355000) {$N\times$};
\node[text width=2.000000cm, anchor=east] at (0.250000,0.600000) {Positional \vspace{-0.05cm} \linebreak Encoding};
\node[text width=2.000000cm, anchor=west]
at (6.750000,0.600000) {Positional \vspace{-0.05cm} \linebreak Encoding};
\end{tikzpicture}
\end{document}
总结优点:
- Python 代码导出的 TikZ 图编译出的 PDF 是矢量图;
- 导出的文件是整个 LaTeX 文件,可以直接编译,满足懒人生成式作图方法;