行列の階数(ランク)とは?定義・求め方・次元定理までわかりやすく解説

連立方程式を解こうとしたら「解が存在しない」と言われた。最小二乗法で回帰係数を求めようとしたら「行列が特異です」とエラーが出た。ニューラルネットの重み行列を圧縮したら、性能をほとんど落とさずにパラメータ数を10分の1にできた——。これらの現象の背後にはすべて、同じ1つの量が潜んでいます。それが行列の階数(ランク, rank)です。

ランクは一言でいうと「行列が持っている本質的な情報の量」です。$3 \times 3$ 行列は数字を9個持っていますが、その9個が独立な情報とは限りません。ある行が他の行のコピーや組み合わせでできているなら、見かけは大きくても中身はスカスカです。ランクはこの「実質的な次元」を数える道具であり、連立方程式の解の個数の判定、最小二乗法が壊れる条件の診断、主成分分析やレコメンドシステムで使われる低ランク近似、制御工学の可制御性判定など、応用は理論と実務の両方に広がっています。

本記事の内容

  • ランクの直感的な意味(線形変換が「潰す」次元)と数学的定義
  • 掃き出し法(行基本変形)によるランクの求め方(手計算の例つき)
  • 行ランク = 列ランクの証明
  • 連立一次方程式の解の存在・一意性とランクの関係
  • 次元定理(rank + nullity = n)の導出と直感図
  • フルランク・ランク落ちの幾何学的意味
  • 特異値と数値ランク(np.linalg.matrix_rank の仕組み)
  • 低ランク近似(SVD・画像圧縮)への橋渡しとPython実装

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

ランクとは:行列が「潰す」次元を数える

行列 $A$ は「ベクトルを別のベクトルに変換する機械」、すなわち線形変換として見ることができます。たとえば $2 \times 2$ 行列は、平面上の点を別の点へ移します。このとき重要な問いは次のものです。

変換した結果は、何次元の空間に広がるか?

平面全体(2次元)を入力したとき、出力も平面全体に広がるなら、この変換は2次元分の情報を保っています。一方、出力がすべて1本の直線上に乗ってしまうなら、変換は平面を直線に「潰して」おり、1次元分の情報が失われています。この変換後に残る次元の数こそがランクです。

ランクの概念図:ランク2の変換は平面を保ち、ランク1の変換は平面を直線に潰す

左が変換前の平面、中央がランク2の行列による変換、右がランク1の行列による変換です。ランク2では格子が歪みはするものの平面のまま保たれているのに対し、ランク1では平面全体が1本の直線にぺしゃんこに潰れています。基底ベクトルの行き先 $A\mathbf{e}_1$ と $A\mathbf{e}_2$ が同じ直線に乗ってしまっていること、つまり列ベクトルが線形従属になっていることが潰れの原因です。

この「潰れ」の観察が、そのままランクの定義につながります。次のセクションで言葉を正確にしましょう。

ランクの数学的定義

ランクを定義するために、行列を列ベクトルの集まりとして見ます。$m \times n$ 行列 $A$ の列を $\mathbf{a}_1, \dots, \mathbf{a}_n$ とすると、$A\mathbf{x}$ は

$$ A\mathbf{x} = x_1 \mathbf{a}_1 + x_2 \mathbf{a}_2 + \cdots + x_n \mathbf{a}_n $$

と書けます。つまり $A$ の出力は、列ベクトルの線形結合で作れるベクトル全体です。この集合を列空間 $C(A)$ と呼びます。先ほどの図で「変換後に広がる空間」と呼んでいたものの正体が列空間です。

その上で、ランクは次のように定義されます。

$$ \operatorname{rank}(A) = \dim C(A) = (線形独立な列ベクトルの最大本数) $$

列の代わりに行で同じことを考えると、行ベクトルが張る行空間の次元、すなわち「線形独立な行の最大本数(行ランク)」も定義できます。そして線形代数の美しい定理の1つが、行ランクと列ランクは必ず一致するという事実です。縦に数えても横に数えても同じ値になるので、安心して単に「ランク」と呼べます(証明は後のセクションで与えます)。

