ラベル 行列 の投稿を表示しています。 すべての投稿を表示
ラベル 行列 の投稿を表示しています。 すべての投稿を表示

2012/09/01

文系のための「多次元データの要約」(1)

今回は、分散と共分散を楽して「行列」を使って計算するという話。

まずは、復習から。分散の計算は、以下の式で表すことができた。
本来は、二乗の形で表すが、共分散の式との比較のため、このように表す。



一方、共分散の計算は、以下のように表した。
共分散の場合は、二つの変数間のバラツキを表すので、
 と  の二つの変数が使われている。



さて、ここからが今回の話の重要なポイント。
今回は、ちょっとした、行列の掛け算の魔法を垣間見ることになる。

まずは、 」分散の計算から考えてみる。
以下は、 」偏差であり、 」という記号で表した。
「〜」の記号は、チルダと呼ぶのだった。



ここで、 というベクトルの計算を考えてみる。これを展開するとどのようになるか?
tの記号は、転置(transpose)を意味したのだから、


このようになる。これは、どのような計算だったか?
忘れた人は、文系のための内積(1)を参照。

確か、「横✕縦+横✕縦+横✕縦・・・となるから・・・。」

おぉ、なるほど。二乗したのを足していく訳か。
あるベクトルの転置と元のベクトルの掛け算は「二乗和」になるのだった。

したがって、以下のようになる。



うん?これは、確か分散の式のΣの内側と同じ計算となっている。
何が言いたいかと言うと、分散の計算をベクトルで表すと、以下のようになる。



 の分散は、見事にベクトルの式で表すことができる。
確か、共分散のΣの中身は、添字が異なるだけで、分散と同じだった。
つまり、掛ける側のベクトルを とすると、



となり、したがって、



という計算になる。素晴らしい。分散と同様に見事に計算できる
分散と同様に、ベクトルの式で表すと、次のようになる。



ここまでが理解できれば大丈夫。ここまでは、ベクトルの掛け算であったが、
次のような行列を考えてみるとどうなるか?



ちょっと、難しいかもしれないが、落ち着いて考えれば大丈夫。
頑張れる人は、手計算で。自信が無い人は、行列の計算の話を参考に。
頑張れない人は、あとでRを使って練習。

計算の順番と解となる行列での位置は次のようになる。
  • 1行目の横ベクトル×1列目の縦ベクトル(  ) ⇒  Answer[1, 1]
  • 1行目の横ベクトル×2列目の縦ベクトル(  ) ⇒  Answer[1, 2]
  • 1行目の横ベクトル×3列目の縦ベクトル(  ) ⇒  Answer[1, 3]
  • 2行目の横ベクトル×1列目の縦ベクトル(  ) ⇒  Answer[2, 1]
  • 2行目の横ベクトル×2列目の縦ベクトル(  ) ⇒  Answer[2, 2]
  • 2行目の横ベクトル×3列目の縦ベクトル(  ) ⇒  Answer[2, 3]
  • 3行目の横ベクトル×1列目の縦ベクトル(  ) ⇒  Answer[3, 1]
  • 3行目の横ベクトル×2列目の縦ベクトル(  ) ⇒  Answer[3, 2]
  • 3行目の横ベクトル×3列目の縦ベクトル(  ) ⇒  Answer[3, 3]
つまり、以下のように書き換えることが可能。



ここで、注意して見てもらいたいのが、対角成分に何が入っているか?ということ。
自分同士の共分散ということは、何を意味するのだったか?答えは、分散

もうひとつのポイントは、二つの変数の共分散の計算は、
順番を変えても答えは同じ(スカラーでは、A×B=B×A)なので、
対角成分を挟んで上側と下側が同じになる、ということも重要。

したがって、この行列の計算を通して計算された結果は、
対角成分に分散が並び、それ以外に共分散が入った対象行列である。

これを、「分散共分散行列」と呼ぶ。

さらに、元の行列が標準化されていた場合、すなわち、
平均が「0」で分散が「1」となるように基準化されていた場合には、
対角成分が全て「1」で、それ以外の成分が相関係数となる

例えば、先ほどの行列 を標準化した行列を Z としたとき、



という関係が成り立つ。これを、「相関係数行列」と呼ぶ。

