PCA的介紹,實例及繪圖
PCA的介紹
多元統計分析中普遍存在的困難中,有一個困難是多元數據的可視化。matlab的plot可以顯示兩個變量之間的關系,plot3和surf可以顯示三維的不同。但是當有多於3個變量時,要可視化變量之間的關系就很困難了。
幸運的是,在一組多變量的數據中,很多變量常常是一起變動的。一個原因是很多變量是同一個驅動影響的的結果。在很多系統中,只有少數幾個這樣的驅動,但是多余的儀器使我們測量了很多的系統變量。當這種情況發生的時候,你需要處理的就是冗余的信息。而你可以通過用一個簡單的新變量代替這組變量來簡化此問題。
主成分分析是一個定量的嚴格的可以起到簡化作用的方法。它產生一組叫做主成分的新變量,每一個主成分是原始變量的線性組合。所有主成分是相互正交的,從而不存在冗余的信息。所有主成分形成了原始數據空間的一組正交基。
但是有無數種方式來創建一組正交基,那主成分正交基有什么特殊之處呢?
第一主成分是數據空間的一個軸。當你把各觀察值投影到這個軸時,結果會形成一個新變量,這個變量的方差是所有可選的軸中最大的。
第二主成分是空間的另一個軸,它垂直於第一個軸。投影數據到這個軸上將得到另一組變量,此變量的方差是所有可選的軸中最大的。
最后得到的所有主成分個數是與原始變量相同的,但是通常前幾個主成分方差的和占到了原始數據總方差的80%以上。通過繪制這組新變量,研究者常常會更深入的了解產生原始數據的驅動力。
在matlab中,可以使用princomp函數來找到主成分,通過使用此函數,你需要用到測量的原始數據。然而,如果你缺少這些數據,但是有這些數據的樣本自相關或協方差矩陣,你可以通過使用pcacov函數來做主成分分析。
主成分分析的實例
計算成分
考慮一個例子,它使用了衡量美國329個城市生活質量的9個指標:氣候、住房、健康、犯罪率、交通、教育、藝術、娛樂和經濟。對於各指標,越高表示越好,如高的犯罪指標表示低的犯罪率。
先從cities.mat中加載數據
>> load cities
>> whos
Name Size Bytes Class Attributes
categories 9x14 252 char
names 329x43 28294 char
ratings 329x9 23688 double
cities.mat中包含了3個變量:
categories--一個包含各指標名字的字符串矩陣
names--一個包含329個城市名字的字符串矩陣
ratings--329行9列的數據矩陣
為快速對ratings數據有個直觀的印象,可以使用盒圖繪制出數據來
boxplot(ratings,'orientation','horizontal','labels',categories)
可以注意到大體上藝術和住房的指標要比犯罪和氣候的指標有更大的變異性。
通常你會考慮繪制各對原始變量,但這將有36對變量圖。而主成分分析或許會降低你需要考慮的變量個數。
有時對原始數據計算主成分是可以的,這在各變量是相同的單位時是很合適的。但是當變量單位不同或不同列數據的方差相差很大時,先對數據做標准化是更好的。
可以通過除以各列標准差來標准化數據,如下
stdr = std(ratings);
sr = ratings./repmat(stdr,329,1);
這樣就為找主成分做好准備了。
[coefs,scores,variances,t2] = princomp(sr);
下面各部分解釋了princomp函數的輸出。
Component Coeffcients
coefs包含了產生主成分的原始變量線性組合的系數,它常被稱為loadings。它是9X9的矩陣,前三個主成分的系數向量為
>> c3 = coefs(:,1:3)
c3 =
0.2064 -0.2178 0.6900
0.3565 -0.2506 0.2082
0.4602 0.2995 0.0073
0.2813 -0.3553 -0.1851
0.3512 0.1796 -0.1464
0.2753 0.4834 -0.2297
0.4631 0.1948 0.0265
0.3279 -0.3845 0.0509
0.1354 -0.4713 -0.6073
可以看到在第一主成分中最大的系數是第三個和第七個,即健康和藝術。此主成分的所有系數都是正的。
主成分通常是單位長且正交的
I = c3'*c3
I =
1.0000 -0.0000 -0.0000
-0.0000 1.0000 -0.0000
-0.0000 -0.0000 1.0000
Component Scores
scores包含了原始數據在被主成分定義的新坐標系統中的坐標,它是和原始數據矩陣同大小的。
繪制scores的前兩列可以展示原始數據投影到前兩個主成分的新數據。princomp函數計算的scores具有零均值。
plot(scores(:,1),scores(:,2),'+')
xlabel('1st Principal Component')
ylabel('2nd Principal Component')
注意到上圖中右邊的離群點。函數gname可以用於標出這些離群點,調用gname時傳入一個string矩陣,它包含了各點的標簽,如下
gname(names)
移動鼠標在右半部分的點點擊,當你點擊各點的時候,在點上會標記names中對應的字符串,如下
從上面的標記,發現這些離散點是美國一些人口比較多的城市,它們明顯與其他數據不同,所以它們可能需要被分離開。為移除這些數據,首先識別這些數據的行,方法如下
1.關閉上面的figure
2.重繪plot
plot(scores(:,1),scores(:,2),'+')
xlabel('1st Principal Component');
ylabel('2nd Principal Component');
3.運行gname函數,如輸入參數
4.標記離散點,標記自動為這些數據的行數
然后創建一個包含這些點的變量
metro = [43 65 179 213 234 270 314];
names(metro,:)
ans =
Boston, MA
Chicago, IL
Los Angeles, Long Beach, CA
New York, NY
Philadelphia, PA-NJ
San Francisco, CA
Washington, DC-MD-VA
然后移除這些行
rsubset = ratings;
nsubset = names;
nsubset(metro,:) = [];
rsubset(metro,:) = [];
size(rsubset)
ans =
322 9
Component Variances
variances是一個包含了主成分方差的向量,scores的每一列的方差即為variances對應的項
variances
variances =
3.4083
1.2140
1.1415
0.9209
0.7533
0.6306
0.4930
0.3180
0.1204
你可以很容易的計算所有差異性占到百分比
percent_explained = 100*variances/sum(variances)
percent_explained =
37.8699
13.4886
12.6831
10.2324
8.3698
7.0062
5.4783
3.5338
1.3378
使用pareto函數可以以圖的方式顯示此百分比
pareto(percent_explained)
xlabel('Principal Component')
ylabel('Variance Explained (%)')
顯示的figure中可以看到第一主成分明顯比第二主成分要高很多,但它只解釋了不到40%的方差,所以需要使用更多的成分。可以看到前三個主成分解釋了三分之二的方差,所以這三個成分可以作為一個理想的方式來降低維數。
Hotelling's T2
t2是一個衡量各觀測值離數據中心距離的統計量,這是一個找出數據中極值點的有效分析方法。
[st2, index] = sort(t2,'descend'); % Sort in descending order.
extreme = index(1)
extreme =
213
names(extreme,:)
ans =
New York, NY
這個極值點是不奇怪的,因為Vew York的ratings是離美國城鎮平均值是最遠的。
結果可視化
使用biplot函數可以幫助我們可視化各變量的主成分的系數和各觀察值的主成分scores。如下,
biplot(coefs(:,1:2), 'scores',scores(:,1:2),...
'varlabels',categories);
axis([-.26 1 -.51 .51]);
上圖中,9個變量以向量的形式呈現出來,向量的方向和長度表示了各變量對兩個主成分的貢獻。例如,對於第一主成分,對所有9個變量的系數都是正值。對於第 二主成分,變量教育、健康、藝術和交通是正的貢獻,其他5個是負的貢獻。這表明此成分在不同城市間是有區別的:大的值的變量、小的值的變量和負值的變量。
上圖中變量標簽有時候會很擁擠,可以在繪圖時在varlabels參數中忽略一些,或在figure的編輯模式下選中並移動它們。可以使用Tools下的Data Cursors功能查看圖中的信息
biplot函數也可以用於繪制三維的信息
biplot(coefs(:,1:3), 'scores',scores(:,1:3),...
'obslabels',names);
axis([-.26 1 -.51 .51 -.61 .81]);
view([30 40]);
matlab實現主成分分析 princomp函數
最近看了些主成分分析,混跡Matlab論壇,翻了n多帖子,對princomp函數有了些了解。
在此只講一些個人理解,並沒有用術語,只求通俗。
貢獻率:每一維數據對於區分整個數據的貢獻,貢獻率最大的顯然是主成分,第二大的是次主成分......
[coef,score,latent,t2] = princomp(x);(個人觀點):
x:為要輸入的n維原始數據。帶入這個matlab自帶函數,將會生成新的n維加工后的數據(即score)。此數據與之前的n維原始數據一一對應。
score:生成的n維加工后的數據存在score里。它是對原始數據進行的分析,進而在新的坐標系下獲得的數據。他將這n維數據按貢獻率由大到小排列。(即在改變坐標系的情況下,又對n維數據排序)
latent:是一維列向量,每一個數據是對應score里相應維的貢獻率,因為數據有n維所以列向量有n個數據。由大到小排列(因為score也是按貢獻率由大到小排列)。
coef:是系數矩陣。通過cofe可以知道x是怎樣轉換成score的。
則模型為從原始數據出發:
score= bsxfun(@minus,x,mean(x,1))*coef;(作用:可以把測試數據通過此方法轉變為新的坐標系)
逆變換:
x= bsxfun(@plus,score*inv(coef),mean(x,1))
例子:

上圖是通過自帶函數繪制,當貢獻率累加至95%,以后的維數會不在顯示,最多只顯示10維。
下面用自己編寫的表示:
之前的錯誤認識:
1.認為主成分分析中latent顯示的貢獻值是原始數據的,其實是加工后的數據的。解釋:對原始數據既然選擇PCA方法,那么計算機認為原始數據每維之間可能存在關聯,你想去掉關聯、降低維數。所以采用這種方法的。所以計算機並不關心原始數據的貢獻值,因為你不會去用了,用的是加工后的數據(這也是為什么當把輸入數據每一維的順序改變后,score、latent不受影響的原因)。
2.認為PCA分析后自動降維,不對。PCA后會有貢獻值,是輸入者根據自己想要的貢獻值進行維數的改變,進而生成數據。(一般大家會取貢獻值在85%以上,要求高一點95%)。
3.PCA分析,只根據輸入數據的特征進行主成分分析,與輸出有多少類型,每個數據對應哪個類型無關。如果樣本已經分好類型,那PCA后勢必對結果的准確性有一定影響,我認為對於此類數據的PCA,就是在降維與准確性間找一個平衡點的問題,讓數據即不會維數多而使運算復雜,又有較高的分辨率。