想把一个小型神经网络说明白,可以用 Graphviz 把输入、线性层、激活函数和输出连成图,并在每一步标上张量尺寸。这里手工描述一个已知结构:4 个输入特征、8 个隐藏单元、3 个输出类别。Graphviz 负责布局绘图,不会自动推断任意训练模型的内部结构。
先定尺寸,再画连线
用 B 表示一次输入的样本数量,也叫 batch size。本例采用 NumPy 矩阵乘法的权重约定:

| 步骤 | 操作 | 输出尺寸 |
|---|---|---|
| 输入 | 每个样本 4 个特征 | [B, 4] |
| 第一线性层 | X @ W1 + b1,W1 为 [4, 8] | [B, 8] |
| ReLU | 负值变为 0 | [B, 8] |
| 第二线性层 | H @ W2 + b2,W2 为 [8, 3] | [B, 3],未归一化分数 |
| Softmax | 在每行的三个类别上归一化 | [B, 3],概率 |
不同框架保存权重的方向可能不同。图上的 [4, 8] 对应本例的 X @ W1,复制到其他框架前请核对该层的真实权重格式。Softmax 表示本教程推理时把分数转成概率的步骤;训练时是否显式调用它,应以所用损失函数的接口为准。
Python 包和绘图程序要分别准备
Python graphviz 官方手册说明:Python 包用于描述图,实际渲染依赖系统中的 Graphviz,且 dot 必须位于 PATH。先安装 Python 包,再从Graphviz 官方下载页按操作系统安装绘图程序。安装后重新打开终端检查:
python -m pip install graphviz numpy
dot -V
本教程在 Windows 11、Python 3.13.14、graphviz 0.21、NumPy 2.5.3 和 Graphviz 16.1.0 下实际生成了 DOT、SVG 和 PNG,并运行了尺寸核对。绘图引擎来自官方 64 位 ZIP,校验下载页提供的 SHA-256 后解压使用;将其 bin 目录加入当前终端的 PATH,再运行脚本即可,无需把 Python 包误当成绘图引擎。
用代码生成可编辑的结构图源码
保存为 network_diagram.py,执行 python network_diagram.py。图从左向右排列,节点用方框,标签中的 \n 是 Graphviz 换行符。
from pathlib import Path
import shutil
from graphviz import Digraph
graph = Digraph('small_mlp', format='svg')
graph.attr(rankdir='LR')
graph.attr('node', shape='box', fontname='Arial')
graph.node('input', r'Input\n[B, 4]')
graph.node('dense1', r'Linear 4 -> 8\nW1 [4, 8], b1 [8]\n[B, 8]')
graph.node('relu', r'ReLU\n[B, 8]')
graph.node('dense2', r'Linear 8 -> 3\nW2 [8, 3], b2 [3]\n[B, 3] logits')
graph.node('prob', r'Softmax(dim=1)\n[B, 3] probabilities')
graph.edges([('input', 'dense1'), ('dense1', 'relu'),
('relu', 'dense2'), ('dense2', 'prob')])
source = graph.save(filename='network.gv')
assert Path(source).is_file()
print('DOT saved:', source)
if shutil.which('dot'):
print('SVG rendered:', graph.render(filename='network.gv', cleanup=False))
else:
print('dot not found; SVG rendering not executed')
无论是否装好 dot,都应先看到 network.gv。打开它,核对有五个节点和四条有向边,并检查输入、隐藏层、输出三个尺寸是否分别为 [B, 4]、[B, 8]、[B, 3]。本机保存源码的这一步已执行成功。
dot 可用时,代码会再生成 network.gv.svg,用浏览器打开它;也可以在终端执行 dot -Tsvg network.gv -o network.svg。先运行 dot -V 确认程序可见,再执行渲染,不应把单独安装 Python 包当成绘图环境已经完整。
让实际数组检查图中的尺寸
图上写着 [B, 8] 不代表计算一定正确。保存下列代码为 shape_check.py,执行 python shape_check.py;这是随机权重的前向计算演示,没有训练模型或准确率承诺。
import numpy as np
rng = np.random.default_rng(42)
B = 2
X = rng.normal(size=(B, 4))
W1, b1 = rng.normal(size=(4, 8)), np.zeros(8)
W2, b2 = rng.normal(size=(8, 3)), np.zeros(3)
H = np.maximum(0, X @ W1 + b1)
logits = H @ W2 + b2
shifted = logits - logits.max(axis=1, keepdims=True)
exp = np.exp(shifted)
prob = exp / exp.sum(axis=1, keepdims=True)
assert X.shape == (2, 4) and H.shape == (2, 8) and logits.shape == (2, 3)
assert prob.shape == (2, 3) and np.allclose(prob.sum(axis=1), 1)
print('X:', X.shape, 'H:', H.shape, 'logits:', logits.shape, 'prob:', prob.shape)
print('prob row sums:', prob.sum(axis=1))
本机输出为 X: (2, 4) H: (2, 8) logits: (2, 3) prob: (2, 3),概率的两行之和均为 1。这里 Softmax 先减去每行最大分数,减少指数计算溢出的风险;断言会检查实际形状和每行归一化结果。
图有了,怎样判断能否给别人看
- 每条箭头代表一次数据流,层名称与实际代码一致。
- 标清 B 是批量大小,不把它写成固定输入特征数量。
- 说明图是自己描述的结构,还是读取模型自动生成;本例是手工描述的教学示意。
- SVG 打开后检查文字没有被裁切,箭头方向正确。换中文标签时检查字体是否存在,出现方框就更换字体或保留英文层名。
如果出现 ExecutableNotFound 或提示找不到 dot,先处理系统安装和 PATH,再重开终端;若矩阵乘法报尺寸不匹配,应先改计算代码和尺寸表,不能只修改图上标签来掩盖问题。本图也不能证明模型精度、运行速度或显存占用。
问答:多加一个隐藏层,应该改哪几处?
例如新增 8 到 6 的线性层:在图中增加 [B, 6] 节点和连线,把最后的权重改成 [6, 3],同时修改验证代码的矩阵尺寸并重跑断言。只在图里添一个方框,没有修改实际数组验证,就还没核对新结构。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30309.html