Scan¶
Scan - 25¶
版本¶
名称: Scan (GitHub)
域:
mainsince_version:
25函数:
False支持级别:
SupportType.COMMON形状推断:
True
此版本的操作符已在版本 25 及之后可用。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。所有输出张量(state_variables 和 scan_output_element 张量)在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。
请注意,传递给 body 子图的迭代元素没有序列轴。它的秩将比相应的 scan_input 的秩小一。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
可选属性 scan_input_directions 指定每个扫描输入的遍历方向(向前或向后)。如果省略此属性,则所有序列都将向前扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
操作的 scan_output 是通过连接 body 在每次迭代中产生的 scan_output_element 值来生成的。可选属性 scan_output_directions 指定为每个 scan_output 构建 scan_output 的方向(通过在每次迭代中将 scan_output_element 附加或前置到 scan_output)。如果省略此属性,则 scan_output_element 将在每次迭代中附加到 scan_output。
可选属性 scan_input_axes 指定每个 scan_input 要扫描的轴。如果省略,则每个 scan_input 都将在轴 0 中扫描。例如,如果轴 0 是批次轴,轴 1 是(要扫描的)时间轴,则指定轴值为 1。请注意,扫描非零轴可能不如扫描轴零高效。
可选属性 scan_output_axes 指定每个 scan_output 沿其累积 scan_outputs 的轴。例如,如果轴 1 是输入和输出的(要扫描的)时间轴,则指定 scan_input 轴和 scan_output 轴的值为 1。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body,
scan_input_axes = [axis_1, ..., axis_m]
> (init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
// scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
sequence_length = scan_1.shape[axis_1];
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
// execute loop
for (int t = 0; t < sequence_length; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = scan_1<axis=axis_1>[t];
... ;
si_m = scan_m<axis=axis_m>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
return st_1, ..., st_n, scan_out_1, ..., scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
scan_input_axes - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 要扫描的轴(序列轴)。如果省略,0 将用作每个 scan_input 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1],其中 r = rank(input)。
scan_input_directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
scan_output_axes - INTS :
K 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_output 的轴。扫描输出沿指定轴累积。如果省略,0 将用作每个 scan_output 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1]。
scan_output_directions - INTS :
K 个标志的可选列表,每个 scan_output 一个。列表的第 i 个元素指定第 i 个 scan_output 是否应通过在每次迭代中附加或前置新值来构建:0 表示附加,1 表示前置。如果省略,所有 scan_output 张量都将通过在每次迭代中附加值来生成。
输入¶
输入数量介于 1 到 2147483647 之间。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
V 在 (
tensor(bfloat16),tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(float4e2m1),tensor(float8e4m3fn),tensor(float8e4m3fnuz),tensor(float8e5m2),tensor(float8e5m2fnuz),tensor(float8e8m0),tensor(int16),tensor(int2),tensor(int32),tensor(int4),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint2),tensor(uint32),tensor(uint4),tensor(uint64),tensor(uint8))所有张量类型,最高 IRv13。
Scan - 24¶
版本¶
名称: Scan (GitHub)
域:
main起始版本:
24函数:
False支持级别:
SupportType.COMMON形状推断:
True
此版本的操作符已可用于版本 24 及以上。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。所有输出张量(state_variables 和 scan_output_element 张量)在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。
请注意,传递给 body 子图的迭代元素没有序列轴。它的秩将比相应的 scan_input 的秩小一。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
可选属性 scan_input_directions 指定每个扫描输入的遍历方向(向前或向后)。如果省略此属性,则所有序列都将向前扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
操作的 scan_output 是通过连接 body 在每次迭代中产生的 scan_output_element 值来生成的。可选属性 scan_output_directions 指定为每个 scan_output 构建 scan_output 的方向(通过在每次迭代中将 scan_output_element 附加或前置到 scan_output)。如果省略此属性,则 scan_output_element 将在每次迭代中附加到 scan_output。
可选属性 scan_input_axes 指定每个 scan_input 要扫描的轴。如果省略,则每个 scan_input 都将在轴 0 中扫描。例如,如果轴 0 是批次轴,轴 1 是(要扫描的)时间轴,则指定轴值为 1。请注意,扫描非零轴可能不如扫描轴零高效。
可选属性 scan_output_axes 指定每个 scan_output 沿其累积 scan_outputs 的轴。例如,如果轴 1 是输入和输出的(要扫描的)时间轴,则指定 scan_input 轴和 scan_output 轴的值为 1。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body,
scan_input_axes = [axis_1, ..., axis_m]
> (init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
// scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
sequence_length = scan_1.shape[axis_1];
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
// execute loop
for (int t = 0; t < sequence_length; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = scan_1<axis=axis_1>[t];
... ;
si_m = scan_m<axis=axis_m>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
return st_1, ..., st_n, scan_out_1, ..., scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
scan_input_axes - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 要扫描的轴(序列轴)。如果省略,0 将用作每个 scan_input 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1],其中 r = rank(input)。
scan_input_directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
scan_output_axes - INTS :
K 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_output 的轴。扫描输出沿指定轴累积。如果省略,0 将用作每个 scan_output 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1]。
scan_output_directions - INTS :
K 个标志的可选列表,每个 scan_output 一个。列表的第 i 个元素指定第 i 个 scan_output 是否应通过在每次迭代中附加或前置新值来构建:0 表示附加,1 表示前置。如果省略,所有 scan_output 张量都将通过在每次迭代中附加值来生成。
输入¶
输入数量介于 1 到 2147483647 之间。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
V 在 (
tensor(bfloat16),tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(float4e2m1),tensor(float8e4m3fn),tensor(float8e4m3fnuz),tensor(float8e5m2),tensor(float8e5m2fnuz),tensor(float8e8m0),tensor(int16),tensor(int32),tensor(int4),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint32),tensor(uint4),tensor(uint64),tensor(uint8))所有张量类型,最高 IRv12。
Scan - 23¶
版本¶
名称: Scan (GitHub)
域:
main起始版本:
23函数:
False支持级别:
SupportType.COMMON形状推断:
True
此版本的操作符已可用于版本 23 及以上。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。所有输出张量(state_variables 和 scan_output_element 张量)在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。
请注意,传递给 body 子图的迭代元素没有序列轴。它的秩将比相应的 scan_input 的秩小一。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
可选属性 scan_input_directions 指定每个扫描输入的遍历方向(向前或向后)。如果省略此属性,则所有序列都将向前扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
操作的 scan_output 是通过连接 body 在每次迭代中产生的 scan_output_element 值来生成的。可选属性 scan_output_directions 指定为每个 scan_output 构建 scan_output 的方向(通过在每次迭代中将 scan_output_element 附加或前置到 scan_output)。如果省略此属性,则 scan_output_element 将在每次迭代中附加到 scan_output。
可选属性 scan_input_axes 指定每个 scan_input 要扫描的轴。如果省略,则每个 scan_input 都将在轴 0 中扫描。例如,如果轴 0 是批次轴,轴 1 是(要扫描的)时间轴,则指定轴值为 1。请注意,扫描非零轴可能不如扫描轴零高效。
可选属性 scan_output_axes 指定每个 scan_output 沿其累积 scan_outputs 的轴。例如,如果轴 1 是输入和输出的(要扫描的)时间轴,则指定 scan_input 轴和 scan_output 轴的值为 1。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body,
scan_input_axes = [axis_1, ..., axis_m]
> (init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
// scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
sequence_length = scan_1.shape[axis_1];
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
// execute loop
for (int t = 0; t < sequence_length; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = scan_1<axis=axis_1>[t];
... ;
si_m = scan_m<axis=axis_m>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
return st_1, ..., st_n, scan_out_1, ..., scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
scan_input_axes - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 要扫描的轴(序列轴)。如果省略,0 将用作每个 scan_input 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1],其中 r = rank(input)。
scan_input_directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
scan_output_axes - INTS :
K 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_output 的轴。扫描输出沿指定轴累积。如果省略,0 将用作每个 scan_output 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1]。
scan_output_directions - INTS :
K 个标志的可选列表,每个 scan_output 一个。列表的第 i 个元素指定第 i 个 scan_output 是否应通过在每次迭代中附加或前置新值来构建:0 表示附加,1 表示前置。如果省略,所有 scan_output 张量都将通过在每次迭代中附加值来生成。
输入¶
输入数量介于 1 到 2147483647 之间。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
V 在 (
tensor(bfloat16),tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(float4e2m1),tensor(float8e4m3fn),tensor(float8e4m3fnuz),tensor(float8e5m2),tensor(float8e5m2fnuz),tensor(int16),tensor(int32),tensor(int4),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint32),tensor(uint4),tensor(uint64),tensor(uint8))所有张量类型,最高 IRv11。
Scan - 21¶
版本¶
名称: Scan (GitHub)
域:
mainsince_version:
21函数:
False支持级别:
SupportType.COMMON形状推断:
True
此版本的操作符自 版本 21 起可用。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。所有输出张量(state_variables 和 scan_output_element 张量)在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。
请注意,传递给 body 子图的迭代元素没有序列轴。它的秩将比相应的 scan_input 的秩小一。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
可选属性 scan_input_directions 指定每个扫描输入的遍历方向(向前或向后)。如果省略此属性,则所有序列都将向前扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
操作的 scan_output 是通过连接 body 在每次迭代中产生的 scan_output_element 值来生成的。可选属性 scan_output_directions 指定为每个 scan_output 构建 scan_output 的方向(通过在每次迭代中将 scan_output_element 附加或前置到 scan_output)。如果省略此属性,则 scan_output_element 将在每次迭代中附加到 scan_output。
可选属性 scan_input_axes 指定每个 scan_input 要扫描的轴。如果省略,则每个 scan_input 都将在轴 0 中扫描。例如,如果轴 0 是批次轴,轴 1 是(要扫描的)时间轴,则指定轴值为 1。请注意,扫描非零轴可能不如扫描轴零高效。
可选属性 scan_output_axes 指定每个 scan_output 沿其累积 scan_outputs 的轴。例如,如果轴 1 是输入和输出的(要扫描的)时间轴,则指定 scan_input 轴和 scan_output 轴的值为 1。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body,
scan_input_axes = [axis_1, ..., axis_m]
> (init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
// scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
sequence_length = scan_1.shape[axis_1];
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
// execute loop
for (int t = 0; t < sequence_length; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = scan_1<axis=axis_1>[t];
... ;
si_m = scan_m<axis=axis_m>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
return st_1, ..., st_n, scan_out_1, ..., scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
scan_input_axes - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 要扫描的轴(序列轴)。如果省略,0 将用作每个 scan_input 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1],其中 r = rank(input)。
scan_input_directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
scan_output_axes - INTS :
K 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_output 的轴。扫描输出沿指定轴累积。如果省略,0 将用作每个 scan_output 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1]。
scan_output_directions - INTS :
K 个标志的可选列表,每个 scan_output 一个。列表的第 i 个元素指定第 i 个 scan_output 是否应通过在每次迭代中附加或前置新值来构建:0 表示附加,1 表示前置。如果省略,所有 scan_output 张量都将通过在每次迭代中附加值来生成。
输入¶
输入数量介于 1 到 2147483647 之间。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
V 在 (
tensor(bfloat16),tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(float8e4m3fn),tensor(float8e4m3fnuz),tensor(float8e5m2),tensor(float8e5m2fnuz),tensor(int16),tensor(int32),tensor(int4),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint32),tensor(uint4),tensor(uint64),tensor(uint8))所有张量类型,最高 IRv10。
Scan - 19¶
版本¶
名称: Scan (GitHub)
域:
mainsince_version:
19函数:
False支持级别:
SupportType.COMMON形状推断:
True
此版本的操作符自 版本 19 起可用。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。所有输出张量(state_variables 和 scan_output_element 张量)在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。
请注意,传递给 body 子图的迭代元素没有序列轴。它的秩将比相应的 scan_input 的秩小一。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
可选属性 scan_input_directions 指定每个扫描输入的遍历方向(向前或向后)。如果省略此属性,则所有序列都将向前扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
操作的 scan_output 是通过连接 body 在每次迭代中产生的 scan_output_element 值来生成的。可选属性 scan_output_directions 指定为每个 scan_output 构建 scan_output 的方向(通过在每次迭代中将 scan_output_element 附加或前置到 scan_output)。如果省略此属性,则 scan_output_element 将在每次迭代中附加到 scan_output。
可选属性 scan_input_axes 指定每个 scan_input 要扫描的轴。如果省略,则每个 scan_input 都将在轴 0 中扫描。例如,如果轴 0 是批次轴,轴 1 是(要扫描的)时间轴,则指定轴值为 1。请注意,扫描非零轴可能不如扫描轴零高效。
可选属性 scan_output_axes 指定每个 scan_output 沿其累积 scan_outputs 的轴。例如,如果轴 1 是输入和输出的(要扫描的)时间轴,则指定 scan_input 轴和 scan_output 轴的值为 1。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body,
scan_input_axes = [axis_1, ..., axis_m]
> (init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
// scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
sequence_length = scan_1.shape[axis_1];
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
// execute loop
for (int t = 0; t < sequence_length; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = scan_1<axis=axis_1>[t];
... ;
si_m = scan_m<axis=axis_m>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
return st_1, ..., st_n, scan_out_1, ..., scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
scan_input_axes - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 要扫描的轴(序列轴)。如果省略,0 将用作每个 scan_input 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1],其中 r = rank(input)。
scan_input_directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
scan_output_axes - INTS :
K 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_output 的轴。扫描输出沿指定轴累积。如果省略,0 将用作每个 scan_output 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1]。
scan_output_directions - INTS :
K 个标志的可选列表,每个 scan_output 一个。列表的第 i 个元素指定第 i 个 scan_output 是否应通过在每次迭代中附加或前置新值来构建:0 表示附加,1 表示前置。如果省略,所有 scan_output 张量都将通过在每次迭代中附加值来生成。
输入¶
输入数量介于 1 到 2147483647 之间。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
V 在 (
tensor(bfloat16),tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(float8e4m3fn),tensor(float8e4m3fnuz),tensor(float8e5m2),tensor(float8e5m2fnuz),tensor(int16),tensor(int32),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint32),tensor(uint64),tensor(uint8))所有张量类型,最高 IRv9。
Scan - 16¶
版本¶
名称: Scan (GitHub)
域:
mainsince_version:
16函数:
False支持级别:
SupportType.COMMON形状推断:
True
此版本的运算符自 版本 16 起可用。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。所有输出张量(state_variables 和 scan_output_element 张量)在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。
请注意,传递给 body 子图的迭代元素没有序列轴。它的秩将比相应的 scan_input 的秩小一。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
可选属性 scan_input_directions 指定每个扫描输入的遍历方向(向前或向后)。如果省略此属性,则所有序列都将向前扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
操作的 scan_output 是通过连接 body 在每次迭代中产生的 scan_output_element 值来生成的。可选属性 scan_output_directions 指定为每个 scan_output 构建 scan_output 的方向(通过在每次迭代中将 scan_output_element 附加或前置到 scan_output)。如果省略此属性,则 scan_output_element 将在每次迭代中附加到 scan_output。
可选属性 scan_input_axes 指定每个 scan_input 要扫描的轴。如果省略,则每个 scan_input 都将在轴 0 中扫描。例如,如果轴 0 是批次轴,轴 1 是(要扫描的)时间轴,则指定轴值为 1。请注意,扫描非零轴可能不如扫描轴零高效。
可选属性 scan_output_axes 指定每个 scan_output 沿其累积 scan_outputs 的轴。例如,如果轴 1 是输入和输出的(要扫描的)时间轴,则指定 scan_input 轴和 scan_output 轴的值为 1。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body,
scan_input_axes = [axis_1, ..., axis_m]
> (init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
// scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
sequence_length = scan_1.shape[axis_1];
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
// execute loop
for (int t = 0; t < sequence_length; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = scan_1<axis=axis_1>[t];
... ;
si_m = scan_m<axis=axis_m>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
return st_1, ..., st_n, scan_out_1, ..., scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
scan_input_axes - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 要扫描的轴(序列轴)。如果省略,0 将用作每个 scan_input 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1],其中 r = rank(input)。
scan_input_directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
scan_output_axes - INTS :
K 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_output 的轴。扫描输出沿指定轴累积。如果省略,0 将用作每个 scan_output 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1]。
scan_output_directions - INTS :
K 个标志的可选列表,每个 scan_output 一个。列表的第 i 个元素指定第 i 个 scan_output 是否应通过在每次迭代中附加或前置新值来构建:0 表示附加,1 表示前置。如果省略,所有 scan_output 张量都将通过在每次迭代中附加值来生成。
输入¶
输入数量介于 1 到 2147483647 之间。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
V 在 (
tensor(bfloat16),tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(int16),tensor(int32),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint32),tensor(uint64),tensor(uint8))所有张量类型,最高 IRv4。
Scan - 11¶
版本¶
名称: Scan (GitHub)
域:
main起始版本:
11函数:
False支持级别:
SupportType.COMMON形状推断:
True
此版本的运算符自 版本 11 起可用。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。所有输出张量(state_variables 和 scan_output_element 张量)在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。
请注意,传递给 body 子图的迭代元素没有序列轴。它的秩将比相应的 scan_input 的秩小一。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
可选属性 scan_input_directions 指定每个扫描输入的遍历方向(向前或向后)。如果省略此属性,则所有序列都将向前扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
操作的 scan_output 是通过连接 body 在每次迭代中产生的 scan_output_element 值来生成的。可选属性 scan_output_directions 指定为每个 scan_output 构建 scan_output 的方向(通过在每次迭代中将 scan_output_element 附加或前置到 scan_output)。如果省略此属性,则 scan_output_element 将在每次迭代中附加到 scan_output。
可选属性 scan_input_axes 指定每个 scan_input 要扫描的轴。如果省略,则每个 scan_input 都将在轴 0 中扫描。例如,如果轴 0 是批次轴,轴 1 是(要扫描的)时间轴,则指定轴值为 1。请注意,扫描非零轴可能不如扫描轴零高效。
可选属性 scan_output_axes 指定每个 scan_output 沿其累积 scan_outputs 的轴。例如,如果轴 1 是输入和输出的(要扫描的)时间轴,则指定 scan_input 轴和 scan_output 轴的值为 1。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body,
scan_input_axes = [axis_1, ..., axis_m]
> (init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
// scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
sequence_length = scan_1.shape[axis_1];
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
// execute loop
for (int t = 0; t < sequence_length; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = scan_1<axis=axis_1>[t];
... ;
si_m = scan_m<axis=axis_m>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
return st_1, ..., st_n, scan_out_1, ..., scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
scan_input_axes - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 要扫描的轴(序列轴)。如果省略,0 将用作每个 scan_input 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1],其中 r = rank(input)。
scan_input_directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
scan_output_axes - INTS :
K 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_output 的轴。扫描输出沿指定轴累积。如果省略,0 将用作每个 scan_output 的扫描轴。轴的负值表示从后往前计数维度。接受的范围是 [-r, r-1]。
scan_output_directions - INTS :
K 个标志的可选列表,每个 scan_output 一个。列表的第 i 个元素指定第 i 个 scan_output 是否应通过在每次迭代中附加或前置新值来构建:0 表示附加,1 表示前置。如果省略,所有 scan_output 张量都将通过在每次迭代中附加值来生成。
输入¶
输入数量介于 1 到 2147483647 之间。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
V 在 (
tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(int16),tensor(int32),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint32),tensor(uint64),tensor(uint8))所有张量类型
Scan - 9¶
版本¶
名称: Scan (GitHub)
域:
main起始版本:
9函数:
False支持级别:
SupportType.COMMON形状推断:
True
此版本的运算符自 版本 9 起可用。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。所有输出张量(state_variables 和 scan_output_element 张量)在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。
请注意,传递给 body 子图的迭代元素没有序列轴。它的秩将比相应的 scan_input 的秩小一。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
可选属性 scan_input_directions 指定每个扫描输入的遍历方向(向前或向后)。如果省略此属性,则所有序列都将向前扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
操作的 scan_output 是通过连接 body 在每次迭代中产生的 scan_output_element 值来生成的。可选属性 scan_output_directions 指定为每个 scan_output 构建 scan_output 的方向(通过在每次迭代中将 scan_output_element 附加或前置到 scan_output)。如果省略此属性,则 scan_output_element 将在每次迭代中附加到 scan_output。
可选属性 scan_input_axes 指定每个 scan_input 要扫描的轴。如果省略,则每个 scan_input 都将在轴 0 中扫描。例如,如果轴 0 是批次轴,轴 1 是(要扫描的)时间轴,则指定轴值为 1。请注意,扫描非零轴可能不如扫描轴零高效。
可选属性 scan_output_axes 指定每个 scan_output 沿其累积 scan_outputs 的轴。例如,如果轴 1 是输入和输出的(要扫描的)时间轴,则指定 scan_input 轴和 scan_output 轴的值为 1。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body,
scan_input_axes = [axis_1, ..., axis_m]
> (init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
// scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
sequence_length = scan_1.shape[axis_1];
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
// execute loop
for (int t = 0; t < sequence_length; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = scan_1<axis=axis_1>[t];
... ;
si_m = scan_m<axis=axis_m>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
return st_1, ..., st_n, scan_out_1, ..., scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
scan_input_axes - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 要扫描的轴(序列轴)。如果省略,0 将用作每个 scan_input 的扫描轴。
scan_input_directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
scan_output_axes - INTS :
K 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_output 的轴。扫描输出沿指定轴累积。如果省略,0 将用作每个 scan_output 的扫描轴。
scan_output_directions - INTS :
K 个标志的可选列表,每个 scan_output 一个。列表的第 i 个元素指定第 i 个 scan_output 是否应通过在每次迭代中附加或前置新值来构建:0 表示附加,1 表示前置。如果省略,所有 scan_output 张量都将通过在每次迭代中附加值来生成。
输入¶
输入数量介于 1 到 2147483647 之间。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
V 在 (
tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(int16),tensor(int32),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint32),tensor(uint64),tensor(uint8))所有张量类型
Scan - 8¶
版本¶
名称: Scan (GitHub)
域:
main起始版本:
8函数:
False支持级别:
SupportType.COMMON形状推断:
True
此运算符版本自版本 8 起可用。
摘要¶
Scan 可用于遍历一个或多个 scan_input 张量,构建零个或多个 scan_output 张量。它结合了通用递归、函数式编程构造(如 scan、fold、map 和 zip)的思想,旨在实现 RNN 类构造的泛化,用于序列到序列的处理。其他张量(此处称为 state_variables)可用于在从一个元素迭代到另一个元素时携带状态(类似于 RNN 中的隐藏状态,在循环上下文中也称为循环携带依赖)。所有这些张量在循环的每次迭代中都必须具有相同的形状(为实现高效内存分配而施加的限制)。许多常见用法涉及单个 scan_input 张量(可获得类似于 scan、fold 和 map 的功能)。当使用多个 scan_input 时,可获得类似于 zip 的行为。
属性 body 必须是一个图,指定在每次迭代中要执行的计算。它将 state_variables 的当前值和 scan_inputs 的当前迭代元素作为输入。它必须返回 state_variables 的(更新后的)值和零个或多个 scan_output_element 张量。scan_output_element 张量的值在所有迭代中连接起来,以产生 scan 构造的 scan_output 值(类似于 RNN 类构造的连接中间隐藏状态值)。
scan 操作返回 state_variables 的最终值以及 scan_outputs。
该操作支持批处理,并且批次轴必须是 0。当使用多个 scan_input 张量时,它们必须都具有相同的批次大小,并且它们必须都具有相同的最大序列长度(序列轴或扫描轴的维度)。序列轴或扫描轴必须是 1。
该操作有一个可选的 sequence_lens 输入(形状为 [BATCH_SIZE]),以允许长度 <= 最大序列长度的变长序列。如果未指定此输入,则假定所有序列的长度等于最大序列长度。对于变长输入序列,scan_outputs 将包含与输入长度相同的序列,并填充到最大序列长度。
可选属性 directions 可用于以反向扫描序列。如果省略此属性,所有序列都将以向前方向扫描。通过在 scan_inputs 中两次指定相同的张量输入,一次向前,一次向后,可以执行双向扫描。
请注意,由于 ONNX 限制,即运算符的最后一个参数才能是可变参数,因此初始状态和扫描输入作为单个输入参数一起列出。同样,最终状态和扫描输出作为单个输出参数一起列出。属性 num_scan_inputs 表示扫描输入的数量 M。
行为
Scan <
num_scan_inputs = m,
body = loop-body
> (sequence_lengths, init_1, ..., init_n, scan_1, ..., scan_m)
等效于以下伪代码
// T.shape[0] denotes the batch-size of T
// The batch-size of scan_1, ..., scan_m are all required to be equal
batch_size = scan_1.shape[0];
// scan_i.shape[1] denotes the (max) sequence-length of scan_i
// scan_i.shape[1] is required to be equal to scan_j.shape[1] for all i,j.
max_sequence_length = scan_1.shape[1];
for (int batch = 0; batch < batch_size; ++batch) {
// initialize state-variables
st_1 = init_1; ... st_n = init_n;
// initialize scan-output variables: [] denotes an empty tensor
scan_out_1 = []; ...; scan_out_k = [];
// identify number of iterations:
N = (sequence_lengths specified) ? sequence_lengths[batch] : max_sequence_length;
// execute loop
for (int t = 0; t < N; ++t) {
// generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
// of rank one less than T obtained by indexing T at position t along axis k.
si_1 = (scan_1<axis=0>[batch])<axis=1>[t];
... ;
si_m = (scan_m<axis=0>[batch])<axis=1>[t];
// execute loop-body
st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
// accumulate the scan-output elements
scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
}
// accumulate the outputs for this batch:
bst_1[batch] = st_1; ..., bst_n[batch] = st_n;
// Note scan-outputs will have size max_sequence_length, but only first N values will be meaningful.
// The remaining values have an undefined value.
b_scan_out_1[batch] = scan_out_1; ...; b_scan_out_k[batch] = scan_out_k;
}
return bst_1, ..., bst_n, b_scan_out_1, ..., b_scan_out_k;
示例用法:使用 Scan 编码 RNN
以下示例展示了如何将一个简单的 RNN 编码为 ScanLoop,该 RNN 作用于输入张量 %X,带有权重张量 %Wi、循环权重张量 %Ri、偏置张量 %Wbi 和 %Rbi,以及初始隐藏状态 %H_0。请注意,循环体是一个嵌套图,它直接计算
值在外部图中计算,需要作为额外的 state_variables 传入。
graph rnn-encoding {
%H_0 = ...
%X = ...
%Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1]("", %H_0, %X)
return %Y, %Y_h
}
graph rnn-cell-1 (
%H_tminus1[FLOAT, tensor]
%X_t[FLOAT, tensor]
) {
%Wi = ...
%Ri = ...
%Wbi = ...
%Rbi = ...
%t1 = X_t * (Wi^T)
%t2 = H_tminus1*(Ri^T)
%t3 = Add(%t1, %t2)
%t4 = Add(%t3, %Wbi)
%t5 = Add(%t4, %Rbi)
%Ht = Tanh(%t5)
%Accumulate = Identity(%Ht)
return %Ht, %Accumulate
}
属性¶
body - GRAPH (必需)
每次迭代运行的图。它有 N+M 个输入:(循环状态变量...,scan_input_elts...)。它有 N+K 个输出:(循环状态变量...,scan_output_elts...)。每个 scan_output 是通过在循环的每次迭代结束时连接指定 scan_output_elt 值创建的。如果这些值的维度在循环迭代中发生变化,则会出错。
directions - INTS :
M 个标志的可选列表。列表的第 i 个元素指定第 i 个 scan_input 张量的扫描方向:0 表示向前方向,1 表示向后方向。如果省略,所有 scan_input 张量都将向前扫描。
num_scan_inputs - INT (必需)
一个属性,指定 scan_inputs 的数量 M。
输入¶
2 到 2147483647 个输入之间。
sequence_lens (可选,异构) - I
可选张量,指定批次中序列的长度。如果未指定此输入,则假定所有序列都具有最大序列长度(scan_input 张量的序列轴的维度)。
initial_state_and_scan_inputs (可变参数) - V
循环 N 个状态变量的初始值,后跟 M 个扫描输入
输出¶
1 到 2147483647 个输出之间。
final_state_and_scan_outputs (可变参数) - V
循环 N 个状态变量的最终值,后跟 K 个扫描输出
类型约束¶
I 在 (
tensor(int64))Int64 张量
V 在 (
tensor(bool),tensor(complex128),tensor(complex64),tensor(double),tensor(float),tensor(float16),tensor(int16),tensor(int32),tensor(int64),tensor(int8),tensor(string),tensor(uint16),tensor(uint32),tensor(uint64),tensor(uint8))所有张量类型