分散共分散行列相関係数行列は、データを要約した指標として重要であると同時に、
この行列を用いることで、主成分分析の計算が容易になる。この話は、いずれ。

では、今度は実際のデータを用いて計算の練習をしてみる。
サンプルデータは、分散標準偏差の説明で用いたものを再び使う。

# Windows と Linux の人は次のコマンド
X <- read.table("clipboard", sep=",", header=TRUE)

# Mac の人は次のコマンド
X <- read.table(pipe("pbpaste") , sep=",", header=TRUE)

以下が、そのデータ。前回のものを再掲しただけ。
データの説明に関しては、平均の話を参照。

Oroshi_Kg, Taka, Naka, Yasu
Tai, 1336, 3150, 1217, 53
Chinu, 226, 630, 513, 105
Sawara, 212, 1575, 1259, 840
Yazu, 4834, 840, 315, 179
Suzuki, 618, 1575, 1146, 525
Akou, 21, 4725, 3129, 1575
Kochi, 28, 2100, 874, 210
Okoze, 28, 5250, 2635, 210
Ainame, 29, 3150, 621, 315
Hage, 1205, 1890, 383, 210
Konoshiro, 21, 2100, 1100, 105
Sayori, 12, 5250, 3916, 1260
Anago, 1637, 2625, 1721, 630
Mebaru, 330, 4200, 1680, 315
Tachiuo, 1211, 2310, 930, 105
Hamo, 1622, 3938, 592, 53
Karei, 41, 6300, 3178, 525
Hirame, 540, 2100, 1496, 210
Aji, 5149, 3150, 789, 210
Saba, 5413, 3675, 625, 53
Ika, 2414, 2888, 1083, 105
Tako, 1844, 1890, 1180, 525
Ebi, 560, 7350, 1420, 525
KurumaEbi, 222, 8925, 6508, 2625
Koiwashi, 1316, 1155, 617, 328
ObaIwashi, 2716, 499, 267, 175
Mentai, 678, 1155, 859, 394
Hamachi, 4772, 998, 632, 105
Isaki, 268, 2625, 1465, 840

まずは、行列 と同じサイズで、平均が並んでいる行列が必要だから、

# ステップ1:データの総数(n)を求める。
n <- nrow(X)
# ステップ2:卸売数量の平均を求める。転置が必要。
m <- t(colMeans(X))
# ステップ3:行列の引き算ができるように、平均値を総数個複製する。
M <- matrix(rep(m, each=n), nrow=n, ncol=4)
# ステップ4:元の行列から、平均値が複製された行列Mを引き算する。
tilde_X <- as.matrix(X-M)

最終的に、「tilde_X」という変数に偏差行列が入った。
ここで、分散共分散の式をそのまま当てはめると、

(t(tilde_X) %*% tilde_X)/(n-1)

となり、実行結果は以下のようになる。

> (t(tilde_X) %*% tilde_X)/(n-1)
           Oroshi_Kg       Taka      Naka      Yasu
Oroshi_Kg  2814792.6 -1026368.1 -920404.3 -335784.2
Taka      -1026368.1  4210888.7 2159783.0  685439.7
Naka       -920404.3  2159783.0 1752709.8  637497.8
Yasu       -335784.2   685439.7  637497.8  306021.7

疑い深い人は、分散共分散の話の結果と照合してみよう。
間違いなく、対角成分には分散が並び、それ以外には共分散が入っている。

さて、今度は、元のデータを標準化して計算をしてみる。

# 標準化した行列を作る
Z <- scale(X)

# 共分散の計算。平均は0なので偏差行列は不要
(t(Z) %*% Z)/(n-1)

実行結果は以下の通り。

> cov(Z)
           Oroshi_Kg       Taka       Naka       Yasu
Oroshi_Kg  1.0000000 -0.2981213 -0.4143816 -0.3617937
Taka      -0.2981213  1.0000000  0.7950020  0.6038183
Naka      -0.4143816  0.7950020  1.0000000  0.8704575
Yasu      -0.3617937  0.6038183  0.8704575  1.0000000

対角成分には「1」が並んでいて、それ以外の所は相関係数が入っている。
このようにして、相関係数行列を計算することができる。

ちなみに、前回、登場したcov()関数cor()関数は、
両方とも行列に対応しているので、共分散行列相関係数行列を出せる。

