掃描

掃描 - 23

版本

  • 名稱: 掃描 (GitHub)

  • 網域: main

  • since_version: 23

  • 函式: False

  • 支援等級: SupportType.COMMON

  • 形狀推斷: True

此運算子版本自版本 23 起已可用。

摘要

掃描可用於迭代一個或多個 scan_input 張量,建構零個或多個 scan_output 張量。它結合了通用遞迴、函數式程式設計結構(例如掃描、摺疊、映射和 zip)的想法,旨在實現序列到序列處理的 RNN 類結構的泛化。其他張量(此處稱為 state_variables)可用於在從一個元素迭代到另一個元素時攜帶狀態(類似於 RNN 中的隱藏狀態,在迴圈的上下文中也稱為迴圈攜帶的依賴關係)。許多常見用法涉及單個 scan_input 張量(其中可以獲得類似於掃描、摺疊和映射的功能)。當使用多個 scan_input 時,會獲得類似 zip 的行為。

屬性 body 必須是一個圖形,指定在每次迭代中執行的計算。它將 state_variables 的當前值和 scan_inputs 的當前迭代元素作為輸入。它必須傳回 state_variables 的(更新)值和零個或多個 scan_output_element 張量。scan_output_element 張量的值會在所有迭代中串聯起來,以產生掃描結構的 scan_output 值(類似於 RNN 類結構的串聯中間隱藏狀態值)。所有輸出張量(state_variables 以及 scan_output_element 張量)都需要在迴圈的每次迭代中具有相同的形狀(為了實現有效的記憶體分配而強加的限制)。

請注意,傳遞給 body 子圖形的迭代元素沒有序列軸。它的秩將比相應的 scan_input 的秩少一。

掃描操作會傳回 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;

範例用法:使用掃描編碼 RNN

以下範例顯示了如何使用 ScanLoop 對輸入張量 %X、權重張量 %Wi、遞迴權重張量 %Ri、偏權張量 %Wbi 和 %Rbi 以及初始隱藏狀態 %H_0 的簡單 RNN 進行編碼。請注意,迴圈主體是巢狀圖形,它直接計算

值在外部圖形中計算,它們需要作為額外的 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(必要)

    指定掃描輸入 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 的軸。scan_outputs 會沿指定的軸累積。如果省略,則會將 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 的所有張量類型。

掃描 - 21

版本

  • 名稱: 掃描 (GitHub)

  • 網域: main

  • since_version: 21

  • 函式: False

  • 支援等級: SupportType.COMMON

  • 形狀推斷: True

此運算子版本自版本 21 起已可用。

摘要

掃描可用於迭代一個或多個 scan_input 張量,建構零個或多個 scan_output 張量。它結合了通用遞迴、函數式程式設計結構(例如掃描、摺疊、映射和 zip)的想法,旨在實現序列到序列處理的 RNN 類結構的泛化。其他張量(此處稱為 state_variables)可用於在從一個元素迭代到另一個元素時攜帶狀態(類似於 RNN 中的隱藏狀態,在迴圈的上下文中也稱為迴圈攜帶的依賴關係)。許多常見用法涉及單個 scan_input 張量(其中可以獲得類似於掃描、摺疊和映射的功能)。當使用多個 scan_input 時,會獲得類似 zip 的行為。

屬性 body 必須是一個圖形,指定在每次迭代中執行的計算。它將 state_variables 的當前值和 scan_inputs 的當前迭代元素作為輸入。它必須傳回 state_variables 的(更新)值和零個或多個 scan_output_element 張量。scan_output_element 張量的值會在所有迭代中串聯起來,以產生掃描結構的 scan_output 值(類似於 RNN 類結構的串聯中間隱藏狀態值)。所有輸出張量(state_variables 以及 scan_output_element 張量)都需要在迴圈的每次迭代中具有相同的形狀(為了實現有效的記憶體分配而強加的限制)。

請注意,傳遞給 body 子圖形的迭代元素沒有序列軸。它的秩將比相應的 scan_input 的秩少一。

掃描操作會傳回 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;

範例用法:使用掃描編碼 RNN

以下範例顯示了如何使用 ScanLoop 對輸入張量 %X、權重張量 %Wi、遞迴權重張量 %Ri、偏權張量 %Wbi 和 %Rbi 以及初始隱藏狀態 %H_0 的簡單 RNN 進行編碼。請注意,迴圈主體是巢狀圖形,它直接計算

