More Related Content
Similar to Rによるprincomp関数を使わない主成分分析 (20)
More from wada, kazumi (20)
Rによるprincomp関数を使わない主成分分析
- 1. 2012.12 作成
princomp 関数を使わない主成分分析
主成分分析の種類
A. 相関行列から算出するもの <= データを標準化する場合
B. 共分散行列から算出するもの <= データを標準化しない場合
主成分分析の流れ
① データを標準化 [A(相関行列出発)の場合のみ]
② 相関行列、または共分散行列の計算
※ データが標準化されていれば、共分散行列=相関行列となる。
③ 相関行列/共分散行列から固有ベクトルと固有値を算出
④ 大きい固有値に対応する固有ベクトルから、第一主成分、第二主成分・・・になる。
⑤ 固有値から寄与率を算出し、何番目の主成分まで採用するか決める。
⑥ 主成分負荷量及び主成分得点の計算
A. 標準化したデータと固有ベクトルとの内積
B. 主成分を標準化し、中心化したデータと内積
[デモ]R によるあやめデータの主成分分析
ステップ 1 : 前処理
まず R を起動し、組込のあやめのデータセットを呼び出す。[a]
データセット名の iris と入力すると、データの内容が表示される。[b]
このデータは、三つの異なる品種のあやめの花弁の寸法を測ったもので、5 変数 150 データ(各
品種 50 データずつ)、1~4 変数までが量的変数で、 5 変数は品種名。
第 データはリスト属性で、
データ番号・変数名つき。縦がデータ数、横が変数。
サンプルデータ(データ番号 1, 51, 101)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
51 7.0 3.2 4.7 1.4 versicolor
101 6.3 3.3 6.0 2.5 virginic
リスト属性のデータは、そのまま計算に使うのは不都合なので、行列(matrix)属性データに変
換し、さらに数量項目ではない第 5 変数を落とし、作業用の dat というデータを作る。[c]
通常データは scale 関数などを用いて標準化することが多いが[d]、今回は標準化しない例を取
り上げる。
- 2. data(iris) #[a]
iris #[b]
dat<- as.matrix(iris[,1:4]) #[c]
# dat<- scale(as.matrix(iris[,1:4])) #[d]
fg1 <- as.numeric(iris[,5]) # 品種別フラグ
pairs(dat, pch=21, bg=c("red", "green", "blue")[fg1]) # 散布図
あやめデータの散布図
2.0 3.0 4.0 0.5 1.5 2.5
7.5
6.5
Sepal.Length
5.5
4.5
4.0
Sepal.Width
3.0
2.0
7
6
5
Petal.Length
4
3
2
1
2.5
1.5
Petal.Width
0.5
4.5 5.5 6.5 7.5 1 2 3 4 5 6 7
- 3. ステップ 2 : 固有値計算
共分散行列を求め[e]、これから固有値・固有ベクトルを算出する。[f]
固有ベクトルが主成分(主成分得点の係数)で、固有値は主成分得点の分散にあたる。
データが 4 変数なので、共分散行列は四行四列。
4 つの固有値は大きい順に並んだ一つのベクトル(下の例では eg$value)
、固有ベクトルは
対応する固有値が大きい順に上から並んだ 4 行 4 列の行列が返される。
寄与率は、4 つの固有値の合計で各固有値を割った値になる。[g]
cv <- cov(dat) #[e]
eg1 <- eigen(cv, symmetric=TRUE) #[f]
eg1a <- eg1$value # eg1 から固有値を eg1a に取り出す
eg1v <- eg1$vectors # eg1 から固有ベクトルを eg1v に取り出す
ct1 <- eg1a / sum(eg1a) #[g]
上の例では、eigen 関数による固有値・固有ベクトルの計算結果を変数 eg1 に代入している
ので、eg1 とタイプすると結果が表示される。
$values が固有値、$vectors が固有ベクトル。それぞれ eg1$value, eg1$vector で個別にこれ
らの内容が参照できる。 1 主成分は、
第 eg1$vectors[1,]、
これに対応する固有値が eg1$values[1]、
寄与率 ct の計算結果を見れば、この第一主成分だけでデータ全体の 92%が説明できることが
わかる。
[結果出力のコンソール画面]
> eg1
$values
[1] 4.22824171 0.24267075 0.07820950 0.02383509
$vectors
[,1] [,2] [,3] [,4]
[1,] 0.36138659 0.65658877 0.58202985 0.3154872
[2,] -0.08452251 0.73016143 -0.59791083 -0.3197231
[3,] 0.85667061 -0.17337266 -0.07623608 -0.4798390
[4,] 0.35828920 -0.07548102 -0.54583143 0.7536574
> ct1
[1] 0.924618723 0.053066483 0.017102610 0.005212184
> eg1$vectors[1,]
[1] 0.3613866 0.6565888 0.5820299 0.3154872
> eg1
$values[1]
[1] 4.228242
主成分分析を行う目的が次元縮約(たくさんある変数の数を減らすこと)であれば、主成
分採用の目安は経験的に累積寄与率が 70~80%以上とされているので、このデータの場合は
第一主成分だけを採用すればよいことになる。
- 4. ステップ 3 : 主成分得点と主成分負荷量の計算
ステップ 2 で、固有値分解により、固有値 ega と固有ベクトル egv を算出した。次に、主成分
得点(データの各主成分に対する値)と、主成分負荷量(構造係数とも呼ばれ、主成分と各変
量の間の相関係数と一致する)を計算してみる。
主成分得点は、データポイントから各主成分に射影したときのデータの重心(=平均)から
の影の長さになる。[図 1 参照]
まず各データから平均値ベクトルを引き、データの中心を原点に持ってくる(中心化)
。[k]
データを標準化せず、共分散行列から出発した場合、主成分も標準化されていないので、固
有値の平方根(=各主成分の標準偏差)で割って標準化する。[l]
(※中心化と主成分の標準化は、最初にデータを標準化した場合は必要がない。
)
主成分得点(上の青いベクトル)は、標準化済主成分と中心化したデータの内積。[m]
主成分負荷量は、もとのデータと主成分得点との相関係数にあたる。
cdat<- t(t(dat) - colMeans(dat, 2)) # [k]
spca<- eg1v %*% diag(1/sqrt(eg1a)) # [l] 主成分を標準化
tok<- cdat %*% spca # [m] 主成分得点
dev.new()
plot(tok[,1:2], pch=21, bg=c("red", "green", "blue")[fg1])
# 第 1・2 主成分を x, y 軸としてプロット
xpca<- solve(spca) # 主成分の逆行列
xpca<- solve(spca) # 主成分の逆行列 =>もとの軸を示すものになる
arrows(0, 0, x1=xpca[,1], y1=xpca[,2], col="red")
# あまり見栄えがよくないが、主成分得点プロットに元の軸を矢印で表示してみた
2
1
tok[, 1:2][,2]
0
-1
-2
-3
図 1. 主成分と主成分得点 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5
tok[, 1:2][,1]
- 5. princomp 関数との比較
princomp 関数による結果と比較してみる。ccr=FALSE 指定で先と同じデータを標準化しな
い形での分析になる。結果は変わらないが、見栄えの良い biplot を出力することができる。
prc1 <- princomp(dat, cor=FALSE)
summary(prc1)
prc1$loadings # 因子負荷量表示
dev.new()
biplot(prc1)
[結果出力のコンソール画面]
> prc1 <- princomp(dat, cor=FALSE)
> summary(prc1)
Importance of components:
Comp.1 Comp.2 Comp.3 Comp.4
Standard deviation 2.0494032 0.49097143 0.27872586 0.153870700 主成分標準偏差
Proportion of Variance 0.9246187 0.05306648 0.01710261 0.005212184 寄与率
Cumulative Proportion 0.9246187 0.97768521 0.99478782 1.000000000 累積寄与率
> prc1$loadings 因子負荷量のはずだが表示されているのは固有ベクトル(未標準化)
Loadings:
Comp.1 Comp.2 Comp.3 Comp.4
Sepal.Length 0.361 -0.657 -0.582 0.315
Sepal.Width -0.730 0.598 -0.320
Petal.Length 0.857 0.173 -0.480
Petal.Width 0.358 0.546 0.754
Comp.1 Comp.2 Comp.3 Comp.4
SS loadings 1.00 1.00 1.00 1.00
Proportion Var 0.25 0.25 0.25 10.25
図 散布図
Cumulative Var 0.25 0.50 0.75 1.00
-20 -10 0 10 20
61
0.2
20
107
94
58
42
54
99 8160 114
120
90
82 91
0.1
10
14
9 63 122
70 69 115
95
143
102
39 85 135
93 88 84
56 147
80100 73
434 83 67 150
68
97
89
6596
46
13
48 109
31
30
2
326 127 133
74 112
79124129
139 104
134
35
10 6264128
Comp.2
7 25 71
72 92Petal.Width Petal.Length
0.0
105
101
0
12 98 117
138
36 24
50 55 148
149
116
23 827 75 137
40 86 77146
44 Sepal.Width 59111 141
113
Sepal.Length
41
38
18
29
1
5 76 144 119
52 78 125
57 145
28 103
140 108
21
32
2245 87 142 131
121
47
20 66 53 130 123
-0.1
-10
49
37 126 106
11 51 136
6 110
33
17
19
34
-20
-0.2
15 118
16 132
-0.2 -0.1 0.0 0.1 0.2
Comp.1
- 6. 結果を比較するかぎり、どうも princomp は主成分を標準していないと思われる。先の spca
は標準化した主成分で、これが上の因子負荷量と同じになるはずだが、上の$loadings で表示
されているのは eg1v、つまり生の固有ベクトルと同じもの。
標準偏差が 1 にならないはずなので、
このままこれを用いてスコア計算すれば、 以下は検証。
> eg1v
[,1] [,2] [,3] [,4]
[1,] 0.36138659 -0.65658877 -0.58202985 0.3154872
[2,] -0.08452251 -0.73016143 0.59791083 -0.3197231
[3,] 0.85667061 0.17337266 0.07623608 -0.4798390
[4,] 0.35828920 0.07548102 0.54583143 0.7536574
>spca
[,1] [,2] [,3] [,4]
[1,] 0.1757487 -1.3328606 -2.0812081 2.043494
[2,] -0.0411048 -1.4822115 2.1379949 -2.070931
[3,] 0.4166141 0.3519427 0.2726031 -3.108044
[4,] 0.1742424 0.1532248 1.9517707 4.881638
>apply(prc1$scores, 2, sd) # やっぱり princomp のスコアは標準化されていない
Comp.1 Comp.2 Comp.3 Comp.4
2.0562689 0.4926162 0.2796596 0.1543862
>tokx<- cdat %*% eg1v # 主成分を標準化せずにスコア計算
>apply(tokx, 2, sd) # 標準化しないときのスコアの分散と同じ
[1] 2.0562689 0.4926162 0.2796596 0.1543862
# 今度は個々のデータのスコアの比較。
> tail(prc1$scores) # princomp の主成分得点
Comp.1 Comp.2 Comp.3 Comp.4
[145,] 2.418746 -0.30479820 0.5044827 0.2410910
[146,] 1.944110 -0.18753230 0.1778251 0.4261959
[147,] 1.527167 0.37531698 -0.1218982 0.2543674
[148,] 1.764346 -0.07885885 0.1304816 0.1370013
[149,] 1.900942 -0.11662796 0.7232516 0.0445953
[150,] 1.390189 0.28266094 0.3629096 -0.1550386
> tail(tokx) # 標準化しないいで計算した主成分得点
[,1] [,2] [,3] [,4]
[145,] 2.418746 -0.30479820 0.5044827 0.2410910
[146,] 1.944110 -0.18753230 0.1778251 0.4261959
[147,] 1.527167 0.37531698 -0.1218982 0.2543674
[148,] 1.764346 -0.07885885 0.1304816 0.1370013
[149,] 1.900942 -0.11662796 0.7232516 0.0445953
[150,] 1.390189 0.28266094 0.3629096 -0.1550386
> tail(tok) #標準化した主成分得点
[,1] [,2] [,3] [,4]
[145,] 1.1762791 -0.6187336 1.8039168 1.5616100
[146,] 0.9454550 -0.3806864 0.6358626 2.7605835
[147,] 0.7426882 0.7618851 -0.4358805 1.6476050
[148,] 0.8580326 -0.1600817 0.4665730 0.8873934
[149,] 0.9244616 -0.2367522 2.5861852 0.2888555
[150,] 0.6760735 0.5737954 1.2976834 -1.0042261