Rで線形代数:線形写像

Rで 線形代数:線形写像 を試みます。

サンプルデータ(点の集まり)を行列と見なし、その行列にランクの異なる3つの行列(ランク3, ランク2, ランク1)を乗じることで、線形写像を行います。

写像後の点の集まりがどのように変化するか、そして 乗じる行列のランクが、写像された後の空間の次元を決定づける ことを観察します。

Rコード

ステップ1: サンプルデータを準備

library(rgl)
knitr::knit_hooks$set(webgl = hook_webgl)
options(rgl.useNULL = TRUE)

seed <- 20250619
set.seed(seed)

n <- 500
x <- rnorm(n = n)
y <- rnorm(n = n)
z <- rnorm(n = n)

# サンプルデータを (n x 3) の行列としてまとめる
# 各行が1つの点(x, y, z)を表す
original_data <- cbind(x, y, z)

ステップ2: ランクの異なる変換行列を定義

# ランク3の行列 (例: 回転とスケーリング)
# 3つの列ベクトルが線形独立なので、空間を潰さない
A_rank3 <- matrix(c(
  1, 0.5, 0.2,
  0, 2, 0.1,
  0, 0, 1.5
), nrow = 3, byrow = TRUE)

# ランク2の行列
# 3列目が1列目と2列目の線形結合 (v3 = v1 + v2) になっている
# このため、写像後の空間はv1とv2が張る平面になる
A_rank2 <- matrix(c(
  1, 0, 1,
  0, 1, 1,
  2, 1, 3
), nrow = 3, byrow = TRUE)

# ランク1の行列
# 2列目が1列目の2倍、3列目が1列目の3倍になっている
# 全てのベクトルが1つの方向しか指さないため、写像後の空間は直線になる
A_rank1 <- matrix(c(
  1, 2, 3,
  2, 4, 6,
  3, 6, 9
), nrow = 3, byrow = TRUE)

# 各行列のランクを確認
print(paste("A_rank3のランク:", qr(A_rank3)$rank))
print(paste("A_rank2のランク:", qr(A_rank2)$rank))
print(paste("A_rank1のランク:", qr(A_rank1)$rank))
[1] "A_rank3のランク: 3"
[1] "A_rank2のランク: 2"
[1] "A_rank1のランク: 1"

ステップ3: 線形写像を適用

# original_data (n x 3) と 行列 (3 x 3) の積を計算
transformed_rank3 <- original_data %*% A_rank3
transformed_rank2 <- original_data %*% A_rank2
transformed_rank1 <- original_data %*% A_rank1

ステップ4: 結果を3Dプロットで可視化

  • 以下の3次元プロットはマウスで回転、拡大、縮小できます。
radius <- 0.2
size <- 10
type <- "s"

1. 元のデータ

plot3d(original_data,
  col = "blue",
  main = "1. Original Data (3D)",
  radius = radius,
  type = type,
  size = size,
  xlab = "x",
  ylab = "y",
  zlab = "z"
)
axes3d()

2. ランク3の行列による変換後

plot3d(transformed_rank3,
  col = "green",
  main = "2. Transformed by Rank-3 Matrix (3D)",
  radius = radius,
  type = type,
  size = size,
  xlab = "x",
  ylab = "y",
  zlab = "z"
)
axes3d()

3. ランク2の行列による変換後

plot3d(transformed_rank2,
  col = "orange",
  main = "3. Transformed by Rank-2 Matrix (2D Plane)",
  radius = radius,
  type = type,
  size = size,
  xlab = "x",
  ylab = "y",
  zlab = "z"
)
axes3d()

4. ランク1の行列による変換後

plot3d(transformed_rank1,
  col = "red",
  main = "4. Transformed by Rank-1 Matrix (1D Line)",
  radius = radius,
  type = type,
  size = size,
  xlab = "x",
  ylab = "y",
  zlab = "z"
)
axes3d()

各プロットの見方

  1. Original Data (青):

    • 3次元空間に広がる球状の点群です。これが全ての変換の元になります。
  2. Transformed by Rank-3 Matrix (緑):

    • 元の球状の点群が、引き伸ばされたり傾いたりして「楕円体」のような形になっています。しかし、依然として3次元の体積を保っていることが重要です。これは、ランク3の行列が3次元空間を潰さずに別の3次元空間に写したことを意味します。
  3. Transformed by Rank-2 Matrix (オレンジ):

    • 一見すると広がって見えますが、プロットを回転させて真横から見てください。全ての点が一枚の平面に乗っていることがわかります。元の3次元の点群が、ぺしゃんこに潰されて2次元の平面に写像されたのです。これがランク2の行列の働きです。
  4. Transformed by Rank-1 Matrix (赤):

    • これも同様にプロットを回転させてみると、全ての点が一直線上に並んでいることがわかります。元の3次元の点群が、完全に潰されて1次元の直線に写像されたのです。これがランク1の行列の働きです。

以上です。