列空間の次元としてのランク:線形独立なら平面全体、線形従属なら直線

左の図では2本の列ベクトル $\mathbf{a}_1, \mathbf{a}_2$ が異なる方向を向いているため、線形結合 $x_1\mathbf{a}_1 + x_2\mathbf{a}_2$ は平面全体に届きます(散布点は係数をランダムに振った結合の例)。右の図では $\mathbf{a}_2 = -\frac{1}{2}\mathbf{a}_1$ という従属関係があるため、どう係数を選んでも結合は1本の直線から出られません。列空間の次元、つまりランクが2と1である様子がそのまま見て取れます。

定義はわかりましたが、$5 \times 7$ 行列の「線形独立な列の最大本数」を定義どおり総当たりで調べるのは現実的ではありません。そこで登場するのが、機械的にランクを求めるアルゴリズム——掃き出し法です。

掃き出し法によるランクの求め方

ランク計算の実用上の主役は、ガウスの消去法でも使った行基本変形です。行基本変形とは次の3つの操作を指します。

  1. 2つの行を入れ替える
  2. ある行を0でない定数倍する
  3. ある行に別の行の定数倍を加える

これらの操作はどれも「行ベクトルの張る空間(行空間)」を変えません。行の入れ替えと定数倍は張る空間に影響せず、「別の行の定数倍を加える」操作も、元の行の組から復元できる(逆操作が存在する)ため、張れるベクトルの範囲は変わらないからです。行基本変形でランクは不変——これがアルゴリズムの根拠になります。

手順は次のとおりです。

  1. 行基本変形を繰り返して、行列を行階段形(各行の先頭の非ゼロ成分が、右下へ階段状に下がっていく形)にする
  2. 非ゼロの行の本数を数える。それがランク

実際に手を動かしてみましょう。次の行列のランクを求めます。

$$ A = \begin{pmatrix} 1 & 2 & 1 \\ 2 & 4 & 3 \\ 3 & 6 & 4 \end{pmatrix} $$

まず第1行を使って、第1列の2行目以降を消します。第2行から第1行の2倍を引き、第3行から第1行の3倍を引きます。

$$ \begin{pmatrix} 1 & 2 & 1 \\ 2 & 4 & 3 \\ 3 & 6 & 4 \end{pmatrix} \longrightarrow \begin{pmatrix} 1 & 2 & 1 \\ 0 & 0 & 1 \\ 0 & 0 & 1 \end{pmatrix} $$

第2列はどちらの行も0になってしまったので、ピボット(各行の先頭の非ゼロ成分)は第3列に現れます。第3行から第2行を引くと、

$$ \begin{pmatrix} 1 & 2 & 1 \\ 0 & 0 & 1 \\ 0 & 0 & 1 \end{pmatrix} \longrightarrow \begin{pmatrix} 1 & 2 & 1 \\ 0 & 0 & 1 \\ 0 & 0 & 0 \end{pmatrix} $$

階段形が完成しました。非ゼロの行は2本なので、$\operatorname{rank}(A) = 2$ です。

行基本変形による階段形への変形でランク2が求まる例

変形の流れを図にするとこのようになります。$3 \times 3$ 行列なのにランクが2しかないのは、よく見ると第2列が第1列のちょうど2倍($\mathbf{a}_2 = 2\mathbf{a}_1$)になっているからです。9個の数字のうち1列分は他の列から再現できる「冗長な情報」だった、というわけです。

一般の行階段形では、ピボットの位置は次の図のように右下へ階段状に下がっていきます。

行階段形とピボットの位置:ピボットの個数がランク

赤い■がピボット、 は任意の値、0は消去済みの成分です。ピボットの個数 = 非ゼロ行の本数 = ランク*という関係が一目でわかります。ピボットを含む列は互いに線形独立で、ピボットを含まない列はピボット列の線形結合で書ける、という構造になっています。

Pythonでは numpy で一発で確認できます。

import numpy as np

A = np.array([[1, 2, 1],
              [2, 4, 3],
              [3, 6, 4]])