cov(X)    # 分散共分散行列を直接計算する
cor(X)    # 相関係数行列を直接計算する

以下は、実行結果。

> cov(X)    # 分散共分散行列を直接計算する
           Oroshi_Kg       Taka      Naka      Yasu
Oroshi_Kg  2814792.6 -1026368.1 -920404.3 -335784.2
Taka      -1026368.1  4210888.7 2159783.0  685439.7
Naka       -920404.3  2159783.0 1752709.8  637497.8
Yasu       -335784.2   685439.7  637497.8  306021.7

> cor(X)    # 相関係数行列を直接計算する
           Oroshi_Kg       Taka       Naka       Yasu
Oroshi_Kg  1.0000000 -0.2981213 -0.4143816 -0.3617937
Taka      -0.2981213  1.0000000  0.7950020  0.6038183
Naka      -0.4143816  0.7950020  1.0000000  0.8704575
Yasu      -0.3617937  0.6038183  0.8704575  1.0000000

手計算の場合には、結局、展開して計算しないといけないので、
手間は同じであるが、Rのように行列の計算ができるソフトウェアを使えば、
分散共分散相関係数を一度に計算することができ、便利なのである。

2012/08/20

文系のための「データの観察」(2)

データの「真ん中」とは何か?その疑問について再び考える。
平均」というのは、確かに「真ん中」のようである。納得できる。
しかし、本当に「平均」だけで良いのか?少々疑問が残る。

どういうことであるか?日本人の「職種別平均収入」で考えてみる。
今回は、「前フリ」無しで、最初から R を立ち上げる。

そろそろ、データの読み込み方は大丈夫だろう。説明を省く。
自信の無い人は、これまでの投稿を確認。やり方は、書いてある。

まずは、一つ目のデータを準備する。
上から順に、薬剤師、精錬工、技術士、機械工、自動車組立工、
製紙工、電気工、看護師、営業用バス運転者、社会保険労務士、
と並んでいて、その横に各業種の平均収入が入っている。
参考データはあるが、色々と変更を加えているので、ほぼ架空のデータ
給料の単位は、「万円」となっている。そのようなデータを用意した。
なお、このデータは、後の操作がしやすいように、収入順で並んでいる

salary
pharmacist, 496.6
refining engineer, 494.3
professional engineer, 489
machinary engineer, 487.8
auto assemblyman, 477.6
paper making engineer, 471.5
electronic engineer, 465.9
clinical nurse, 465.2
bus driver, 450.1
specialist in social insurance, 446.8

このデータを「X1」という変数に格納する。

# Windows  と Linux の人は以下のコマンド
X1 <- read.table("clipboard", sep=",", header=TRUE)

# Mac の人は以下のコマンド
X1 <- read.table(pipe("pbpaste"), sep=",", header=TRUE)

では、実際にこのデータを使って分析を行なってみる。
平均収入はどのようになっているのか?以下が出力結果。

> mean(X1$salary)
[1] 474.48

なるほど、納得できる。これらの職種間の平均収入は、474.48万円である。
元のデータを観察してみると、なんとなく、納得のいく数値である。

では、次に別のデータを用意してみる。
今度は、先のデータに加えて、パイロット、大学教授、医者、
の3つの職業を加えた。このデータを変数「X2」に入れる。
このデータも、収入順に並んでいるこのことは後に重要

salary
pilot, 1295.5
professor, 1133.2
doctor, 1101.2
pharmacist, 496.6
refining engineer, 494.3
professional engineer, 489
machine engineer, 487.8
auto assemblyman, 477.6
paper making engineer, 471.5
electronic engineer, 465.9
clinical nurse, 465.2
bus driver, 450.1
specialist in social insurance, 446.8

データを変数にセットするコマンドは以下の通り。

# Windows  と Linux の人は以下のコマンド
X2 <- read.table("clipboard", sep=",", header=TRUE)

# Mac の人は以下のコマンド
X2 <- read.table(pipe("pbpaste"), sep=",", header=TRUE)

X1と同様に、平均を出してみる。以下は、出力結果。

> mean(X2$salary)
[1] 636.5154

うん?636.515万円?この結果を見て「違和感」を感じる。3つ加えただけ。
先程に比べて、値が大きすぎる。これは、本当に全体の「真ん中」と言えるか?
追加した3つの職種によって、平均は一気に引き上げられた。ここで疑問が生まれる。
これらは、むしろ、「外れ値」として考えた方が良いのでは無いか?と。

