東京大学講師の松井と申します。本記事は壁 Advent Calendar 2023の12/7のものです。

壁を作る

数式を書いているとき、数を並べて壁(行列)を作りたいなと思うことがあります。例えば「7」を\(2 \times 3\)に並べると次のようになります。

\[\begin{bmatrix} 7 & 7 & 7 \\ 7 & 7 & 7 \end{bmatrix}\]

これでOKですが、もし行列のサイズが \(n \times m\) のように変数として与えられる場合はどうすればいいでしょうか?また、スカラだけでなくベクトルや行列を並べたいときはどうすればいいでしょうか?

本記事では、スカラを並べるスカラ壁、ベクトルを並べるベクトル壁、行列を並べる行列壁を簡潔に記述する方法を紹介します。

スカラ壁

「\(a \in \mathbb{R}\)」というスカラを \(n \times m\) に並べてスカラ壁を作りたいとき、単純に次のように書けます。

\[\begin{bmatrix} a & \cdots & a \\ \vdots & \ddots & \vdots \\ a & \cdots & a \end{bmatrix}\]

ですがこの表記は行列の大きさがパッと見わからないですし、スカラを並べるだけにしては大仰です。ここでは「全ての要素が1である行列(オールワンマトリクス)」\(\mathbf{1}_{n \times m}\)を使うことで次のように書けます。

\[a\mathbf{1}_{n \times m} = a \begin{bmatrix} 1 & \cdots & 1 \\ \vdots & \ddots & \vdots \\ 1 & \cdots & 1 \end{bmatrix}\]

この書き方は全ての情報が必要十分にまとまっていて気持ちいいですね。

この表記を知っていると、たとえばある行列\(\mathbf{A} \in \mathbb{R}^{n \times m}\)の全要素から\(a\)を引くという処理は次のように簡単に書けます。

\[\mathbf{A} - a\mathbf{1}_{n \times m}\]

ベクトル壁

さて、次は\(n\)次元ベクトル \(\mathbf{v} \in \mathbb{R}^n\)を横に\(m\)個並べて\(n \times m\)のベクトル壁を作ってみましょう。これは次のように書けますが、ちょっと自明ではないかもしれないです。

\[\begin{bmatrix} \mathbf{v} & \cdots & \mathbf{v} \end{bmatrix}\]

見にくいので、縦線を入れることもあると思います。

\[\begin{bmatrix} \vert & & \vert \\ \mathbf{v} & \cdots & \mathbf{v} \\ \vert & & \vert \end{bmatrix}\]

この書き方は\(\mathbf{v}\)が並んでいる感が出て良いですが、行列サイズを明示的に述べたい場合は不便です。どうすればいいでしょうか。

実はこれは非常に簡単に、「要素全て1の横ベクトル」と\(\mathbf{v}\)の行列積の形で書き下せます。

\[\mathbf{v} \mathbf{1}_{1 \times m} = \mathbf{v}\mathbf{1}_m^\top = \mathbf{v} [1, \dots, 1]\]

上記は展開すれば\(\mathbf{v}\)が並んだものになることがわかります。「1の横ベクトル」は、当然ながら最初から横に定義(\(\mathbf{1}_{1 \times m}\))しても、縦で定義して転置(\(\mathbf{1}_m^\top\))しても、OKです。本記事では縦ベクトルを転置するスタイルで統一します。

ここで、「プログラミングっぽく\(\mathtt{stack}\)みたいな関数を定義してしまって\(\mathtt{stack}(\mathbf{v})\)みたいに書いてもいいんじゃないの?」と思うかもしれません。しかし、一般的に、線形代数の表記で書き下せる場合は書き下しておくほうが、メリットがあります。それは、他の線形代数の演算に組み込まれたときに式変形出来ることがあるためです。

たとえば、\(n \times m\) の行列 \(\mathbf{A} \in \mathbb{R}^{n \times m}\)に対し、各列の平均を取る操作を考えます。これは次のように書けます。

\[\frac{1}{m} \mathbf{A} \mathbf{1}_m\]

ここで、\(\mathbf{A}\)に上記のベクトル壁を入れる場合を考えてみましょう。この場合、結果は当然ながら\(\mathbf{v}\)そのものになるわけですが、もしここでベクトル壁をプログラミングっぽく書いていた場合、

\[\frac{1}{m} \mathtt{stack}(\mathbf{v}) \mathbf{1}_m\]

となりここで終わってしまいます。

しかし、ちゃんと線形代数の言葉で書いていた場合、

\[\frac{1}{m} (\mathbf{v} \mathbf{1}_m^\top) \mathbf{1}_m = \frac{1}{m} \mathbf{v} (\mathbf{1}_m^\top \mathbf{1}_m) = \frac{1}{m} \mathbf{v} m = \mathbf{v}\]

となり、\(\mathbf{v}\)そのものになるという結果を導出することが出来ました。

同様に、\(n \times m\) 行列\(\mathbf{A}\)の各行の平均をとる操作を考えてみましょう。これは次にようになります。

\[\frac{1}{n} \mathbf{1}_n^\top \mathbf{A}\]