print("rank(A) =", np.linalg.matrix_rank(A))  # => 2
print("det(A)  =", np.linalg.det(A))          # => ほぼ 0

出力は rank(A) = 2det(A) = 0.0(数値誤差程度)となり、手計算と一致します。行列式が0になるのは偶然ではありません。後のセクションで見るように、正方行列では「ランク落ち $\Leftrightarrow$ 行列式が0」という関係があります。

ところで、ここまで「行を変形して数えた本数」をランクと呼んできましたが、定義したのは「列空間の次元」でした。行で数えた結果と列で数えた結果が一致することは、まだ証明していません。次のセクションで決着をつけましょう。

行ランク = 列ランクの証明

ゴール: 任意の $m \times n$ 行列 $A$ について、行空間の次元と列空間の次元が等しいことを示します。

証明にはいくつかの流儀がありますが、ここでは見通しの良い分解による証明を紹介します。列ランク(列空間の次元)を $r$ とおきます。

列空間の基底を $\mathbf{c}_1, \dots, \mathbf{c}_r \in \mathbb{R}^m$ とし、これを並べた $m \times r$ 行列を $C$ とします。$A$ の各列は列空間の元なので、基底の線形結合で書けます。つまり、$j$ 列目について

$$ \mathbf{a}_j = r_{1j}\mathbf{c}_1 + r_{2j}\mathbf{c}_2 + \cdots + r_{rj}\mathbf{c}_r $$

となる係数 $r_{ij}$ が存在します。この係数を並べた $r \times n$ 行列を $R$ とすると、$n$ 本の列についての関係式をまとめて

$$ A = C R $$

と書けます。ここからが核心です。$A = CR$ を今度は行の側から読み直します。行列の積の規則から、$A$ の第 $i$ 行は「$R$ の $r$ 本の行を、$C$ の第 $i$ 行の成分を係数として線形結合したもの」です。つまり $A$ のすべての行は、たった $r$ 本のベクトル($R$ の行)の線形結合で書けます。線形結合で張れる空間の次元は元の本数を超えないので、

$$ (A \text{ の行ランク}) \leq r = (A \text{ の列ランク}) $$

が得られました。あとは同じ議論を転置行列 $A^{\top}$ に適用します。$A^{\top}$ の行は $A$ の列、$A^{\top}$ の列は $A$ の行なので、

$$ (A \text{ の列ランク}) = (A^{\top} \text{ の行ランク}) \leq (A^{\top} \text{ の列ランク}) = (A \text{ の行ランク}) $$

両方向の不等式が揃ったので、行ランクと列ランクは一致します。証明終わりです。

この証明から出てきた $A = CR$ という分解は、それ自体が重要な視点を含んでいます。ランク $r$ の $m \times n$ 行列は、$m \times r$ 行列と $r \times n$ 行列の積に圧縮できる——成分の個数でいえば $mn$ 個が $(m + n)r$ 個で済むのです。これが記事の終盤で扱う低ランク近似の原型になっています。

ランクの定義と計算方法が固まったので、基本性質を一覧で整理してから、応用の本丸である連立方程式に進みます。

ランクの基本性質

頻繁に使う性質をまとめます。$A$ は $m \times n$ 行列とします。

性質 直感
サイズによる上限 $\operatorname{rank}(A) \leq \min(m, n)$ 独立な行・列は行数・列数を超えない
転置不変性 $\operatorname{rank}(A^{\top}) = \operatorname{rank}(A)$ 行ランク = 列ランク
積のランク $\operatorname{rank}(AB) \leq \min(\operatorname{rank}A, \operatorname{rank}B)$ 変換を重ねても次元は増えない
和のランク $\operatorname{rank}(A+B) \leq \operatorname{rank}A + \operatorname{rank}B$ 列空間の和で張られる
正則行列との積 $P, Q$ が正則なら $\operatorname{rank}(PAQ) = \operatorname{rank}(A)$ 可逆な変換は次元を保つ
正方行列の正則性 $n \times n$ で $\operatorname{rank}(A) = n \Leftrightarrow \det A \neq 0 \Leftrightarrow A^{-1}$ が存在 潰れない $\Leftrightarrow$ 逆変換できる
グラム行列 $\operatorname{rank}(A^{\top}A) = \operatorname{rank}(A)$ 最小二乗法の正規方程式が解ける条件

