- 机器学习
- 深度学习
【免费下载链接】leaf
Open Machine Intelligence Framework for Hackers. (GPU/CPU)
本指南围绕 Leaf(Open Machine Intelligence Framework for Hackers,GPU/CPU)官方术语文档(doc/src/deep-learning-glossary.md)中的两个核心概念——Layer(层)与Network(网络)——展开。你将理解 Leaf 对"层"与"网络"的独特定义、二者之间的层级关系,以及"一切皆 Layer"的设计哲学如何在源码层面落地;读完可准确使用LayerConfig构建单个层,并通过容器层(Container Layer)把它们连接成可执行、可训练的神经网络。
从 Glossary 看 Leaf 的术语体系
Leaf 的术语表(Glossary)只收录了两个词条:Layer 与 Network。这不是文档偷懒,而是刻意为之——在 Leaf 中,整个框架只有 Layer 这一种构建块,Network 也不过是"由其他 Layer 组成的 Layer"。理解这两个概念,就掌握了 Leaf 设计的主线。
Layer:神经网络中的最高级构建块
通用理解(In General)
在(深度)神经网络中,Layer 是最高级别的构建块(the highest-level building block)。一个层通常是一个容器:
- 接收加权输入;
- 对输入进行变换;
- 将结果作为输出传递给下一层。
一个层通常只包含一种类型的函数(如 ReLU、池化、卷积等),这样便于与网络的其他部分进行比较。网络中第一个和最后一个层分别被称为输入层(input layer)与输出层(output layer),两者之间的所有层统称为隐藏层(hidden layers)。
Leaf 中的 Layer(In Leaf)
在 Leaf 中,Layer 与上述通用理解高度一致。一个 Leaf 层同样满足三点:
- 是最高级别的构建块;
- 需要接收输入,可能对其进行变换,并需要返回结果;
- 应当是单一职责的(uniform)——它只做一种类型的函数。
关键差异在于:Leaf 层可以实现的远不止神经网络相关的功能。术语文档明确写道:Leaf 层可以实现任何功能,而非仅限于 ReLU、池化、LSTM 等神经网络操作。例如Sequential层就是一个典型例子——它是一个容器层,作用是"连接多个层,从而创建一个网络"。也就是说,"连接其他层"这一行为本身,在 Leaf 中也被实现为一个 Layer。
这一点与文档 doc/src/layers.md 的论述互为印证:"Layers are the only building blocks in Leaf. As we will see later on, everything is a layer. Even when we construct networks, we are still just working with layers composed of smaller layers."(Layer 是 Leaf 中唯一的构建块,即使我们构造网络,也不过是在处理由更小的层组成的层。)
源码佐证:Layer 的通用结构与生命周期
在 src/layer.rs 中,Layer<B: IBackend>是包裹所有具体层实现的通用结构。它的核心字段包括:
| 字段 | 作用 |
|---|---|
name: String | 标识该层,主要用于日志输出 |
config: Box<LayerConfig> | 层的配置 |
worker: Box<ILayer<B>> | 层的具体实现,负责大部分计算(forward / backward) |
weights_data/weights_gradient | 权重及其梯度的共享引用(SharedTensor) |
input_blobs_data/input_blobs_gradient | 输入数据的共享引用 |
output_blobs_data/output_blobs_gradient | 输出数据的共享引用 |
loss: Vec<f32> | 每个输出 blob 对网络损失的贡献权重 |
ILayertrait 则定义了所有层必须遵循的通用行为契约(src/layer.rs):
forward:计算前向输出,内部获取输入张量的读锁、输出张量的写锁,再调用compute_output;backward_input:计算关于输入的梯度(反向传播),调用compute_input_gradient;backward_parameters:计算关于权重/偏置等参数的梯度,调用compute_parameters_gradient;- 配套的生命周期钩子:
init(一次性初始化,如预计算常量)、reshape(根据输入形状调整输出/权重形状)、sync(将各 blob 同步到计算设备)等。
这与术语文档对 Layer "接收输入、变换、返回结果"的定义完全对应:无论层内部做什么,只要实现了这套输入/输出契约,就可以被堆叠进网络。
源码佐证:LayerConfig 与 worker 的分工
Leaf 的层不是直接new出来的,而是通过LayerConfig描述、再由Layer::from_config(backend, &config)生成。LayerConfig(src/layer.rs)包含:
pub struct LayerConfig { pub name: String, // 层名称 pub layer_type: LayerType, // 层类型(决定 worker 的具体实现) pub outputs: Vec<String>, // 每个输出 blob 的名称 pub inputs: Vec<String>, // 每个输入 blob 的名称 pub params: Vec<WeightConfig>, // 每个权重 blob 的训练配置 pub propagate_down: Vec<bool>, // 哪些输入跳过反向传播 }Layer::from_config会根据layer_type匹配到具体的 worker 实现,例如Linear、ReLU、Sigmoid、Sequential、Reshape、NegativeLogLikelihood等(见worker_from_config的match,src/layer.rs)。因此文档 doc/src/layers.md 中的最小示例是完全可运行的:
// 构造一个输出 500 个节点的全连接层配置 let linear_1: LayerConfig = LayerConfig::new("linear1", LinearConfig { output_size: 500 }); // 将其变成一个已初始化、可直接运行的 Layer let linear_network_with_one_layer: Layer = Layer::from_config(backend, &linear_1);在layer.rs的worker_from_config实现中,LayerType::Linear(layer_config)会构造Linear::from_config(&layer_config),这正是该示例中 worker 字段是一个Linear实现的原因。
源码佐证:层实现示例
以 src/layers/activation/relu.rs 中的 ReLU 层为例,其注释明确定义:非线性激活函数y = max(0, x),并且它通常比 Sigmoid/Tanh 更快。ReLU 层不持有任何权重,只有 reshape 逻辑(将输入、输出、梯度调整到与输入一致)与relu_plain/relu_grad_plain的计算调用。
其他已实现层同样遵循统一的接口:
- Linear(全连接层):
y = a * x + b,输入一维直接变换、二维时第一维视为 batch size;自动创建权重 blob,并用 Glorot(Xavier)填充器初始化(src/layers/common/linear.rs); - Sigmoid(激活层):
y = (1 + e^(-x))^(-1)(src/layers/activation/sigmoid.rs); - NegativeLogLikelihood(损失层):对比输出与目标值并分配损失,通常是网络的最后一层(src/layers/loss/negative_log_likelihood.rs);
- Reshape / Flatten(工具层):调整张量形状,如把
n * c * h * w展平成n * (c*h*w)(src/layers/utility/reshape.rs、src/layers/utility/flatten.rs)。
测试用例 tests/layer_specs.rs 也验证了由SequentialConfig组合 Linear + Sigmoid + Linear 可以构造出一个完整的简单网络并正常运行。
Network:由 Layer 组成的图
通用理解(In General)
网络,通常也被称为神经网络(Neural Network, NN)或人工神经网络(Artificial Neural Network, ANN),是机器学习方法的一个子集。术语文档还列举了其他机器学习方法作为对照(并非穷举):线性回归(Linear Regression)、SVM、遗传/进化算法(Genetic/Evolution Algorithms)、动态规划(dynamic programming)、确定性算法优化方法(deterministic algorithmic optimization methods)。
也就是说,在 Leaf 的语境里,"网络"并不限定于神经网络,它泛指由层构成的任何计算图。
Leaf 中的 Network(In Leaf)
在 Leaf 中,网络被定义为一个或多个层的图(graph,即一个连接的集合)。这个网络可以是人工神经网络方法,也可以是其他机器学习方法,甚至可以是任何与机器学习无关的方法。
术语文档在这里给出了一个非常关键、也最容易让人困惑的陈述:
"As described in 2. Layers a network in Leaf is actually a layer which connects other layers."(如 Layers 章节所述,Leaf 中的网络实际上是一个连接了其他层的层。)
这正是"一切皆 Layer"哲学的集中体现:Network 不是与 Layer 并列的另一种实体,而是 Layer 的一种特例(容器层)。网络由容器层(如Sequential)持有多个子层的LayerConfig,并在初始化时把它们连接起来。
源码佐证:Sequential 容器如何"造出"网络
以 src/layers/container/sequential.rs 为例,SequentialConfig只包含三个字段:
| 字段 | 含义 | 默认值 |
|---|---|---|
layers: Vec<LayerConfig> | 容器所包含的各层配置 | 空 |
inputs: Vec<(String, Vec<usize>)> | 输入张量的名称与形状,供首层引用 | 空 |
force_backward: bool | 是否强制所有层执行反向传播 | false |
Sequential::init_layers的初始化流程清晰地还原了"连接成一个图"的过程:
- 为每个声明的输入张量创建
data/gradient两个SharedTensor并注册; - 把容器输入名加到第一个层上,让首层正确连接输入;
- 逐层连接:每层输出 blob 命名为
SEQUENTIAL_{i}并作为下一层的输入 blob,从而让"上一个层的输出成为下一个层的输入";最后一层输出命名为SEQUENTIAL_OUTPUT_{i};若前一层支持原地计算(in-place),则直接复用其输出名; - 逐层调用
Layer::connect,通过registry(blob 注册表)把各层的输入/输出/权重 blob 关联起来; - 从后往前执行
init_backprop,判定哪些 blob 对 loss 有贡献、哪些可以跳过反向传播,从而为每层设置needs_backward标志; - 若
force_backward == true,再对所有层执行init_force_backward; - 最后一个层的输出即被视为容器(整个网络)的输出。
对应到 src/layer.rs 中的Layer::connect,其职责包括:按配置连接输入 blob、追加输出 blob(支持原地计算与匿名输出 blob)、为需要权重的层创建权重与梯度张量,并调用worker.init、reshape与resize_shared_workspace完成内存分配。
因此,文档 doc/src/building-networks.md 中由SequentialConfig构建卷积网络的代码是标准用法:
let mut net_cfg = SequentialConfig::default(); net_cfg.add_input("data", &vec![batch_size, 28, 28]); net_cfg.add_layer(LayerConfig::new("reshape", ReshapeConfig::of_shape(&vec![batch_size, 1, 28, 28]))); net_cfg.add_layer(LayerConfig::new("conv", ConvolutionConfig { num_output: 20, filter_shape: vec![5], stride: vec![1], padding: vec![0] })); net_cfg.add_layer(LayerConfig::new("pooling", PoolingConfig { mode: PoolingMode::Max, filter_shape: vec![2], stride: vec![2], padding: vec![0] })); net_cfg.add_layer(LayerConfig::new("linear1", LinearConfig { output_size: 500 })); net_cfg.add_layer(LayerConfig::new("sigmoid", LayerType::Sigmoid)); net_cfg.add_layer(LayerConfig::new("linear2", LinearConfig { output_size: 10 })); net_cfg.add_layer(LayerConfig::new("log_softmax", LayerType::LogSoftmax)); // 把配置变成可运行的深度卷积网络 let mut net = Layer::from_config(backend.clone(), &net_cfg);初始化网络(An initialized network)
术语文档对"初始化网络"给出了明确的定义:
"An initialized network is a network, which is ready to be executed, meaning it is fully constructed e.g. all necessary memory is allocated on the host or device."(已初始化的网络是指可以立即执行的网络,即它已被完整构建,例如所有必要的内存都已在主机或设备上分配。)
换句话说,"初始化"发生在Layer::from_config完成的那一刻——它不仅是把LayerConfig变成层对象,还包括connect阶段的全部动作:分配输入/输出/权重/梯度的SharedTensor、确定反向传播标志、调整张量形状、分配共享工作区(shared workspace)。这正好解释了为什么文档 doc/src/layers.md 会说"Hurray! We just constructed a network with one layer"——单个Layer::from_config返回的对象就是一个已初始化、可直接forward的"一层的网络"。
嵌套组合:网络是更大的网络的构建块
由于网络本质上仍是 Layer,Sequential自然可以作为更大网络的构建块。文档 doc/src/building-networks.md 给出了嵌套示例:先把一个包含 conv + pooling + linear + sigmoid 的conv_net作为LayerConfig加入外层net_cfg,再在外面继续追加linear与log_softmax,得到更大的网络。从源码看,这依赖于Sequential::learnable_weights等接口的扁平化收集——容器层会把内部所有子层的可学习权重、梯度与名称收集汇总(见 src/layers/container/sequential.rs 中learnable_weights()、learnable_weights_gradients()、learnable_weights_names()的flat_map实现),使外部 Solver 可以统一更新整个嵌套网络的参数。
Layer::is_using_in_place、exact_num_output_blobs、min_output_blobs、auto_weight_blobs等钩子(src/layer.rs)则让容器层与其他普通层在行为上保持一致,例如容器层通过is_container() -> true告知框架在 forward/backward 时避免加锁以防止死锁。
小结:一个概念,两种视角
- Layer 是 Leaf 中唯一的构建块:接收输入、变换、返回输出;既可以实现神经网络算子(ReLU、Sigmoid、Linear、卷积、池化),也可以实现任意其他功能(Reshape、日志等),甚至可以是"连接其他层"这一行为本身。
- Network 是 Layer 的图:在 Leaf 中它由一个或多个层连接而成,实际由容器层(如
Sequential)承载;网络不是独立于层的实体,而是"连接了其他层的层",因此可以无限嵌套组合。 - 初始化即就绪:已初始化的网络意味着全部内存已在主机或设备上分配完毕,可以立即执行前向与反向计算。
后续可以继续沿着两个方向深入:一是阅读 doc/src/layers.md 了解五类层的划分(Activation / Common / Loss / Utility / Container,对应源码目录 src/layers),二是阅读 doc/src/building-networks.md 学习如何用SequentialConfig组装真实网络,再配合 doc/src/solvers.md 了解网络训练与参数优化。对于需要逐模块验证的行为,tests/layer_specs.rs 与 tests/solver_specs.rs 提供了可运行的行为规范参考。
- 机器学习
- 深度学习
【免费下载链接】leaf
Open Machine Intelligence Framework for Hackers. (GPU/CPU)
相关推荐
Yii 2 框架术语表深度解读:Alias、Application、Asset 与 Module 等核心概念的源码级解析
Yii 2 框架术语表深度解读:Alias、Application、Asset 与 Module 等核心概念的源码级解析 Yii 2 是一个快速、安全、专业的
后端Web框架MITMEngine:终极HTTPS中间人攻击检测工具深度解析 🔍
MITMEngine:终极HTTPS中间人攻击检测工具深度解析 🔍 MITMEngine 是一款强大的HTTPS中间人攻击检测工具,能够从服务器角度准确识别H
Telepresence 核心术语全解读:从 Attachment、Traffic Agent 到 VIF 的架构概念体系
Telepresence 核心术语全解读:从 Attachment、Traffic Agent 到 VIF 的架构概念体系 本文以 Telepresence 官
云原生开发工具微服务网络
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考