Einsum

バージョン名: Einsum-7

カテゴリー: 行列乗算

簡単な説明: Einsum は、オペランドに対して Einstein の合計規則を実行します。

詳細な説明: Einsum は、多くの一般的な多次元線形代数テンソル演算を表すことができます: 行列の乗算、内積 (またはドット積)、外積、クロス積、転置、トレース抽出と対角抽出。また、単一の Einsum 操作は、複数のオペランドに対するこれらの一般的な線形代数テンソル演算の複雑な組み合わせを表現できます。例えば、形状 [5, 5] のテンソルから抽出された対角線のドット積など、5D ベクトルは単一の Einsum 操作によって実行されます。入力テンソルに関する Einstein の総和規則は、Einsum 操作の必須属性である equation によって定義されます。この操作は、明示モードと暗黙モードの equation をサポートします。両方のモードにおける equation の形式を以下に説明します。

明示モードでは、einsum equation には、入力添字から -> で区切られた出力添字があり、n 個のオペランドに対して次の形式になります: <subscript for input1>、<subscript for input2>、...、<subscript for inputn> - >< subscript for output>。<subscript for input1> の各入力添え字には、一連のラベル (アルファベット ['A',...,'Z','a',...,'z'] が含まれており、ここで、各ラベルは対応するオペランドの次元を指します。ラベルでは大文字と小文字が区別され、アルファベット順に並べ替えると大文字が小文字より優先されます。ラベルはアルファベット順に下付き文字で表示する必要はありません。スカラー入力の添字は空です。入力添字はカンマ , で区切られます。<subscript for output> は、一連のラベル (アルファベット文字 ['A',...,'Z','a',...,'z'] を表します。入力添字の長さは入力のランクと一致します。スカラー入力の場合、入力添字は空です。

複数の入力に対する Einsum 操作は、複数の連続する Einsum 操作として扱うことができます。最初のステップでは、Einsum は最初の 2 つの入力を適用します。2 番目のステップでは、最初のステップの結果と 3 番目の入力に基づいて操作します。Einsum は、両方のオペランドからのバッチのすべてのペアによる要素ごとの乗算と同様に、2 つのオペランドを操作します。バッチ次元は、2 つの入力添字のうちの 1 つにのみ属するラベルを使用して定義されます。

例えば、形状 [2, 5], [5, 3, 6] の 3 つの入力と ab,bcd,bc->ca に等しい equation を持つ Einsum の最初のステップ後の中間結果は次のようになります。添字 abcd を持つ形状 [2, 5, 3, 6] のテンソル。最初の入力と 2 番目の入力のバッチ次元は、ラベルシーケンス acd で表されます。次のステップでは、添字 abcd および bc を持つ形状 [2, 5, 3, 6] および [5, 3] の入力テンソルに対して同じロジックを実行し、添え字 abcd が付いた形状 [2, 5, 3, 6] のテンソルを出力します。最後に、出力の添字は、出力次元と総和換算次元の順序を定義します。出力添え字に存在しないラベルに対応する次元は総和換算されます。この例の最終結果は [3,2] に等しい形状になります。ここで、ラベル b および d の次元が削減され、転置が適用されて出力レイアウト ca が得られます。

  • Einsum 操作は 1 つのオペランドに対して実行できます。この場合、操作により入力が転置され、その次元が削減される可能性があります。

  • 入力ランクは、対応する添字の長さと等しくなければなりません。入力添字内の対応するラベルを持つ次元は、サイズが同じである必要があります。

  • ラベルは、同じ入力添字内で繰り返すことができます (例えば、aac,abd,ddde に等しい equation)。この場合、対応する次元のサイズが一致する必要があり、オペランドはこれらの次元に沿った対角線に置き換えられます。例えば、ijkj->ij に等しい equation を使用した、形状 [2, 4, 5, 4] の単一 3D テンソルに対する Einsum 操作です。

  • 仕様では、操作をよりよく理解するために Einsum 操作の原始的なアルゴリズムを考慮しており、実装には推奨されません。

  • 説明したアルゴリズムは、対応するラベルが後続の入力の入力添字と出力添字に存在しない場合、中間結果の即時次元和削減によって改善できます。これは、パフォーマンスを大幅に向上させ、メモリーのコストを削減できます。この例では、最初のステップの後、ラベル d に対応する次元を削減できます。

出力形状は、出力添字内のラベルが指定された順序で対応する次元サイズを連結することによって計算されます。

例 1 は、Einsum が 2 つの 1D テンソルの内積を計算する方法を示しています。

a1 = [1.0, 2.0, 3.0]
a2 = [4.0, 5.0, 6.0]
equation = "i,i->"
output = 32.0

例 2 は、Einsumが行列-ベクトル乗算を計算する方法を示しています。

A = [[1.0, 2.0, 3.0],
     [1.0, 2.0, 3.0]]
b = [4.0, 5.0, 6.0]
equation = "ij,j->i"
output = [32.0, 32.0]

例 3 は、Einsum が各バッチ・オブジェクトのトレースを計算する方法を示しています。

A = [[[1.0, 2.0, 3.0],
      [4.0, 5.0, 6.0],
      [7.0, 8.0, 9.0]],
     [[2.0, 4.0, 6.0],
      [8.0, 10.0, 12.0],
      [14.0, 16.0, 18.0]]]
equation = "kii->k"
output = [15.0, 30.0]

例 4 は、Einsum が各バッチ・オブジェクトの対角線を抽出する方法を示しています。

A = [[[1.0, 2.0, 3.0],
      [4.0, 5.0, 6.0],
      [7.0, 8.0, 9.0]],
     [[2.0, 4.0, 6.0],
      [8.0, 10.0, 12.0],
      [14.0, 16.0, 18.0]]]
equation = "kii->ki"
output = [[1.0, 5.0, 9.0],
          [2.0, 10.0, 18.0]]

例 5 は、Einsum が入力テンソルを転置する方法を示しています。

A = [[[1.0, 2.0, 3.0],
      [4.0, 5.0, 6.0],
      [7.0, 8.0, 9.0]]]
equation = "ijk->kij"
output = [[[1.0, 4.0, 7.0]],
          [[2.0, 5.0, 8.0]],
          [[3.0, 6.0, 9.0]]]

アルファベットのラベルに加えて、省略記号 ... を下付き文字のラベルとして使用して、ブロードキャストされる次元をカバーできます。各入力添字には、最大 1 つの省略記号を含めることができます。例えば、5 ランクのテンソルの入力添字 a...bc の省略記号は、2 次元と 3 次元をカバーします。入力添字に複数のオペランドの省略記号が含まれている場合、要素ごとの操作のブロードキャスト・ルールで使用できる numpy ブロードキャスト (または多方向ブロードキャスト) ルールを満たすために、省略記号でカバーされる次元がブロードキャスト可能である必要があります。少なくとも 1 つの入力添字に省略記号が含まれている場合、出力添字には常に 1 つの省略記号が含まれている必要があります。例えば、形状 [9, 1, 4, 3][3, 11, 7, 1] の 2 つの入力に対する Einsum 操作 (equation="a...b,b...->a...") では、省略記号が付きます。両方のオペランドは、サイズ [1, 4][11, 7, 1] の次元をカバーし、[11, 7, 4] にブロードキャストされます。a のラベルが付いた次元はブロードキャストされた次元のままであるため、Einsum 操作の結果の形状は [9, 11, 7, 4] になります。

例 6 は、Einsum が省略記号を含む方程式を使用して、単一の入力にをどのように操作するか示しています。

A = [[1.0, 2.0, 3.0],
     [4.0, 5.0, 6.0],
     [7.0, 8.0, 9.0]]
equation = "a...->..."
output = [12.0, 15.0, 18.0]

例 7 は、2 つのオペランドをブロードキャストして Einsum がどのように動作するかを示しています。

A = [[1.0, 2.0, 3.0],
     [4.0, 5.0, 6.0],
     [7.0, 8.0, 9.0]]
B = [0.5]
equation = "a...,...->a..."
output = [[0.5, 1.0, 1.5],
          [2.0, 2.5, 3.0],
          [3.5, 4.0, 4.5]]

暗黙モード (アインシュタイン加算の古典的な形式) では、方程式には出力添字がなく、次の形式になります: <subscript for input1>, <subscript for input2>, ..., <subscript for inputn>。暗黙モードの方程式は、各オペランドの入力添字のみで構成されます。出力添字は、方程式の左側で繰り返されない、アルファベット順にソートされた一連のラベルとして復元できます。例えば、暗黙モードの等式 = "dbbc,ca" は、明示的モードの等式 = "dbbc,ca->ad" と同等です。暗黙モードの方程式は、Einstein の合計規則のサブセットのみを設定できます。例えば、等式 = "kii->i" は暗黙モードでは表現できません。省略記号ラベルが暗黙モードで方程式の左側にある場合、省略記号はリカバリーの出力添え字の最初に来ます。

例 8 は、Einsum が、等式 = "AbC" と同じ暗黙モード 等式 = "AbC->ACb" で大文字と小文字の両方を含む方程式でどのように操作するか示しています。

A = [[[1.0, 2.0, 3.0],
      [4.0, 5.0, 6.0]]]
equation = "AbC"
output = [[[1.0, 4.0],
           [2.0, 5.0],
           [3.0, 6.0]]]

両方のモードの等式には、等価性を失わずに削除できる任意の位置に空白文字 (U+0020) を含めることができます。

属性:

  • equation

    • 説明: 入力オペランドに対する Einstein の合計規則を定義します。方程式は明示モードまたは暗黙モードのいずれかである必要があります。

    • 値の範囲: 方程式の形式は前述されています

    • タイプ: string

    • 必須: はい

入力:

  • 複数の入力: T タイプとさまざまな形状のテンソル。

出力:

  • 1: タイプ T と形状のテンソルは、方程式の出力添字に基づいて計算されます。

タイプ:

  • T: 任意の数値タイプ。

例:

<layer ... type="Einsum" version="opset7">
    <data equation="ij,ij->i"/>
    <input>
        <port id="0">
            <dim>2</dim>
            <dim>64</dim>
        </port>
        <port id="0">
            <dim>2</dim>
            <dim>64</dim>
        </port>
    </input>
    <output>
        <port id="2">
            <dim>2</dim>
        </port>
    </output>
</layer>
<layer ... type="Einsum" version="opset7">
    <data equation="ab...,ac...,ade->...bc"/>
    <input>
        <port id="0">
            <dim>2</dim>
            <dim>3</dim>
            <dim>4</dim>
        </port>
        <port id="1">
            <dim>2</dim>
            <dim>7</dim>
            <dim>1</dim>
        </port>
        <port id="3">
            <dim>2</dim>
            <dim>4</dim>
            <dim>7</dim>
        </port>
    </input>
    <output>
        <port id="4">
            <dim>4</dim>
            <dim>3</dim>
            <dim>7</dim>
        </port>
    </output>
</layer>