特に「積のランクは増えない」という性質は直感的に重要です。一度ランク1の行列で直線に潰してしまった情報は、その後どんな行列を掛けても平面には戻りません。情報の損失は不可逆なのです。また最後のグラム行列の性質は、最小二乗法の正規方程式 $A^{\top}A\hat{\mathbf{x}} = A^{\top}\mathbf{b}$ が一意に解ける条件($A$ が列フルランク)を与える、統計・機械学習で頻出の事実です。

これらの道具を手に、ランクの最も古典的な応用——連立一次方程式の解の判定——を見ていきましょう。

連立一次方程式の解とランク

連立一次方程式 $A\mathbf{x} = \mathbf{b}$ はいつ解を持ち、解はいくつあるのでしょうか。ランクを使うと、この問いに完全な答えが出せます。

まず解の存在です。$A\mathbf{x}$ は列ベクトルの線形結合でしたから、「解が存在する」とは「$\mathbf{b}$ が列空間 $C(A)$ に入っている」ことと同じです。これをランクの言葉に翻訳すると、係数行列 $A$ に $\mathbf{b}$ を1列付け加えた拡大係数行列 $[A \mid \mathbf{b}]$ を使って、

$$ A\mathbf{x} = \mathbf{b} \text{ が解を持つ} \iff \operatorname{rank}(A) = \operatorname{rank}([A \mid \mathbf{b}]) $$

と書けます(ルーシェ=カペリの定理)。$\mathbf{b}$ が列空間の中にあれば、$\mathbf{b}$ を付け加えても独立な列は増えずランクは変わらない。逆に $\mathbf{b}$ が列空間の外にあれば、$\mathbf{b}$ は新しい独立な方向なのでランクが1増える、という理屈です。

次に解の一意性です。解が存在するとき、未知数の個数を $n$ として、

  • $\operatorname{rank}(A) = n$ ならば解はただ1つ
  • $\operatorname{rank}(A) = r < n$ ならば解は $n - r$ 個の自由パラメータを持つ無限族

になります。自由パラメータの個数 $n – r$ は、階段形でピボットが立たなかった列(自由変数)の個数に対応します。

2元連立方程式(平面上の2直線)で3つの場合を図にすると、状況が一目で整理できます。

ランクで決まる連立一次方程式の解の個数(一意解・無数の解・解なし)

左は2直線が1点で交わる場合で、$\operatorname{rank}(A) = \operatorname{rank}([A|\mathbf{b}]) = 2 = n$ となり一意解。中央は2本目の式が1本目の定数倍にすぎない場合で、ランクは1のまま一致し($< n$)、直線上のすべての点が解になります。右は左辺だけ定数倍で右辺が食い違う場合で、$\operatorname{rank}(A) = 1 < \operatorname{rank}([A|\mathbf{b}]) = 2$ となり平行線は交わらず解なし。方程式の本数ではなく、独立な情報の本数(ランク)が解の運命を決めることがよくわかります。

ここで「解が無限にあるとき、その自由度はなぜぴったり $n – r$ なのか」という疑問が残っています。この疑問に答えるのが、線形代数のハイライトの1つである次元定理です。

次元定理(rank-nullity theorem)の導出

$A\mathbf{x} = \mathbf{0}$ を満たすベクトル $\mathbf{x}$ の集合を零空間(核)$N(A)$ と呼びます。零空間は「変換 $A$ で原点に潰されてしまう方向」の集まりで、その次元 $\dim N(A)$ を退化次数(nullity)といいます。次元定理は、ランクと退化次数の間の正確なトレードオフを主張します。

$$ \operatorname{rank}(A) + \dim N(A) = n \quad (n \text{ は } A \text{ の列数}) $$

ゴール: この等式を、掃き出し法の構造を使って導出します。

