多次元配列としてのテンソル、その計算方法

  • このエントリーをはてなブックマークに追加
  • Pocket
  • LINEで送る

この記事では多次元配列としてのテンソルの定義と、その計算方法についてまとめます。

以下のような内容を扱います。

  • テンソル(多次元配列)の定義
  • テンソルの演算
    • 足し算とスカラー倍
    • 内積
    • モード積

多次元配列としてのテンソルの定義

本記事ではテンソルを多次元配列として定義します。この定義は数学や物理学で知られる定義よりも「マイルド」な定義です。

数学や物理学の教科書には、テンソルは双線形写像や基底の変換と関連付けて定義されています。数学のテキストとしては、例えば『線型代数学(新装版)』(佐武)、物理学のテキストとしては『一般相対性理論を一歩一歩数式で理解する』(石井)などが挙げられます。


 

 

数学や物理学でのテンソルの定義は、テンソルの雰囲気や計算方法を知れればよいというユーザーにとっては行き過ぎな感があります。データサイエンスや機械学習などの学習にあたっては、テンソルは「多次元配列」として理解するだけで済む場合も多く、本記事でもそれを踏襲します。

テンソルを多次元配列として定義する方針を取るテキストとしては以下がわかりやすいです。

1次元配列はベクトル、2次元配列は行列(マトリクス)という呼び名があるのはご存知のとおりですが、3次元以上の配列もひっくるめてテンソルと呼ぶことにします(ベクトルは1次元テンソル、行列は2次元テンソル)。D次元テンソルはD個のインデックスを指定することで、値が一つ定まります。以下、テンソルは大文字筆記体で\(\mathcal{X,Y} \)のように表します。

テンソル\(\mathcal{X} \)を\(I\times J\times K \)次元の多次元配列、すなわちテンソルとします。\( \mathcal{X}\)の要素は、\(i\in\left\{1,…,I \right\},j\in\left\{1,…,J \right\},k\in\left\{1,…,K \right\} \)の各インデックスを指定すると定まります。

\begin{equation} \begin{split}
\mathcal{X}=(x_{ijk})
\end{split} \end{equation}

テンソル\( \mathcal{X}\)の\( ijk\)成分を\( \left[\mathcal{X} \right]_{ijk}\)とも書きます。

次元、次数、モード

\(i\in\left\{1,…,I \right\},j\in\left\{1,…,J \right\},k\in\left\{1,…,K \right\} \)の3つのインデックスをもつテンソル\( \mathcal{X}=(x_{ijk})\)は3次元配列です。この「3次元」というのは「3つのインデックスをもつ」という意味ですが、この「3」は次元ではなく次数もしくは階数とよぶのが適当です。したがって\( \mathcal{X}=(x_{ijk})\)は3次のテンソル、もしくは3階のテンソルです。

\( I,J,K\)は3次テンソル\( \mathcal{X}=(x_{ijk})\)の「軸」を表していますが、この「軸」をモードといいます。各モードの長さを次元といいます。3次テンソル\( \mathcal{X}=(x_{ijk})\)の1つめのモードは\(i\in\left\{1,…,I \right\}\)というインデックス(添字)がつけられていて、その次元は\( I\)です。

 

テンソルの演算

足し算(要素ごとの和)とスカラー倍

\(I\times J\times K \)次元のテンソル\(\mathcal{X}=(x_{ijk}),\mathcal{Y}=(y_{ijk}) \)の和\( \mathcal{X+Y}\)は

\begin{equation} \begin{split}
\left[ \mathcal{X+Y}\right]_{ijk}=(x_{ijk}+y_{ijk})
\end{split} \end{equation}

で定義されます。つまり要素ごとの足し算です。次元が異なる場合には定義できません。\( 1\times 2\)行列と\(3\times 4 \)行列を足せないのと同じことです。

テンソルのスカラー倍\(a \mathcal{X}\)も要素ごとのスカラー倍として

\begin{equation} \begin{split}
\left[ a\mathcal{X}\right]_{ijk}=(ax_{ijk})
\end{split} \end{equation}

で定義されます。

内積

ベクトル\(\boldsymbol{ v }=(v_i),\boldsymbol{ w}=(w_i)\)の内積\(<\boldsymbol{ v},\boldsymbol{ w }>\) は

\begin{equation} \begin{split}
<\boldsymbol{ v},\boldsymbol{ w }>=\sum_i v_iw_i
\end{split} \end{equation}
と定義されたことを思い出しましょう。この定義は「同じ次元を持つ配列の内積は、要素ごとの積の和」と解釈できます。これを多次元配列としてのテンソルにも当てはめます。

\(I\times J\times K \)次元のテンソル\(\mathcal{X}=(x_{ijk}),\mathcal{Y}=(y_{ijk}) \)の内積和\( <\mathcal{X},\mathcal{Y}>\)は

\begin{equation} \begin{split}
<\mathcal{X},\mathcal{Y}>=\sum_i \sum_j \sum_k x_{ijk}y_{ijk}
\end{split} \end{equation}

と定義されます。

この内積の定義は2次元配列である行列にも有効です。ここでは内積と呼びましたが、同じサイズをもつ行列の要素ごとの積には「アダマール積」という名前がついています。

モード積