何か、新しい政策を考える際に、安易に収入の平均を用いると、
トンデモナイことが起きる。実態に合わない政策が決定されるかもしれない。
吟味せずに、数値データを扱うことは、極めて危険なことである。

などと、問題点を指摘していても仕方ない。別の方法が必要である。
どうするべきか?

そこで登場するのが、2つ目の「真ん中」の概念。
平均」ではなく、データの「真ん中」番目を見てはどうか?
なるほど。確かに、これも「真ん中」である。

では、最初にX2の対象数を数えてみる。Rを使って。
nrow()関数を覚えているだろうか?

> nrow(X2)
[1] 13

したがって、このデータの場合は、7番目が「真ん中」番目である。
今回は総数が奇数なので、上から数えても、下から数えても「7番目」である。
試しに、7番目のデータを見てみる。予め収入順で並んでいるので楽
7行目を指定するので、以下のような結果が出る。

> X2[7,]
[1] 487.8

通常は、下から数えることになっている。これを「中央値」と呼ぶ。
R では、中央値を出す関数を持っている。median()関数である。
この関数は、値が並んでいなくても使える

> median(X2$salary)
[1] 487.8

なるほど。この結果を見てみると、平均よりも中央値の方が実態に合っている。
そのように思える。では、X1の場合と比較してみる。

> median(X1$salary)
[1] 474.55
> median(X2$salary)
[1] 487.8

若干、値が高くなっているが、平均よりも安定している。
データの「真ん中」を決める際に、安定感が無い指標は良いとは言えない。
したがって、中央値の方が、より適切にデータの「真ん中」を示していると言える。

ただし、データの総数が非常に大きく、
また、データが真ん中に向かって「綺麗な釣鐘状」に存在する場合、
平均値と中央値は近づく。そのような場合には、平均でも良いということになる。

ところで、気づいた人も居るハズ。X1のデータの総数は、偶数であった

奇数の場合は、ちょうど「真ん中」というのがあって決めやすいが、
偶数の場合は、「真ん中」が2つあって簡単に決めることができない。


実は、中央値というのは、奇数(odd)偶数(even)で取り方が異なる。
どうするべきか?議論が分かれるところである。


上を採用する方法、下を採用する方法も考え得る。
あるいは、上下2つの値の平均を採用するという方法もある。

どの方法が正しいかを述べることは困難であるが、
やはり、「真ん中」という意味では、平均を取る方法が適切に思える。
なお、R の median()関数 も偶数の場合には平均を取っている。

基本的な説明は以上であるが、やはり、数理的なことも理解しておいた方が良い。
もう少し、詳しく、「中央値」について考えてみる。



数式に慣れていない人は卒倒するかもしれない。落ち着きが必要。

ここで、Qという変数が登場する。これは、Quantile (分位数)の頭文字。
分位数というのは、あるデータをある数で等分すること

なるほど、「中央値」というのは、全体を2つに等分するので、
二分位数」ということか。もっとも、そんな言い方はしないが。
とにかく、そのように考えると、Qの「添字」である「1/2」の意味が解る。

さて、イコールを挟んで右側、つまり、右舷を見てみる。厄介に見えるかもしれない。
二段に分かれている。上には「if n is odd」、下には「if n is even」と書いてある。
なるほど、上の方は奇数の場合で、下の方は偶数の場合であるか。

大体、分かってきた。ここで、ちょっとした疑問がある。
何故、「x」ではなく、「x'」となっているのか?疑問に思わない人もいるかも。

そもそも、元のデータの変数が「x」だったして、
元のデータ「x」が今回のように、昇順に並んでいるとは限らない
そのような場合には、必ず、並び替え(ソーティング)が必要となる。
「x'」というのは、要するに、元のデータを並び替えただけのもの

さて、後は簡単である。添字は、データの「何番目」であるかを表す。
したがって、次のことが言える。

  • 奇数の場合には、「総数nに1を足して2で割った数」番目が「中央値」となる。
  • 偶数の場合には、「総数を2で割った」番目と、「それより一つ上」番目を足して、さらに、その合計を「2で割った値」が「中央値」となる。