$A$ を行階段形に変形し、ランクを $r$ とします。このとき $n$ 本の列は次の2種類に分かれるのでした。

  • ピボット列: $r$ 本。対応する変数は他の変数から決まる「従属変数」
  • ピボットなしの列: $n – r$ 本。対応する変数は自由に選べる「自由変数」

$A\mathbf{x} = \mathbf{0}$ の解は、自由変数 $n – r$ 個の値を好きに決めると、従属変数がそれに応じて一意に定まる、という構造をしています。そこで「自由変数の1つを1、残りを0」とおいて得られる解を $\mathbf{v}_1, \dots, \mathbf{v}_{n-r}$ とすると、これらは線形独立で(各 $\mathbf{v}_i$ は自分専用の自由変数の位置に1を持つため)、しかも任意の解は

$$ \mathbf{x} = t_1 \mathbf{v}_1 + t_2 \mathbf{v}_2 + \cdots + t_{n-r} \mathbf{v}_{n-r} $$

と一意に書けます。つまり $\{\mathbf{v}_i\}$ は零空間の基底であり、

$$ \dim N(A) = n – r = n – \operatorname{rank}(A) $$

が示されました。移項すれば次元定理そのものです。先ほどの「解の自由度が $n – r$」という事実は、次元定理の言い換えだったわけです。

式の上では以上で導出完了ですが、この定理の「気持ち」を図で押さえておきましょう。

次元定理 rank + nullity = n の直感図:行空間と零空間の分解

定義域 $\mathbb{R}^n$ は、行空間($r$ 次元)と零空間($n-r$ 次元)という互いに直交する2つの部分空間に分解されます。零空間の成分は $A$ によってすべて $\mathbf{0}$ に潰され、行空間の成分は列空間へ1対1に移されます。入力の $n$ 次元は「生き残る $r$ 次元」と「潰される $n-r$ 次元」に過不足なく振り分けられる——これが次元定理の直感的な内容です。情報の保存則のようなものだと思うと覚えやすいでしょう。

次元の「会計」が合うことを確認したところで、今度はランクが最大の場合とそうでない場合の幾何学的な違いを、3次元で見てみます。

フルランクとランク落ちの幾何学的意味

$\operatorname{rank}(A) = \min(m, n)$ のとき、$A$ はフルランクであるといいます。正方行列がフルランクなら逆行列が存在し、変換は完全に巻き戻せます。一方 $\operatorname{rank}(A) < \min(m,n)$ の状態をランク落ち(rank deficient)と呼びます。

$3 \times 3$ 行列で、単位立方体内のランダムな点を変換してみると、両者の違いは劇的です。

3次元線形変換のフルランクとランク落ち:立方体が平面に潰れる様子

左のフルランク(ランク3)の変換では、立方体は歪んだ平行六面体になりますが、体積を持つ3次元の塊のままです。右はわざと第3列を「第1列+第2列」にしたランク2の行列で、立方体全体が厚みゼロの平面に押し潰されています。体積が0になるということは行列式が0ということであり、行列式の幾何学的意味(体積拡大率)とランクがここでつながります。

  • ランク3: 体積 $\to$ 体積($\det A \neq 0$、逆変換可能)
  • ランク2: 体積 $\to$ 平面($\det A = 0$、潰れた方向は復元不能)
  • ランク1: 体積 $\to$ 直線
  • ランク0: すべて原点(零行列のみ)

ランク落ちは実務では「悪い知らせ」であることが多い概念です。回帰分析で説明変数同士がほぼ線形従属だと(多重共線性)、$A^{\top}A$ がランク落ち寸前になり係数推定が不安定になります。ロボットアームの運動学では、ヤコビ行列のランク落ちが「特異姿勢」(動かせない方向が生じる構え)に対応します。

ところで、ここまでの理論はすべて「成分は厳密な値」という前提でした。しかし現実のデータは測定ノイズや丸め誤差を含みます。「厳密には潰れていないが、ほぼ潰れている」行列をどう扱えばよいのでしょうか。ここで特異値の出番です。

特異値と数値ランク:matrix_rank の仕組み

特異値分解(SVD)によれば、任意の $m \times n$ 行列は