ここにベクトル壁を入れてみると、

\[\frac{1}{n} \mathbf{1}_n^\top (\mathbf{v} \mathbf{1}_m^\top) = \frac{1}{n} (\mathbf{1}_n^\top \mathbf{v}) \mathbf{1}_m^\top = \mu \mathbf{1}_m^\top\]

となります。ここで、\(\mu = \frac{1}{n} \mathbf{1}_n^\top \mathbf{v}\) は、ベクトル\(\mathbf{v}\)の要素の平均を意味します。 つまり、ここでの最終結果は「\(\mathbf{v}\)の平均値を横に\(m\)個並べたもの」ということがわかります。これは ベクトル壁の定義を考えれば当たり前の結果ですね。この導出も、ベクトル壁をプログラミングっぽく書いていた場合はたどり着けません。

上記の平均計算は簡単な例ですが、より複雑な式変形を行う場合は、ちゃんと線形代数的に書き下しておくと思いもよらない変形が出来て嬉しい場面があるかもしれません。

行列壁

さて、いよいよ本題です。ここまではよく知られていた表記でした。それでは、行列を並べて行列壁を作るにはどうすればいいでしょうか?

\(\mathbf{A} \in \mathbb{R}^{n \times m}\) を横方向に\(k\)個並べて、\(n \times mk\) の行列壁を作ることを考えましょう。これは以下のように直接書くことが出来ます。

\[\begin{bmatrix} \mathbf{A} & \cdots & \mathbf{A} \end{bmatrix}\]

あるいは、単位行列をくくりだして以下のように書くことも出来るでしょう。

\[\mathbf{A} \left[ \begin{array}{ccc|ccc|c|ccc} 1 & & & 1 & & & & 1 & & \\ & \ddots & & & \ddots & & \cdots & & \ddots & \\ & & 1 & & & 1 & & & & 1 \\ \end{array} \right] = \mathbf{A} \begin{bmatrix} \mathbf{I}_m & \cdots & \mathbf{I}_m \end{bmatrix}\]

ですが、ウ~ン、なんかイマイチ!もっと気持ちよくまとめられそうな気がしてきます。

ここで、クロネッカー積1\(^,\)2を考えましょう。クロネッカー積とは、\(n \times m\) の行列\(\mathbf{X} = \{x_{ij}\}\)と、\(k \times l\) の行列\(\mathbf{Y}\)に対し、\(\mathbf{X} \otimes \mathbf{Y} \in \mathbb{R}^{nk \times ml}\)を以下のように定義するものです。

\[\mathbf{X} \otimes \mathbf{Y} = \begin{bmatrix} x_{11} \mathbf{Y} & x_{12} \mathbf{Y} & \cdots & x_{1m} \mathbf{Y} \\ x_{21} \mathbf{Y} & x_{22} \mathbf{Y} & \cdots & x_{2m} \mathbf{Y} \\ \vdots & \vdots & & \vdots \\ x_{n1} \mathbf{Y} & x_{n2} \mathbf{Y} & \cdots & x_{nm} \mathbf{Y} \end{bmatrix}\]

上記の式からわかるように、クロネッカー積とは、「\(\mathbf{X}\)の各要素\(x_{ij}\)」を用いて\(\mathbf{Y}\)をスカラ倍し、それ\(nm\)個分全て並べてクソデカ行列を作るという演算です。

このクロネッカー積をじっと眺めてみましょう。すると、\(\mathbf{X}\)を\(\mathbf{1}_k^\top\)として、かつ\(\mathbf{Y}\)を\(\mathbf{A}\)とすると、次のような式が得られることがわかります。

\[\mathbf{1}_k^\top \otimes \mathbf{A} = \begin{bmatrix} 1 \mathbf{A} & 1 \mathbf{A} & \cdots & 1 \mathbf{A} \end{bmatrix} = \begin{bmatrix} \mathbf{A} & \mathbf{A} & \cdots & \mathbf{A} \end{bmatrix}\]

これは、求めたかった行列壁そのものです! このように、「オールワンの横ベクトル」と「\(\mathbf{A}\)」のクロネッカー積を取ることで、\(\mathbf{A}\)を並べて行列壁を綺麗に書き下すことが出来ました。

この表記も、やはり式変形で威力を発揮します。 行列壁に対し左から\(\mathbf{B} \in \mathbb{R}^{l \times n}\)をかけることを考えましょう。 もし行列の壁を、数式を使って表現することをあきらめて\(\mathtt{stack}(\mathbf{A})\)のようにプログラムっぽく書いていた場合、\(\mathbf{B}\mathtt{stack}(\mathbf{A})\) としか書けずにここで終わってしまいます。

もし行列の壁を\(\mathbf{1}_k^\top \otimes \mathbf{A}\)と書いていた場合、これは

\[\mathbf{B}(\mathbf{1}_k^\top \otimes \mathbf{A}) = \mathbf{1}_k^\top \otimes (\mathbf{B}\mathbf{A})\]