解りにくいかもしれない。X2の場合は、総数が13であった(n=13)。
つまり、奇数。したがって、(13+1) ÷ 2 = 7番目の値が中央値となる。

では、X1の場合はどのようになるのか。確か、総数は10であった(n=10)。
今度は、偶数。だから、二段目の式を当てはめることになる。
10÷2番目と(10÷2)+1番目、つまり、5番目と6番目の値を足して割った数が中央値
この場合は、少々厄介であるか。Rで確認してみる。以下、実行結果。

> X1[5,]
[1] 477.6
> X1[6,]
[1] 471.5
> (X1[5,]+X1[6,])/2
[1] 474.55
> median(X1$salary)
[1] 474.55

確かに、正しく計算されていて、上に提示した式とも合致している。
R を用いると、数式上の表現と、実際の処理を比較できるので良い。

さてさて、以上のことで、データの「真ん中」ということが整理できた。
平均と中央値という2つの決め方がデータの「真ん中」なのである。

本当にそれで良いのか?まだ、「真ん中」の決め方があるかもしれない。
では、どのような方法があるか?確か、外れ値に影響されないことが重要だった
例えば、最も頻繁に登場する値を「真ん中」として考えられないだろうか?
ふむふむ。これは検討の余地がありそうである。この話はいずれ。

2012/08/18

文系のための「内積」(2)

さて、行列の「掛け算」の基本的な話は済んだ。
では、「掛け算」を使うとどのようなことができるのか、
Rを使って、色々と見ていくことにする。

ここからは、多少、複雑になってくる。
自信の無い人は、Rコンソールを立ち上げて、
実際に確認しながら読んだ方が良い。読むだけだと、逆に混乱する。

今回は、図形の変換という点から見てみる。
Rコンソールを立ち上げ、以下のデータを準備する。
最初に、以下のコマンドを貼り付ける。実行はまだ

# 「足し算」の例で用いたデータの読み込み
# Windows & Linux の人は以下のコマンド
X <- as.matrix(read.table("clipboard", sep = ","))

# Mac の人は以下のコマンド
X <- as.matrix(read.table(pipe("pbpaste"), sep = ","))

以下をコピーして、貼りつけた上記のコマンドを実行
最終列に、「1」が並んでいるのは、計算の都合上のもの。
数学の魔法をかけるための準備。魔法にも準備が必要。

x,y,dummy
P1,0,0,1
P2,40,40,1
P3,40,0,1
P4,0,0,1

同様に、以下のコマンドをコピーして貼り付け。実行はまだ

T <- as.matrix(read.table("clipboard", sep = ","))

以下のデータをコピーしてから上記コマンドを実行

1,0,10
0,1,15
0,0,1

以前は、「足し算」を使って、図形の並行移動を行った。
これは、「掛け算」を使ってもできる。どういうことか?

二回目に貼り付けたデータ「Tが、変換行列になっている。
以下の行列の中で、TxとTy という変数が確認できる。
Tx の変数がx軸の移動量であり、Ty がy軸方向の移動量である。
本当にそのように都合良い行列があるのか?ふむ、ある。



手計算の場合には、少々、厄介に見えるかもしれないが、
とにかく、以下のようになる。


行列の「掛け算」では、掛けられる方を横に、
掛ける方を縦に掛け算し、足し合わせるのだった。
したがって、途中の計算は、以下のようになり、



したがって、


計算ミスをしそうだ。実際、計算ミスはよくする。
数学が苦手な人間の多くは、計算ミスによるコンプレックス
心配無用。手計算でできる事の方が少ない
だから、思い切って計算機の力を借りることにする。

R上では、以下のように計算する。

t(T %*% t(X))

そして、Xには図形データの行列が、Aには変換行列が入っている。
t()関数というのは、転置(Transpose)のことだった。

注意する点は、「掛け算」の仕方。
計算機では、一般的にアスタリスク(「*」)が「掛け算の記号」であるが、
Rの「行列の掛け算」では「%*%」とする。これが、行列の掛け算の記号である。

以上を理解した上で、このコマンドを観察してみると、
なるほど、上記の数式と同じことは誰でも理解できる。
実行すると、以下のようになる。

> t(T %*% t(X))
   [,1] [,2] [,3]
P1   10   15    1
P2   50   55    1
P3   50   15    1
P4   10   15    1