$$ A = U \Sigma V^{\top}, \qquad \Sigma = \operatorname{diag}(\sigma_1, \sigma_2, \dots), \quad \sigma_1 \geq \sigma_2 \geq \cdots \geq 0 $$

と分解できます。$\sigma_i$ が特異値で、「変換 $A$ が $i$ 番目に強く伸ばす方向の倍率」を表します。ランクとの関係は非常にシンプルです。

$$ \operatorname{rank}(A) = (0 \text{ でない特異値の個数}) $$

倍率が0の方向は完全に潰される方向なので、これは「潰されずに生き残る方向の本数 = ランク」という冒頭の直感のそのままの定式化です。

問題は、ノイズを含む現実の行列では特異値が厳密に0にならないことです。本当はランク5の行列にわずかなノイズが乗ると、6番目以降の特異値は $10^{-8}$ のような微小な正の値になり、「0でない特異値の個数」を文字どおり数えるとランク20(フルランク)と誤判定してしまいます。

そこで実用上は、小さすぎる特異値は0とみなすしきい値を設けます。これが数値ランクの考え方です。

特異値の急落としきい値による数値ランクの判定

左は理論上の特異値で、6番目以降は厳密に0です。右はノイズを加えた同じ行列の特異値を対数軸で見たもので、5番目と6番目の間に約7桁の「崖」があります。しきい値(赤破線)をこの崖の間に引き、それより大きい特異値だけを数えることで、ノイズに惑わされず「実質ランク5」と判定できます。特異値の急落はその行列の本質的な次元が尽きたサインなのです。

NumPyの np.linalg.matrix_rank はまさにこの方法を実装しています。デフォルトのしきい値は

$$ \text{tol} = \sigma_{\max} \times \max(m, n) \times \varepsilon $$

($\varepsilon$ は浮動小数点のマシンイプシロン、約 $2.2 \times 10^{-16}$)で、これより大きい特異値の個数を返します。動作を確認してみましょう。

import numpy as np

rng = np.random.default_rng(42)

# 真のランクが5の20x20行列を作り、微小ノイズを加える
U, _ = np.linalg.qr(rng.normal(size=(20, 20)))
V, _ = np.linalg.qr(rng.normal(size=(20, 20)))
sv_true = np.array([10, 7, 4.5, 2.5, 1.2] + [0] * 15)
A_clean = U @ np.diag(sv_true) @ V.T
A_noisy = A_clean + rng.normal(0, 1e-8, (20, 20))

s = np.linalg.svd(A_noisy, compute_uv=False)
print("特異値(上位8個):", np.round(s[:8], 10))
print("デフォルトの判定  :", np.linalg.matrix_rank(A_noisy))
print("tolを明示した判定 :", np.linalg.matrix_rank(A_noisy, tol=1e-5))

実行すると、特異値は5番目までが $1.2$ 以上、6番目以降が $10^{-8}$ 前後になります。デフォルトのしきい値は $\sigma_{\max} \cdot 20 \cdot \varepsilon \approx 4 \times 10^{-14}$ とノイズ水準 $10^{-8}$ より小さいため、デフォルト判定は20(フルランク)を返します。一方 tol=1e-5 を指定すれば期待どおり5が返ります。ノイズの大きさが既知なら tol を自分で設定すべき、というのが実務上の重要な教訓です。デフォルトはあくまで「丸め誤差だけが誤差源」という想定の値にすぎません。

特異値という物差しを手に入れると、ランクは「潰れているか否か」の2値判定から、「どのくらい潰れかけているか」の連続的な評価へ拡張できます。その先にあるのが、ランクを意図的に下げて情報を圧縮する低ランク近似です。

低ランク近似への橋渡し:SVDと画像圧縮

行ランク=列ランクの証明で見たとおり、ランク $r$ の $m \times n$ 行列は $(m+n)r$ 個の数で表現できます。ならば逆に、フルランクの行列を「ほぼ等しいランク $k$ の行列」で置き換えれば、データを圧縮できるはずです。