ベクトル(1次元配列)と行列(2次元配列)、行列どうし(2次元配列どうし)の掛け算ができたように、多次元配列としてのテンソルについても掛け算を定義できると都合がいいです。\(I \)次元ベクトル\(\boldsymbol{x } =(x_i)\)と\(I\times J \)行列\(A=(\boldsymbol{ a}_i)=(a_{ij}) \)の積が

\begin{equation} \begin{split}
A^T\boldsymbol{x }&=(\sum_i x_i\boldsymbol{ a}_i)\\
\Leftrightarrow \left[ A^T\boldsymbol{x }\right]_j&=\sum_i x_ia_{ij}
\end{split} \end{equation}

と定義できたことを思い出しましょう。同じ添字\( i\)を持つ要素を掛け合わせ、添字\(i \)について和をとるという操作です。

行列とベクトル、行列と行列の積は、行列のサイズが揃っていなければ定義できませんでした。これは「行列のどのモードについて積をとるか(行のモードか列のモードか)」が重要な意味を持つことを示唆しています。テンソルの積も同様で、どのモードに対して積をとるかを明示的に扱う必要があります。

\( J\)次元ベクトル\( \boldsymbol{ y}=(y_j)\)と\(I\times J\times K \)次元の3次テンソル\( \mathcal{X}=(x_{ijk}),i\in\left\{1,…,I \right\},j\in\left\{1,…,J \right\},k\in\left\{1,…,K \right\}\)との積は、次元が一致する\( J\)のモードに対してのみ定義可能です。モード\( j\in{1,…,J}\)の対して定義されるテンソルの積をモード\( j\)積と呼び、その演算を\( \times_j\)と表します。\( \boldsymbol{ y}=(y_j)\)と\( \mathcal{X}=(x_{ijk})\)のモード\( j\)積は

\begin{equation} \begin{split}
\boldsymbol{ y}\times_j\mathcal{X} =\sum_j y_jx_{ijk}
\end{split} \end{equation}
と定義され、\( \boldsymbol{ y}\times_j\mathcal{X}\)は\(I\times K \)次元の2次のテンソルになります。

3次テンソル\( \mathcal{X}=(x_{ijk})\)と\( \mathcal{Y}=(Y_{jkl})\)のモード積は、モード\( j\)積とモード\( k\)積の2つを考えることができて、次のように定義されます。

\begin{equation} \begin{split}
\mathcal{X}\times_j \mathcal{Y}=\sum_j x_{ijk}y_{jkl}\\
\mathcal{X}\times_k \mathcal{Y}=\sum_k x_{ijk}y_{jkl}
\end{split} \end{equation}

\( \mathcal{X}\times_j \mathcal{Y}\)は\( I\times K\)次元の2次のテンソル、\(\mathcal{X}\times_k \mathcal{Y} \)は\( I\times J\)次元の2次のテンソルになります。

3次テンソル\( \mathcal{X}=(x_{ijk})\)と\( \mathcal{Z}=(z_{klm})\)のモード積は、モード\( k\)積のみ考えることができて、次のように定義されます。

\begin{equation} \begin{split}
\mathcal{X}\times_k \mathcal{Z}=\sum_k x_{ijk}z_{klm}
\end{split} \end{equation}

\( \mathcal{X}\times_k \mathcal{Z}\)は\( I\times J\times L\times M\)次元の4次のテンソルになります。

一般に\( P\)次のテンソル\( \mathcal{X}=(x_{i_1i_2…i_P})(i_p=1,…,I_p,p=1,…,P)\)と\( Q\)次のテンソル\( \mathcal{Y}=(Y_{j_1j_2…j_Q})(j_q=1,…,J_q,q=1,…,Q)\)に対して、次元が一致するモードに対してモード積が定義できます。つまりモード\(i_{p^*}\)の次元=モード\(j_{q^*} \)の次元となるような\(p^*\in \left\{ 1,…,P\right\}, q^*\in \left\{ 1,…,Q\right\}\)が存在して、そのモードの添字を\(r=(i_{p^*}=j_{p^*}) \)とおくと

\begin{equation} \begin{split}
\mathcal{X}\times_r \mathcal{Y}=\sum_r x_{i_1i_2…i_P}y_{j_1j_2…j_Q}
\end{split} \end{equation}
としてモード\( r\)積が定義されます。\( \mathcal{X}\times_r \mathcal{Y}\)の次元は
\begin{equation} \begin{split}
\underbrace{I_1\times\cdots\times I_{p^*-1}\times I_{p^*+1}\times I_P}_{P-1個}\times\underbrace{ J_1\times\cdots\times J_{q^*-1}\times J_{q^*+1}\times J_Q}_{Q-1個}
\end{split} \end{equation}
となります。\( r\)のほかに一致する次元を持たない場合には、このテンソルは\(P+Q-2 \)個のモードを持つといえます。

参考文献

本記事は以下のテキストを参考にしました。本記事では触れられなかった別の演算(外積やスライス)を扱っており、多次元配列としてのテンソルを計算する方法がよくまとまっています。本書ではテンソルを関係データの分析に用い、いくつもの「軸」を持つデータ(たとえば時間、場所、性別の情報を持つ来客データ)から有用な情報を得るための手法が解説されています。

  • このエントリーをはてなブックマークに追加
  • Pocket
  • LINEで送る

SNSでもご購読できます。

コメントを残す

*