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のように行列の計算ができるソフトウェアを使えば、
分散共分散相関係数を一度に計算することができ、便利なのである。

10 件のコメント:

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

    の下の式は、シグマの下が"i=i"になってますが?


    \sigma^2=\frac{1}{n-1}\sum_{i=i}^{n}(\bar x - x_i)(\bar x - x_i)

    返信削除
  2. さらに同じ式で、"(\bar x - x_i"が2回あるのは正しいのでしょうか?また、この部分は"x_i - \bar x"が正しいのではないでしょうか?

    返信削除
    返信
    1. コメントありがとうございます。

      [bar x - x_i]が二回あるのはこれは正しいのです。
      直前の文章に書いてありますがここでは「2乗」しているのです。

      小学校の算数では「x(かける)」の記号を書いていましたが、
      ここでは、「x」の記号は省略しています。
      ちなみに、「x」のかわりに「・」を使うこともあります。

      私も詳しくは知らないのですが、
      このことに関しては、以下のようなサイトがありました。

      http://www004.upp.so-net.ne.jp/s_honma/symbolhistory.htm

      さて、2つ目の質問に関してですが、
      これも、一つ目の質問に関係することです。

      [bar x - x_1] と [x_i - bar x]はどちらでも同じことになるので、
      どちらでも良いことになります。

      例として、以下のようなベクトルを考えてみます。

      x = {1, 3, 5, 7}

      まず、これの平均「[bar x]」は以下のようになります。

      [bar x] = (1 + 3 + 5 + 7) / 4 = 16/4 = 4

      ここで、いきなり分散[sigma^2]を計算したいところですが、
      その前に基本的な事を一つ整理しておきたいと思います。

      そもそも、平均というのは、数を「平(たいら)に均(なら)す」ことです。
      したがって、平均と各値との差の合計というのは、別の見方をすると、
      それぞれの値の差が「全く無い」という言い方もできます。

      上記の場合、「4」が「4」つということなので、
      平均だけで元のデータを表すと、以下のようになります。

      (4 + 4 + 4 + 4) / 4 = 16 / 4 = 4

      この時、各値と平均との差(偏差)の合計は以下のようになります。

      (4-4) + (4-4) + (4-4) + (4-4) = 0

      当たり前の事ですが、当然、合計は「0」になります。
      では、元のベクトルの場合はどうなるのでしょうか?

      平均-元の値:(4-1) + (4-3) + (4-5) + (4-7) = (-3) + (-1) + (+1) + (+3) = 0
      元の値-平均:(1-4) + (3-4) + (5-4) + (7-4) = (+3) + (+1) + (-1) + (-3) = 0

      結局、お互いの値のプラスとマイナスが打ち消し合ってしまい、
      偏差の合計は常に「0」となってしまうのです。
      実は、偏差の合計が「0」がなる部分が「平均」となっているのです。

      これでは、バラツキの大きさが解らないないのです。
      これは困った...ということで、2乗してみると?

      平均-元の値:(4-1)^2 + (4-3)^2 + (4-5)^2 + (4-7)^2 = 9+ 1 + 1 + 9 = 20
      元の値-平均:(1-4)^2 + (3-4)^2 + (5-4)^2 + (7-4)^2 = 9 + 1 + 1+ 9 = 20

      少しだけ、小学校の掛け算のルールを思い出して欲しいのですが、
      掛け算には以下の様な性質がありました。

      (+) x (+) = (+)
      (-) x (-) = (+)

      2乗するということは、元の値同士を書けることなので、
      上記の何れかのルールが適用されることになるのですが、
      結局、マイナスであろうが、プラスであろうが、2乗するとプラスになります。

      したがって、平均と元の値との差を足しあわせた合計と、
      元の値から平均との差を足しあわせた合計は同じになります。

      これを一般的に「偏差」の「2乗(平方)」の「和」ということで
      「偏差平方和」あるいは単に「平方和」と呼びます。

      おな、「偏差は基準(データの真ん中)から元の値までの距離」と考えると、
      [bar x - x_i]と書いた方が、なんとなく、言葉の説明にあってるように思います。

      もちろん、「元の値から基準までの距離が偏差」と考えることもできるので、
      [x_i - bar x] と書くと、そのようなニュアンスで理解することもできます。
      計算結果は同じでも、書き方によって、説明の仕方も何となく変わります。

      削除
  3. 文系Aさんから上記のような質問があったので、
    誤解が少しでも軽減するように、
    最初の分散の式を少し書き換えました。

    返信削除
  4. そうでした。二乗でしたね。書き方が少し変わっただけで混乱してしまうとは、ちゃんと理解できていない証拠ですね。お恥ずかしい。ご説明ありがとうございます。

    ということは、"i=i"も正しいのですね。

    返信削除
    返信
    1. あっ...これは、ケアレスミスです。直すのを忘れていましたね。
      正しくは、{i=1} になります。

      削除
  5. 以下のAnswer[2,1]は正しくはAnswer[2,2]でしょうか?

    2行目の横ベクトル×2列目の縦ベクトル( ) ⇒ Answer[2, 1]

    返信削除
    返信
    1. そうですね。これもケアレスミスです。ご指摘の通りです。
      修正しておきました。

      削除
  6. 以下の部分は、実行結果のコマンドが見本と異なりますが、同じ事ができるという


    cov(Z)

    Z <- scale(X)
    (t(Z) %*% Z)/(n-1)
    と同じ結果を返す、ということでしょうか?

    qt.
    # 共分散の計算。平均は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
    unqt.

    返信削除
    返信
    1. これは、説明の仕方が悪かったかもしれません。
      ここでは、「分散共分散行列」と「相関係数行列」の比較が目的でした。
      両者は、非常に密接な関係があるのです。

      重要なポイントは、元の行列「X」というのがあって、
      これを「標準化(scale)」した行列が「Z」であるということ。
      標準化について「文系のための「二変数の関係」(1)」で説明しています。
      (http://cis-jp.blogspot.jp/2012/08/blog-post_22.html)

      要するに、平均が「0」で分散が「1」となるようにデータを整えることです。
      形式手には、それぞれの値について、その値から「平均」を引いて「標準偏差」で割ります。

      全ての値について、平均を引くということは、全体としては基準を「0」にシフトすることであり、
      さらに、シフトした値を標準偏差で基準化することで、標準偏差に対する割合に変換しているのです。
      当然、割合なので、全てを合計するとバラツキの割合は「100%」。つまり、分散は「1」となります。

      ちょっと見にくいですが、標準化の式は以下の通りです。
      以下では、行列Xにおける任意(i番目)の値「x_i」の標準化の場合です。
      なお、標準化した任意(同じくi番目)の値を「z_i」、平均を「μ」とします。

      z_i = x_i - μ / σ

      さてさて、少し、話が逸れましたが、以上を踏まえた上で、
      ご質問を頂いた内容に入りたいと思います。

      何が言いたいかと言うと、元の行列「X」の」「相関係数行列」である{cor(X)}と、
      「標準化」した行列「Z」の「分散共分散行列」である{cov(Z)}は等しくなります。
      つまり、以下のようになります。

      {cov(scale(X))} = {cov(Z)} = {cor(X)}

      結論を言うと、「元の行列」を「標準化」した行列の「分散共分散行列」は、
      「元の行列」から直接的に導出した「相関係数行列」と等しいことを示しています。
      大したことに見えないかもしれませんが、全ての値を1つずつ計算して相関係数を計算するよりも、
      このように、行列を使って計算すると計算が極めてシンプルになります。
      この辺りの恩恵は、色々とやっている内に少しずつ理解できると思います。

      文系分野の研究では安易に「相関係数」を用いている場合がありますが、
      「分散」と「共分散」の考え方をよく理解しておくことが最も重要なことなのです。

      削除