值在外部圖形中計算,它們需要作為額外的 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(必要)

    指定掃描輸入 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 的軸。scan_outputs 會沿指定的軸累積。如果省略,則會將 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 in ( 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) )

    所有 Tensor 類型,最高至 IRv10。

掃描 - 19

版本

  • 名稱: 掃描 (GitHub)

  • 網域: main

  • since_version: 19

  • 函式: False

  • 支援等級: SupportType.COMMON

  • 形狀推斷: True

此版本的運算子自版本 19 起可用。

摘要

掃描可用於迭代一個或多個 scan_input 張量,建構零個或多個 scan_output 張量。它結合了通用遞迴、函數式程式設計結構(例如掃描、摺疊、映射和 zip)的想法,旨在實現序列到序列處理的 RNN 類結構的泛化。其他張量(此處稱為 state_variables)可用於在從一個元素迭代到另一個元素時攜帶狀態(類似於 RNN 中的隱藏狀態,在迴圈的上下文中也稱為迴圈攜帶的依賴關係)。許多常見用法涉及單個 scan_input 張量(其中可以獲得類似於掃描、摺疊和映射的功能)。當使用多個 scan_input 時,會獲得類似 zip 的行為。

屬性 body 必須是一個圖形,指定在每次迭代中執行的計算。它將 state_variables 的當前值和 scan_inputs 的當前迭代元素作為輸入。它必須傳回 state_variables 的(更新)值和零個或多個 scan_output_element 張量。scan_output_element 張量的值會在所有迭代中串聯起來,以產生掃描結構的 scan_output 值(類似於 RNN 類結構的串聯中間隱藏狀態值)。所有輸出張量(state_variables 以及 scan_output_element 張量)都需要在迴圈的每次迭代中具有相同的形狀(為了實現有效的記憶體分配而強加的限制)。

請注意,傳遞給 body 子圖形的迭代元素沒有序列軸。它的秩將比相應的 scan_input 的秩少一。

掃描操作會傳回 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;

範例用法:使用掃描編碼 RNN

以下範例顯示了如何使用 ScanLoop 對輸入張量 %X、權重張量 %Wi、遞迴權重張量 %Ri、偏權張量 %Wbi 和 %Rbi 以及初始隱藏狀態 %H_0 的簡單 RNN 進行編碼。請注意,迴圈主體是巢狀圖形,它直接計算

值在外部圖形中計算,它們需要作為額外的 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(必要)

    指定掃描輸入 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 的軸。scan_outputs 會沿指定的軸累積。如果省略,則會將 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 in ( 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) )

    所有 Tensor 類型,最高至 IRv9。

掃描 - 16

版本

  • 名稱: 掃描 (GitHub)

  • 網域: main

  • since_version: 16

  • 函式: False

  • 支援等級: SupportType.COMMON

  • 形狀推斷: True

此版本的運算子自版本 16 起可用。

摘要

掃描可用於迭代一個或多個 scan_input 張量,建構零個或多個 scan_output 張量。它結合了通用遞迴、函數式程式設計結構(例如掃描、摺疊、映射和 zip)的想法,旨在實現序列到序列處理的 RNN 類結構的泛化。其他張量(此處稱為 state_variables)可用於在從一個元素迭代到另一個元素時攜帶狀態(類似於 RNN 中的隱藏狀態,在迴圈的上下文中也稱為迴圈攜帶的依賴關係)。許多常見用法涉及單個 scan_input 張量(其中可以獲得類似於掃描、摺疊和映射的功能)。當使用多個 scan_input 時,會獲得類似 zip 的行為。

屬性 body 必須是一個圖形,指定在每次迭代中執行的計算。它將 state_variables 的當前值和 scan_inputs 的當前迭代元素作為輸入。它必須傳回 state_variables 的(更新)值和零個或多個 scan_output_element 張量。scan_output_element 張量的值會在所有迭代中串聯起來,以產生掃描結構的 scan_output 值(類似於 RNN 類結構的串聯中間隱藏狀態值)。所有輸出張量(state_variables 以及 scan_output_element 張量)都需要在迴圈的每次迭代中具有相同的形狀(為了實現有效的記憶體分配而強加的限制)。

請注意,傳遞給 body 子圖形的迭代元素沒有序列軸。它的秩將比相應的 scan_input 的秩少一。

掃描操作會傳回 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;

範例用法:使用掃描編碼 RNN

