【Pythonで学ぶ線形代数学講座(19)】行列の階数(rank)の定義と意味
行列の階数(rank)
平面全体の線形変換
これまでの記事では、点や直線、領域などの集合 $V$ について、線形変換 $f$ による像 $f(V)=\mathrm{Im}f$ を調べてきました。
そして今回は $xy$ 平面全体を $V$ に定めて、$f$ の表現行列 $A$ によって移される像を調べます。『連立方程式の解』の記事で学んだように、行列 $A=\begin{bmatrix}a&b\\c&d\end{bmatrix}$ によるベクトル $\begin{bmatrix}x\\y\end{bmatrix}$ の線形変換は
\[x\begin{bmatrix}a\\c\end{bmatrix}+y\begin{bmatrix}b\\d\end{bmatrix}\tag{1}\]
のように、ベクトル $\begin{bmatrix}a\\c\end{bmatrix}$ と $\begin{bmatrix}b\\d\end{bmatrix}$ の線形結合と考えることができます。
$x$ と $y$ がすべての値をとるとき、ベクトル $\begin{bmatrix}x\\y\end{bmatrix}$ は平面全体を表す集合 $V$ であり、$\begin{bmatrix}a\\c\end{bmatrix}$ と $\begin{bmatrix}b\\d\end{bmatrix}$ が平行でない ($\det A\neq 0$) ときは、(1) で表される像 $f(V)=\mathrm{Im}f$ もやはり平面全体を表しています。つまり平面は平面は移ります。
線形変換により個々の点は移動しますが、$f(V)=\mathrm{Im}f$ は全単射なので、複数の点が重複して同じ点に移ることはありません。平面上のすべての点が一斉にずれて新たな平面をつくることになり、結果として見た目は何も変わらないことになります。
$\det A\neq 0$ であっても、行列の成分によって各点のずれ方は様々です。
格子点に平面を代表させて線形変換してみると「ずれ具合」がよくわかります。
Python で格子点を行列 $A=\begin{bmatrix}2&1\\3&5\end{bmatrix}$ で変換してみます。
座標を設定するために、コードライブラリ の coordinate() を実装しておいてください。
# python_linear_transformation_grid # In[1] import numpy as np import matplotlib.pyplot as plt # ここにcoordinate()を実装 # FigureとAxes fig, ax = plt.subplots(2, 1, sharex = "all", figsize=(5, 10)) # 座標を設定 coordinate(ax[0], [-6, 6], [-6, 6], xlabel = "") coordinate(ax[1], [-6, 6], [-6, 6]) # 格子点データを作成 x = np.arange(-10, 10) y = np.arange(-10, 10) X, Y = np.meshgrid(x, y) X = X.reshape(-1) Y = Y.reshape(-1) # XとYを縦軸方向に連結 p0 = np.vstack((X, Y)) # 変換行列を定義 a = np.array([[2, 1], [3, 5]]) # 格子点を行列aで変換 p1 = np.dot(a, p0) # 格子点を表示 ax[0].scatter(X, Y, color = "blue") ax[1].scatter(p1[0], p1[1], color = "red")
今度は $A=\begin{bmatrix}1&2\\2&4\end{bmatrix}$ による平面の像を考えてみます。
この行列は $\det A=0$ です。
すなわち、$A$ による $\begin{bmatrix}x\\y\end{bmatrix}$ の変換は
\[\begin{bmatrix}1&2\\2&4\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}=x\begin{bmatrix}1\\2\end{bmatrix}+y\begin{bmatrix}2\\4\end{bmatrix}=(x+2y)\begin{bmatrix}1\\2\end{bmatrix}\]
となり、平面はつぶれて直線に押し込められます。その様子も Python で確認しておきましょう。
# In[2] # FigureとAxes fig, ax = plt.subplots(2, 1, sharex = "all", figsize=(5, 10)) # 座標を設定 coordinate(ax[0], [-6, 6], [-6, 6], xlabel = "") coordinate(ax[1], [-6, 6], [-6, 6]) # 平面上の点を作成 x = np.linspace(-10, 10, 513) y = np.linspace(-10, 10, 513) X, Y = np.meshgrid(x, y) X = X.reshape(-1) Y = Y.reshape(-1) p0 = np.vstack((X, Y)) # 変換行列を定義 a = np.array([[1, 2], [2, 4]]) # 平面を行列aで変換 p1 = np.dot(a, p0) ax[0].scatter(X, Y) ax[1].scatter(p1[0], p1[1], s = 3)
このように $\det A=0$ のときに平面は潰れてしまいますが、実は潰れ方にはもう1種類あります。それは零行列 $A=\begin{bmatrix}0&0\\0&0\end{bmatrix}$ による変換で、平面上のすべての点を原点 $(0,0)$ に押し込めてしまいます (これについては敢えて Python で計算させるまでもないでしょう)。
行列の階数(rank)
線形変換 $f$ によるベクトル空間 $V$ の像 $f(V)$ の次元を $\mathrm{rank}f$ で表します。
$f$ の表現行列が $A$ であるときは $\mathrm{rank}A$ と書くこともあります。
rank を日本語では 階数 と訳しています。
$\mathrm{rank}$ は像の潰れ具合によって $f$ を分類します。
$V$ が 2 次元であれば、$\mathrm{det}A\neq 0$ のときは $\mathrm{rank}A=2$です。
$\mathrm{det}A=0$ のときは $\mathrm{rank}A=1$ または $\mathrm{rank}A=0$ のどちらかです。
$V$ が 3 次元のときは、行列 $A$ による空間の潰れ方 (潰れない場合も含めます) によって、下図のような 3 種類の $\mathrm{rank}$ がありえます。
言い換えるなら、$\mathrm{rank}$ は行列の中にある線形独立なベクトルの本数です。
たとえば 3 次元行列
\[A=\begin{bmatrix}1&0&0\\0&1&0\\0&0&1\end{bmatrix}\]
によって $xyz$ 空間を線形変換すると
\[\begin{bmatrix}1&0&0\\0&1&0\\0&0&1\end{bmatrix}\begin{bmatrix}x\\y\\z\end{bmatrix}
=x\begin{bmatrix}1\\0\\0\end{bmatrix}+y\begin{bmatrix}0\\1\\0\end{bmatrix}+z\begin{bmatrix}0\\0\\1\end{bmatrix}\]
となり、3 本の線形独立なベクトルによって空間を張るので $\mathrm{rank}A=3$ となります。
numpy.linalg.matrix_rank()
行列の階数 rank は numpy.linalg.matrix_rank() を使って求めることができます。
0 ~ 9 の無作為な成分をもつ 4 × 4 の正方行列を 100 個作って、その中から階数 $3$ 以下の行列を表示してみます。
# numpy_rank # In[1] import numpy as np from numpy import linalg np.random.seed(9) for i in range(100): a = np.random.randint(0, 10, (4, 4)) rank = linalg.matrix_rank(a) if rank < 4: print("rank(a) = {}\n{}\n".format(rank, a)) ''' rank(a) = 3 [[1 6 1 8] [8 6 8 1] [7 0 1 3] [6 2 0 7]] rank(a) = 3 [[1 5 7 6] [1 8 3 7] [0 5 2 7] [1 1 8 2]] '''
100 個のうち僅かに 2 個だけが階数 3 の行列です。以前にも似たようなことをやりましたが、適当にベクトルを選ぶと、ほとんどの場合は線形独立になります。
コメント