开放式神经网络交换-ONNX(下)
开放式神经网络交换-ONNX(下)
计算节点由名称、它调用的算子operator的名称、命名输入的列表、命名输出的列表和属性列表组成。
输入和输出在位置上与算子operator输入和输出相关联。属性通过名称与算子operator属性相关联。
它们具有以下属性:
属于值命名空间的名称可以出现在多个位置,即作为图形输入、图形初始值设定项、图形输出、节点输入或节点输出。名称作为图形输入、图形初始值设定项或节点输出的出现称为定义(站点),名称作为节点输入或图形输出的出现称为使用(站点)。
图形中使用的值名称必须具有唯一的定义站点,但图形输入列表和图形初始值设定项列表中可能出现相同的名称。(如后文所述,在存在嵌套子图的情况下适用其他例外情况。)
当名称同时出现在初始值设定项列表和图形输入列表中时,runtime可能允许调用者为此(输入)名称指定一个值,覆盖在初始值设定项中指定的值,而runtime可能允许用户忽略为此(输入)名称指定的值,选择在初始值设定项中指定的值。不打算被调用方重写的常量的名称应只出现在初始值设定项列表中,而不应出现在图形输入列表中。在用作属性值的嵌套子图中,用户不能同时使用与子图初始值设定项和子图输入相同的名称(除非相应的操作规范明确允许)。
计算图中的边是由一个节点的输出建立的,该节点在随后一个节点的输入中被名称引用。
给定节点的输出将新名称引入图中。节点输出值由节点的算子operator计算。节点输入可以引用节点输出、图形输入和图形初始化器。当节点输出的名称与图形输出的名称一致时,图形输出的值是该节点计算的相应输出值。嵌套子图中的节点输入可以引用外部图中引入的名称(作为节点输出、图形输入或图形初始值设定项)。
图形必须对所有节点输出使用单个静态赋值,这意味着在一个图中所有节点输出名称都必须是唯一的。对于嵌套子图,节点输出名称必须与嵌套子图中可见的外部作用域的名称不同。
节点依赖项不能在计算图中创建循环。
节点中输入和输出的数量、类型、节点中指定的属性集及其类型必须满足节点算子operator签名所施加的约束。
定义顶层计算图的节点列表必须按拓扑排序;也就是说,如果图中节点K跟在节点N之后,N的任何数据输入都不能引用K的输出。
节点属性用于将文本(静态)值传递给算子operator。
输入和输出值
这种表示法区分了两种类型的值:静态已知的属性值和输入/输出值。两种情况下允许的值类型不同。
输入和输出值作为图形输入、输出和初始化器,以及节点输入和输出。它们的值由启动模型执行的代码或计算输出值的运算符在运行时确定。
属性
属性值只在节点中找到,通过名称关联传递给运算符。属性值是运行时常量,因为它们的值是在构建模型图时确定的,因此不会在运行时计算。属性的一个常见用法是表示在模型训练期间建立的系数。
属性具有以下属性:
属性“name”和“type”对于所有属性都是必需的,并且“doc_string”应该用于所有属性。属性必须只有一个承载值的属性。
可变输入和输出
运算符的最后一个输入或输出可以标记为可变的。例如,运算符“Max()”可用于计算不同数量输入值的最大值。变量运算符有一个关联的最小arity,它指定必须指定的操作数的最小数目。
对于每个变量运算符输入,必须指定N个或多个节点输入,其中N是运算符的最小arity。对于每个变量运算符输出,必须指定N个或多个节点输出,其中N是运算符的最小arity。
可选输入和输出
一些运算符具有标记为可选的输入,这意味着引用节点可以放弃为此类输入提供值。
有些运算符的输出是可选的。当未指定运算符的实际输出参数时,运算符实现可以放弃此类输出的计算值。
有两种方法可以不指定可选的输入或输出:第一种方法仅适用于尾随的输入和输出,即不提供该输入;第二种方法是使用空字符串代替输入或输出名称。
引用具有可选输出的运算符的每个节点必须为计算的每个输出提供名称,并且不能为未计算的输出提供名称。
外部张量数据
大型常量张量的原始数据,如初始值设定项,可以在单独的文件中序列化。在这种情况下,张量必须提供相对于模型文件的文件名,并且不能使用值字段。它可以提供该文件中的字节偏移量和长度。它还可以指定文件的SHA1摘要。一个文件可能包含多个张量的数据。
更多详细信息请参见ExternalData.md。
标准数据类型
有两个官方的ONNX类型;两者之间的主要区别在于支持的类型和支持的运算符。
对于支持的类型,ONNX定义只识别张量作为输入和输出类型,而经典的机器学习扩展。ONNX-ML还可以识别序列和地图。
ONNX支持以下数据类型,用于图形和节点的输入和输出,以及图形的初始值设定项。
基本数值、字符串和布尔类型必须用作张量的元素。
张量元素类型
Input / Output Data Types
The following types are used to define the types of graph and node inputs and outputs.
ONNX当前没有定义稀疏张量类型。
静态张量shape
除了元素类型,张量类型还有一个静态shape。张量变量的静态shape与张量值的运行时(动态)shape相关,但不同。静态张量shape是表示张量是向量、矩阵还是更高维值的记录列表。例如,100x100矩阵的shape为[100100]。
静态shape由“TensorShapeProto”定义:
message TensorShapeProto {
message Dimension {
oneof value {
int64 dim_value = 1;
string dim_param = 2;
};
};
repeated Dimension dim = 1;
}
Which is referenced by the Tensor type message:
message Tensor {
optional TensorProto.DataType elem_type = 1;
optional TensorShapeProto shape = 2;
维数大小的空列表[]是有效的张量shape,表示零维(标量)值。零维张量不同于未知维数的张量,它由张量记录中缺少的“shape”属性来表示。当值类型(包括节点输入)中缺少shape属性时,它指示相应的运行时值可以具有任何shape。本小节描述了如何解释缺少的shape或缺少尺寸的shape等。但是,特定的使用上下文可能会对类型和shape施加进一步的约束。例如,模型(顶层图)的输入和输出必须具有一个shape,指示输入和输出的等级,即使不需要指定确切的尺寸。
列表中的每个大小可以表示为整数值,也可以表示为“维数变量”(dimension variable),这是一个字符串,表示维数的实际大小没有静态约束到某个特定的数字。这对于声明关心维数数量而不是每个维数的确切大小的接口非常有用。维数既不能设置维数值,也不能设置维数参数。这样的维数表示与其他未知维数无关的未知维数。
例如,NxM矩阵将具有shape列表[N,M]。
每个维数变量的名称必须符合C标识符语法。
当前,维数变量没有范围。维数变量“N”表示模型中整个图形的相同值。例如,如果图有两个输入X和Y,每个输入都有shape[“N”],那么在运行时,为X和Y传入的值必须是具有相同维数的秩1的张量。嵌套子图当前与主图共享相同的维数变量范围。这使得模型能够将子图内部张量的维数与外部图中张量的维数相关联。
ONNXML支持更丰富的类型,比如张量序列。维数变量的全局作用域意味着类型为“Sequence<Tensor<float[M,N]>”的变量表示一系列具有相同shape的张量。如果维数在序列中的所有张量上没有固定的大小,则必须从上述类型中省略维数变量M或N。如果序列中不同的张量可能具有不同的秩,则必须从类型中省略整个shape。
例如,执行矩阵叉积cross-product的图可以定义为获取形状[K,M]和[M,N]的两个输入,并产生形状[K,N]的输出。
形状可以使用整数和变量的组合来定义。
历史记录:早期考虑过以下扩展,但从未实现或支持。
使用空字符串(作为维度变量)来表示与任何其他维度无关的未知维度。为了使用既没有dim_value也没有dim_param集的维度,这一点被丢弃了。
使用字符串“*”(作为维度变量)来表示零个或多个未知基数维的序列。不支持此操作。在当前的实现中,形状中的维数必须表示张量的秩。一个未知等级的张量用一个没有形状的TypeProto::tensor对象来表示,这是合法的。
允许子图(如循环体)局部的维度变量的作用域机制可能有用,但目前不支持。
ONNXML支持更丰富的类型,比如张量序列。一个类型的局部维度变量的作用域机制可能有助于区分以下两种类型:一个平方矩阵序列(大小不同)和一个方阵序列(大小相同)。目前不支持。
- The use of an empty string (as a dimension variable) to denote an unknown dimension not related to any other dimension. This was discarded in favor of using a Dimension with neither dim_value nor dim_param set.
- The use of the string "*" (as a dimension variable) to denote a sequence of zero or more dimensions of unknown cardinality. This is not supported. In the current implementation, the number of dimensions in a shape MUST represent the rank of the tensor. A tensor of unknown rank is represented using a TypeProto::Tensor object with no shape, which is legal.
- A scoping mechanism to allow dimension variables that are local to a sub-graph (such as the body of a loop) may be useful, but is not currently supported.
- ONNXML supports richer types such as Sequences of Tensors. A scoping mechanism for the dimension variables local to a type may be useful to distinguish between the following two types: a sequence of square matrices (of differing sizes) vs a sequence of square matrices (all of same size). This is not currently supported.
属性类型
用于属性的类型系统与用于输入和输出的类型系统相关,但略有不同。属性值可以是稠密张量、稀疏张量、标量数值、字符串、图形或上述类型之一的重复值。
训练相关信息
与训练相关的信息由模型中包含的一个或多个TrainingInfoProto实例来描述。每个TrainingInfoProto都包含描述初始化步骤和训练步骤的信息。
初始化步骤用图形描述(训练InfoProto.initialization)以及初始化绑定映射(TrainingInfoProto.initialization_绑定). 初始化步骤是通过计算图来执行的,并将图产生的输出分配给初始化绑定中指定的训练模型的状态变量。初始化绑定在概念上是一个映射,指定为键-值对的列表,其中每个键是状态变量的名称,值是(初始化)图的输出的名称。在绑定中指定为键的每个名称必须是出现在主推理图(即ModelProto.graph.initializer)或出现在中的初始值设定项的名称TrainingInfoProto.algorithm.initializer. 在绑定中指定为值的每个名称都必须是训练InfoProto.initialization图表。在重复初始化绑定字段中指定的键值必须是唯一的。
训练步骤也类似地用图表描述(模拟算法训练)和更新绑定映射(TrainingInfoProto.update_绑定). 训练步骤是通过计算图并将图产生的输出分配给更新绑定中指定的状态变量来执行的。上述初始化的约束和描述也适用于训练步骤。
因此,训练模型的状态变量由主推理图(i.e., ModelProto.graph.initializer)以及训练算法图(TrainingInfoProto.algorithm.initializer)由绑定的键标识(in
TrainingInfoProto.initialization_binding and TrainingInfoProto.update_binding)。
请注意,在训练环境中,状态变量不是常数值。它们表示由多个图共享的可变变量(在顶级训练模型范围内隐式声明)。为了与推理图表示法向后兼容,使用了共享可变变量的隐式声明,而不是显式声明。
所有状态变量都预先初始化为相应的初始值设定项中指定的值。执行初始化步骤的后续调用(使用运行时公开的适当API)将更新上述状态变量的值。如果训练模型不止一个TrainingInfoProto实例,则依次执行每个实例对应的初始化步骤。一个训练TrainingInfoProto.initialization可以省略(仅当没有初始化\u绑定时)。对于训练步骤,运行时可能允许用户调用模拟算法训练,允许训练过程根据需要交织不同的算法。不同的训练原型算法被调用会影响训练结果,调用者有责任按正确的顺序调用它们。
其它规范文件
ONNX规范由定义IR语义和标准数据类型的文档和定义标准运算符语义和IR语法的以下文档组成。后者被指定为protobuf_v2和v3模式文件。
有关详细信息,请参阅元数据类别文档。