以下範例顯示了如何使用 ScanLoop 對輸入張量 %X、權重張量 %Wi、遞迴權重張量 %Ri、偏權張量 %Wbi 和 %Rbi 以及初始隱藏狀態 %H_0 的簡單 RNN 進行編碼。請注意,迴圈主體是巢狀圖形,它直接計算

值在外部圖形中計算,它們需要作為額外的 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(必要)

    指定掃描輸入 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 的軸。scan_outputs 會沿指定的軸累積。如果省略,則會將 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 in ( 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) )

    所有 Tensor 類型,最高至 IRv4。

掃描 - 11

版本

  • 名稱: 掃描 (GitHub)

  • 網域: main

  • since_version: 11

  • 函式: False

  • 支援等級: SupportType.COMMON

  • 形狀推斷: True

此版本的運算子自版本 11 起可用。

摘要

掃描可用於迭代一個或多個 scan_input 張量,建構零個或多個 scan_output 張量。它結合了通用遞迴、函數式程式設計結構(例如掃描、摺疊、映射和 zip)的想法,旨在實現序列到序列處理的 RNN 類結構的泛化。其他張量(此處稱為 state_variables)可用於在從一個元素迭代到另一個元素時攜帶狀態(類似於 RNN 中的隱藏狀態,在迴圈的上下文中也稱為迴圈攜帶的依賴關係)。許多常見用法涉及單個 scan_input 張量(其中可以獲得類似於掃描、摺疊和映射的功能)。當使用多個 scan_input 時,會獲得類似 zip 的行為。

屬性 body 必須是一個圖形,指定在每次迭代中執行的計算。它將 state_variables 的當前值和 scan_inputs 的當前迭代元素作為輸入。它必須傳回 state_variables 的(更新)值和零個或多個 scan_output_element 張量。scan_output_element 張量的值會在所有迭代中串聯起來,以產生掃描結構的 scan_output 值(類似於 RNN 類結構的串聯中間隱藏狀態值)。所有輸出張量(state_variables 以及 scan_output_element 張量)都需要在迴圈的每次迭代中具有相同的形狀(為了實現有效的記憶體分配而強加的限制)。

請注意,傳遞給 body 子圖形的迭代元素沒有序列軸。它的秩將比相應的 scan_input 的秩少一。

掃描操作會傳回 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;

範例用法:使用掃描編碼 RNN

以下範例顯示了如何使用 ScanLoop 對輸入張量 %X、權重張量 %Wi、遞迴權重張量 %Ri、偏權張量 %Wbi 和 %Rbi 以及初始隱藏狀態 %H_0 的簡單 RNN 進行編碼。請注意,迴圈主體是巢狀圖形,它直接計算

值在外部圖形中計算,它們需要作為額外的 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(必要)

    指定掃描輸入 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 的軸。scan_outputs 會沿指定的軸累積。如果省略,則會將 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 in ( 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) )

    所有 Tensor 類型

掃描 - 9

版本

  • 名稱: 掃描 (GitHub)

  • 網域: main

  • since_version: 9

  • 函式: False

  • 支援等級: SupportType.COMMON

  • 形狀推斷: True

此版本的運算子自版本 9 起可用。

摘要

掃描可用於迭代一個或多個 scan_input 張量,建構零個或多個 scan_output 張量。它結合了通用遞迴、函數式程式設計結構(例如掃描、摺疊、映射和 zip)的想法,旨在實現序列到序列處理的 RNN 類結構的泛化。其他張量(此處稱為 state_variables)可用於在從一個元素迭代到另一個元素時攜帶狀態(類似於 RNN 中的隱藏狀態,在迴圈的上下文中也稱為迴圈攜帶的依賴關係)。許多常見用法涉及單個 scan_input 張量(其中可以獲得類似於掃描、摺疊和映射的功能)。當使用多個 scan_input 時,會獲得類似 zip 的行為。

屬性 body 必須是一個圖形,指定在每次迭代中執行的計算。它將 state_variables 的當前值和 scan_inputs 的當前迭代元素作為輸入。它必須傳回 state_variables 的(更新)值和零個或多個 scan_output_element 張量。scan_output_element 張量的值會在所有迭代中串聯起來,以產生掃描結構的 scan_output 值(類似於 RNN 類結構的串聯中間隱藏狀態值)。所有輸出張量(state_variables 以及 scan_output_element 張量)都需要在迴圈的每次迭代中具有相同的形狀(為了實現有效的記憶體分配而強加的限制)。