一応、重ねあわせを行なってみる。方法は、以下の通り。
plot(X, type="b", col = "blue", xlim = c(0,60), ylim = c(0, 60))
par(new=TRUE)
plot(t(T%*%t(X)), type="b",col = "red", xlim = c(0,60), ylim = c(0, 60))

行列の「掛け算」を使うと、大きさを変えることもできる。
これを、「スケーリング」と呼ぶ。これをやってみる。
平行移動と同様に、次のような変換行列を用意する。
Sx というのが、xの値のスケールなり、
Sy というのが、yの値のスケールとなる。
平行移動と同様に、この変換行列で都合よく変換できる。



では、さっそくやってみる。まずは、以下の命令後をコピーして貼り付け。

# Windows と Linux の人は以下のコマンド。
S <- as.matrix(read.table("clipboard", sep = ","))

# Mac の人は、以下のコマンド
S <- as.matrix(read.table(pipe("pbpaste"), sep = ","))

以下のデータをコピーしてから上記コマンドを実行
この例では、x軸とy軸の両方に二倍比率を変えても構わない

2,0,0
0,2,0
0,0,1

ここまでの復習も兼ねて、手計算にも挑戦すると良い。
回答は、Rの計算結果が示してくれる。



Rでの実行結果は以下の通り。以下の通りになっているかを確認。

> t(S%*%t(X))
   [,1] [,2] [,3]
P1    0    0    1
P2   80   80    1
P3   80    0    1
P4    0    0    1

さらに、プロットして、確認してみる。
plot(X, type="b", col = "blue", xlim = c(0,90), ylim = c(0, 90))
par(new=TRUE)
plot(t(S%*%t(X)), type="b",col = "red", xlim = c(0,90), ylim = c(0, 90))

最後に、「回転」もやってみよう。これも「掛け算」でできる。
ここで準備する変換行列は次の通り。



ここでは、三角関数が出てくる。ここでは、詳しいことは書かない。
とは言え、全く知らない人も居るかもしれない。基本だけ。

角度には、二種類が存在する。
1つ目は、いわゆる「度(Degree)」で、
2つ目は、「弧度(Radian)」というもの。
この2つくらいは知っておかなくてはならない。

弧度」というのは、聞きなれないかもしれないが、
要するに、半径の長さと弧の長さが等しくなる角度を1とした単位である。
数的な処理では、「」よりも「弧度」を使うことが良くある。

とにかく、次の式は記憶。記憶できなければ、いつでも参照できるように。
この変換式を使って、角度を定義する。



したがって、30度の変化を行う場合は、

> (2*pi*30)/360
[1] 0.5235988

とりあえず、コピーアンドペーストで、変換行列を作成する。
まず、「d」という変数に、「30度」を弧度に変換して格納し、
さらに、行列の元となるベクトルを作成する。

d <- (2*pi*30)/360
v <- c(cos(d),sin(d),0,-sin(d),cos(d),0,0,0,1)

そして、作成したベクトルから変換行列を作る。

R <- matrix(v, nrow=3, ncol=3)

結果として、次のような行列ができる。

> R
          [,1]       [,2] [,3]
[1,] 0.8660254 -0.5000000    0
[2,] 0.5000000  0.8660254    0
[3,] 0.0000000  0.0000000    1

これから行う変換は、次の通りである。小数点四位以下は省いてある。
小数点を長々と書く意味は無い。計算機の都合を信じてはいけない。
まぁ、良いのだが。とにかく、以下のようになる。



Rでやってみる。実行結果は以下の通り。

> t(R%*%t(X))
       [,1]     [,2] [,3]
P1  0.00000  0.00000    1
P2 14.64102 54.64102    1
P3 34.64102 20.00000    1
P4  0.00000  0.00000    1

ふむ。なるほど!数値だけ見ても良く解らない。正しいのか?
ということで、可視化してみる。

plot(t(R%*%t(X)), type="b",col = "red", xlim = c(0,60), ylim = c(0, 60))
par(new=TRUE)
plot(X, type="b", col = "blue", xlim = c(0,60), ylim = c(0, 60))

実は、これらの変換は、一般的には「アフィン変換」と呼ばれるもの。
上記の変換以外にも、「せん断」という変換もできるが、今回は省く。
ちなみに、この変換では「台形」になる変換できないので注意が必要。