となり、「\(\mathbf{B}\mathbf{A}\)を\(k\)個並べて行列の壁を作ったもの」になることがわかります。これは元の定義を考えれば \(\mathbf{B} \begin{bmatrix} \mathbf{A} & \cdots & \mathbf{A} \end{bmatrix} = \begin{bmatrix} \mathbf{B}\mathbf{A} & \cdots & \mathbf{B}\mathbf{A} \end{bmatrix}\) なので当然の結果です。

NOTE: ちなみに、上記を計算する際には以下を用いました。クロネッカー積には以下に示す混合積の性質(通常の行列積とクロネッカー積を組み合わせた積に関する性質)があります。

\[(\mathbf{E} \otimes \mathbf{F}) (\mathbf{G} \otimes \mathbf{H}) = (\mathbf{E} \mathbf{G}) \otimes (\mathbf{F} \mathbf{H})\]

ここで、\(\mathbf{E} \in \mathbb{R}^{a \times b}, \mathbf{F} \in \mathbb{R}^{c \times d}, \mathbf{G} \in \mathbb{R}^{b \times e}, \mathbf{H} \in \mathbb{R}^{d \times f}\)です。

ここで\(a = b = 1\)の場合を考えると、\(e \in \mathbb{R}\)および \(\mathbf{g} \in \mathbb{R}^e\)を用いて、上記は次のようになります。

\[(e \otimes \mathbf{F}) (\mathbf{g}^\top \otimes \mathbf{H}) = e\mathbf{F} (\mathbf{g}^\top \otimes \mathbf{H}) = (e \mathbf{g}^\top) \otimes (\mathbf{F} \mathbf{H})\]

ここで両辺を\(e\)で割ることで、次の式を得ます。

\[\mathbf{F} (\mathbf{g}^\top \otimes \mathbf{H}) = \mathbf{g}^\top \otimes (\mathbf{F} \mathbf{H})\]

この式において、\(\mathbf{F}, \mathbf{g}, \mathbf{H}\)に対しそれぞれ\(\mathbf{B}, \mathbf{1}_k, \mathbf{A}\)を代入すると、 元の式変形が得られます。

ちなみに、実はベクトル壁も全く同様にクロネッカー積を用いて次のように書くことができます。

\[\mathbf{1}^\top_m \otimes \mathbf{v} = \begin{bmatrix} \mathbf{v} & \cdots & \mathbf{v} \end{bmatrix}\]

ここでは、直接式を変形することにより、クロネッカー積を使わない元々のベクトル壁表現の導出が可能です。

\[\mathbf{1}^\top_m \otimes \mathbf{v} = \mathbf{v}\mathbf{1}_m^\top\]

ここでは以下の性質を用いました。

NOTE: ベクトル同士のクロネッカー積には以下の性質があります。 任意のベクトル\(\mathbf{a} \in \mathbb{R}^n, \mathbf{b} \in \mathbb{R}^m\)に対して

\[\mathbf{a} \otimes \mathbf{b}^\top = \mathbf{b}^\top \otimes \mathbf{a} = \mathbf{a}\mathbf{b}^\top\]

となります。つまり、「\(\mathbf{a}\)の縦 \(\otimes\) \(\mathbf{b}\)の横」は 「\(\mathbf{b}\)の横 \(\otimes\) \(\mathbf{a}\)の縦」に等しく、それは「\(\mathbf{a}\)の縦と\(\mathbf{b}\)の横の通常の行列積」、すなわち 「\(\mathbf{a}\)の縦と\(\mathbf{b}\)の縦の外積」に等しいということです。

まとめ

このように、オールワンベクトルやクロネッカー積を使うことで様々なを作ることが出来ます。 論文中で提案手法を表現する際にが必要になったら、是非本記事を参考にしてみてください。 最後に、紹介した記述をまとめておきます。

スカラ壁: \(a\in\mathbb{R}\)を\(n \times m\)に並べたものは以下。

\[a\mathbf{1}_{n \times m} = a \begin{bmatrix} 1 & \cdots & 1 \\ \vdots & \ddots & \vdots \\ 1 & \cdots & 1 \end{bmatrix} \in \mathbb{R}^{n \times m}\]

ベクトル壁: \(\mathbf{v} \in \mathbb{R}^n\)を横に\(m\)個並べたものは以下。

\[\mathbf{v} \mathbf{1}_{1 \times m} = \mathbf{v}\mathbf{1}_m^\top = \mathbf{v} [1, \dots, 1] = \begin{bmatrix} \vert & & \vert \\ \mathbf{v} & \cdots & \mathbf{v} \\ \vert & & \vert \end{bmatrix} \in \mathbb{R}^{n \times m}\]

行列壁: \(\mathbf{A} \in \mathbb{R}^{n \times m}\)を横に\(k\)個並べたものは以下。

\[\mathbf{1}_k^\top \otimes \mathbf{A} = \begin{bmatrix} \mathbf{A} & \mathbf{A} & \cdots & \mathbf{A} \end{bmatrix} \in \mathbb{R}^{n \times mk}\]

参考文献

  1. D.A. ハーヴィル、「統計のための行列代数 下」、丸善出版、2012 

  2. 横田達也、「テンソル分解の基礎と応用」、MIRU 2022 チュートリアル