請注意,傳遞給 body 子圖形的迭代元素沒有序列軸。它的秩將比相應的 scan_input 的秩少一。

掃描操作會傳回 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;

範例用法:使用掃描編碼 RNN

以下範例顯示了如何使用 ScanLoop 對輸入張量 %X、權重張量 %Wi、遞迴權重張量 %Ri、偏權張量 %Wbi 和 %Rbi 以及初始隱藏狀態 %H_0 的簡單 RNN 進行編碼。請注意,迴圈主體是巢狀圖形,它直接計算

值在外部圖形中計算,它們需要作為額外的 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(必要)

    指定掃描輸入 M 數量的屬性。

  • scan_input_axes - INTS :

    一個可選的 M 旗標列表。列表中的第 i 個元素指定要掃描的軸(序列軸),用於第 i 個 scan_input。如果省略,則每個 scan_input 都會使用 0 作為掃描軸。

  • scan_input_directions - INTS :

    M 個標誌的可選列表。列表中的第 i 個元素指定要掃描的第 i 個 scan_input 張量的方向:0 表示前向方向,1 表示反向方向。如果省略,則所有 scan_input 張量都會在前向方向掃描。

  • scan_output_axes - INTS :

    一個可選的 K 旗標列表。列表中的第 i 個元素指定第 i 個 scan_output 的軸。掃描輸出會沿著指定的軸累積。如果省略,則每個 scan_output 都會使用 0 作為掃描軸。

  • 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 in ( 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) )

    所有 Tensor 類型

掃描 - 8

版本

  • 名稱: 掃描 (GitHub)

  • 網域: main

  • since_version: 8

  • 函式: False

  • 支援等級: SupportType.COMMON

  • 形狀推斷: True

此版本的運算子自版本 8 起可用。

摘要

掃描可用於迭代一個或多個 scan_input 張量,建構零個或多個 scan_output 張量。它結合了通用遞迴、函數式程式設計結構(如掃描、摺疊、映射和壓縮)的概念,旨在實現序列到序列處理的 RNN 類結構的泛化。其他張量(此處稱為 state_variables)可用於在從一個元素迭代到另一個元素時攜帶狀態(類似於 RNN 中的隱藏狀態,在迴圈的上下文中也稱為迴圈攜帶的相依性)。所有這些張量都需要在迴圈的每次迭代中具有相同的形狀(強加此限制以實現有效的記憶體配置)。許多常見的用法涉及單個 scan_input 張量(其中可以獲得類似於掃描、摺疊和映射的功能)。當使用多個 scan_input 時,會獲得類似於壓縮的行為。

屬性 body 必須是一個圖形,指定在每次迭代中要執行的計算。它將 state_variables 的當前值和 scan_inputs 的當前迭代元素作為輸入。它必須傳回 state_variables 的(更新)值和零個或多個 scan_output_element 張量。 scan_output_element 張量的值會連接到所有迭代中,以產生掃描結構的 scan_output 值(類似於 RNN 類結構的串聯中間隱藏狀態值)。

掃描操作會傳回 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;

範例用法:使用掃描編碼 RNN

以下範例顯示了如何使用 ScanLoop 對輸入張量 %X、權重張量 %Wi、遞迴權重張量 %Ri、偏權張量 %Wbi 和 %Rbi 以及初始隱藏狀態 %H_0 的簡單 RNN 進行編碼。請注意,迴圈主體是巢狀圖形,它直接計算

值在外部圖形中計算,它們需要作為額外的 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(必要)

    指定掃描輸入 M 數量的屬性。

輸入

介於 2 到 2147483647 個輸入之間。

  • sequence_lens (可選, heterogeneous) - I

    可選的張量,指定批次中序列的長度。如果未指定此輸入,則所有序列都假設為最大序列長度(scan_input 張量的序列軸的維度)。

  • initial_state_and_scan_inputs (可變參數) - V

    迴圈的 N 個狀態變數的初始值,後接 M 個掃描輸入

輸出

介於 1 和 2147483647 個輸出之間。

  • final_state_and_scan_outputs (可變參數) - V

    迴圈的 N 個狀態變數的最終值,後接 K 個掃描輸出

類型約束

  • I in ( tensor(int64) )

    Int64 張量

  • V in ( 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) )

    所有 Tensor 類型