SVDを使うと、この「最良のランク $k$ 近似」が具体的に作れます。特異値を大きい順に $k$ 個だけ残した

$$ A_k = \sum_{i=1}^{k} \sigma_i \mathbf{u}_i \mathbf{v}_i^{\top} $$

が、フロベニウスノルムの意味で $A$ に最も近いランク $k$ 行列になることが知られています(エッカート=ヤングの定理)。特異値は「その方向の情報の重要度」なので、重要度の高い方向から順に $k$ 個採用する、という自然な戦略が実際に最適なのです。

画像(輝度値の行列)で試してみましょう。

import numpy as np
import matplotlib.pyplot as plt

# 滑らかな構造を持つ128x128の合成画像を作る
n = 128
yy, xx = np.mgrid[0:n, 0:n] / n
img = (np.sin(6 * np.pi * xx) * np.cos(4 * np.pi * yy)
       + 2 * np.exp(-((xx - 0.3)**2 + (yy - 0.6)**2) / 0.02)
       + 1.5 * np.exp(-((xx - 0.75)**2 + (yy - 0.25)**2) / 0.05)
       + xx * yy)

U, s, Vt = np.linalg.svd(img)

fig, axes = plt.subplots(1, 4, figsize=(12, 3.4))
for ax, k in zip(axes, [1, 5, 20, n]):
    Ak = U[:, :k] @ np.diag(s[:k]) @ Vt[:k]   # ランクk近似
    ratio = k * (2 * n + 1) / n**2 * 100      # 保存に必要なデータ量の割合
    err = np.linalg.norm(img - Ak) / np.linalg.norm(img) * 100
    ttl = "元画像(ランク128)" if k == n else f"ランク{k}(データ量{ratio:.0f}% 誤差{err:.1f}%)"
    ax.imshow(Ak, cmap="viridis")
    ax.set_title(ttl, fontsize=10)
    ax.axis("off")
plt.tight_layout()
plt.show()

SVDによる低ランク近似で画像が再現される様子(ランク1・5・20・元画像)

ランク1ではぼんやりした縦横の濃淡しか表現できませんが、ランク5で大域的な模様が現れ、ランク20では元画像とほとんど見分けがつきません。ランク20の保存に必要なデータ量は元の約31%、相対誤差は数%以下です。自然界のデータの多くは「実質的に低ランク」であり、上位の特異値に情報が集中している——この性質こそ、主成分分析・レコメンドシステムの行列分解・大規模言語モデルのLoRAファインチューニングなど、現代のデータ科学で低ランク構造が酷使される理由です。

ここまでで、ランクという1つの概念が、連立方程式の解の判定から情報圧縮までを貫いて支えていることが見えたはずです。最後に全体を整理します。

まとめ

本記事では、行列の階数(ランク)について解説しました。

  • ランク = 線形変換後に生き残る次元の数 = 線形独立な行・列の最大本数 = 列空間(行空間)の次元。行ランクと列ランクは常に一致する
  • 求め方は行基本変形で階段形にして非ゼロ行を数える。行基本変形はランクを変えないことが根拠
  • 連立方程式 $A\mathbf{x}=\mathbf{b}$ は $\operatorname{rank}(A) = \operatorname{rank}([A|\mathbf{b}])$ のときに限り解を持ち、$\operatorname{rank}(A)=n$ なら一意、$r
  • 次元定理 $\operatorname{rank}(A) + \dim N(A) = n$:入力の次元は「生き残る分」と「潰される分」に過不足なく分配される
  • 正方行列では フルランク $\Leftrightarrow$ $\det A \neq 0$ $\Leftrightarrow$ 逆行列が存在
  • 現実のデータでは特異値のしきい値処理による数値ランクを使う。np.linalg.matrix_rank のデフォルトは丸め誤差想定なので、ノイズがあるデータでは tol を明示する
  • 特異値を上位 $k$ 個だけ残す低ランク近似は、最適な情報圧縮を与える(エッカート=ヤングの定理)

ランクは、固有値・特異値・射影といった線形代数の中核概念をつなぐハブです。次のステップとして、以下の記事に進むと理解がさらに立体的になります。