この変換は、画像処理やGISにおける空間データの変換など、
様々なシーンで利用されているので、覚えておくと応用が効く。
もちろん、行列を使わずに計算することもできるが、計算ミスの危険性は増大する。
行列で計算できるのであれば、行列で計算した方が楽なのである。

2012/08/12

文系のための「内積」(1)

今回は、多少の我慢が必要かもしれない。話が少し複雑。
とは言え、ある意味、最も重要な話。先に話が進まない。

さて、まずは復習。

「行列」の「足し算」と「引き算」は、それほど難しくなかった。
要するに、同じサイズの2つの行列が存在したとして、
同じ場所にある成分同士で「足し算」するのであった。



このような、2つの行列が存在したとき、
行数」は、 であり、「列数」は、 となる。
そして、「行列X」における「不特定番目」の「成分」と、
同様に、「行列Y」における「不特定番目」の「成分」の「足し算」は、



である。つまり、同じ場所同士の成分を足しているだけ。
引き算」も同様。同じ場所同士の成分を引けば良い。
ここまでは、流石に理解できているはず。

さて、ここからが問題である。基礎編では最難関の山場
ここさえ、クリアできれば、後はかなり楽になる。

では、行列の「掛け算」というのをやってみる。
とりあえず、「3行1列」の行列と、「1行3列」の行列を用意する。

うん?、1行?? 1列?? となった人、正解。
これは、どういった、状況であるか?
イヤヨ(184)クロウハ(968)」で考える。

 

横一列の行列」とは、「横ベクトル」そのものであり、



縦一列の行列」は、「縦ベクトル」である。確かに、そのようであった。

まずは、ベクトルの掛け算から始めることにする。

さて、なぜ「行列」の「掛け算」が難しいのか?
その理由は、「足し算」と「引き算」のように、
同じ場所の成分同士を計算するわけではないからである。

掛けられる行列は「横方向」に、掛ける行列は「縦方向」に「掛けて」、
結果を「足す。という操作を必要とする。

先程の「横ベクトル」と「縦ベクトル」の計算をやってみる。



つまり、このようになる。横ベクトルでは、左から右に向かって進みながら、
縦ベクトルでは、上から下に向かって足し算をする。

折角なので、次のような例もやってみる。
イヤヨ(184)イヤヨ(184)もナントカの内」。



気づいた人もいるかもしれない。ベクトルの「掛け算」を応用すると、
同じベクトルの、転置の掛け算は、二乗して足し合わせることができる
これを「二乗和」と呼び、行列を用いた様々な演算の中で頻繁に登場する。

手計算では、有難味というのは湧かないが、
コンピュータで計算するときに重宝する。これが重要。

ところで、この例では、同じベクトルを「」と「」にしてある。
これを「転置(transpose)」と呼び、「ベクトル」と「行列」では頻繁に登場する。
また、このような計算を慣例的に次のように表す。



ベクトルの計算で、この記号が出てきたら、
つまりは、「二乗和」の計算をしている。

「横」と「縦」に計算する。なるほど、大体は理解できた。それほど難しくはない?
注意するべき点が2つある。ここからが、混乱の原因。

まず一つ目。掛けられる行列の「行数」と掛ける行列の「列数」の一致。
したがって、次のような、計算はできない。「イヤ(18)!ハシゴ(845)酒は



上から順番に計算していくと、「5」を掛ける数が無い
したがって、このような場合には計算ができない。
この約束事は、ベクトルだけでなく、「行列」にも当てはまる

そして、二つ目。掛ける順番は変えてはいけない、という原則。
スカラーでは、気にする必要は無かった。というのは、



であった。しかし、「ベクトル」や「行列」の場合は、そうは行かない。



このように、結果が「行列」となってしまい、計算結果が異なる。
したがって、「行列」においては、次のことが言える。



イヤヨ(184)クロウハ(968)」と「クロウハ(968)イヤヨ(184)
両者は、似て非なるものである。

したがって、次の場合にも注意が必要である。



両方とも、統計や数学の教科書に頻繁に登場するが、
両者は、全く異なっているのであって、混同してはいけない。念の為に、確認しておく。
  •  の場合

  •  の場合


以上が、行列の「掛け算」の導入の話。次からは、実際に「R」での計算を実践してみる。