PCA應(yīng)該是算法中比較簡單的算法之一,本主題主要介紹PCA的算法模型,應(yīng)用與數(shù)學(xué)基礎(chǔ);
??1. PCA算法與模型介紹;
??2.PCA算法的應(yīng)用;
??3.PCA數(shù)學(xué)基礎(chǔ)與相關(guān)概念;
PCA算法介紹
PCA(Principal Component Analysis)
- PCA稱主成分分析,是一種常用的數(shù)據(jù)分析方法。
- PCA的主要結(jié)果是降維,降低原始數(shù)據(jù)的維數(shù);
- PCA降維的目的是去掉原始數(shù)據(jù)中不重要的特征(或者去掉相關(guān)的特征),保留重要特征。(或者去掉相關(guān)的特征,保留不相關(guān)特征)
- PCA降維的數(shù)學(xué)理論是通過線性變換將原始數(shù)據(jù)變換為一組各維度線性無關(guān)的表示。
降維應(yīng)用背景介紹
- 降維背景說明
在機器學(xué)習(xí)的很多應(yīng)用場景中(尤其是基于統(tǒng)計學(xué)習(xí)的機器學(xué)習(xí)中),從特征維度與數(shù)量,都需要盡量可能的多,多維度的特征與海量的數(shù)據(jù)包含更加豐富的信息;然后才能通過機器學(xué)習(xí)訓(xùn)練出更加可靠的規(guī)律與結(jié)果。
多特證與海量數(shù)據(jù)的要求提高了數(shù)據(jù)采集的難度。更重要的是在很多情形下,許多特征之間可能存在相關(guān)性,從而增加了問題分析的復(fù)雜性,影響機器學(xué)習(xí)的效率,提高機器學(xué)習(xí)的成本。
數(shù)據(jù)樣本中很多特征不是孤立的,盲目去除某些特征,就不能充分利用數(shù)據(jù)中的信息,會損失很多有用的信息,從而產(chǎn)生錯誤的結(jié)論。
因此需要找到一種合理的方法,既減少需要分析特征,又減少原特征包含信息的損失,從而從分利用已經(jīng)采集的數(shù)據(jù)。
由于各特征之間存在一定的相關(guān)關(guān)系,因此盡可能的對特征進(jìn)行融合。使得新特征維數(shù)減少,同時又不相關(guān),而且還盡量包含原始特征的信息。
- 降維的作用
- 降維就是一種對高維特征數(shù)據(jù)預(yù)處理方法,是非常廣泛的數(shù)據(jù)預(yù)處理方法;降維是將高維度的數(shù)據(jù)保留下最重要的一些特征,去除噪聲(干擾結(jié)果的數(shù)據(jù))和不重要的特征; 降維可以提升數(shù)據(jù)處理速度;在實際的生產(chǎn)和應(yīng)用中,降維在一定的信息損失范圍內(nèi),可以為我們節(jié)省大量的時間和成本。作妖作用歸納如下:
- 使得數(shù)據(jù)集更易使用。
- 降低算法的計算開銷。
- 去除噪聲。
- 使得結(jié)果容易理解。
- 降維就是一種對高維特征數(shù)據(jù)預(yù)處理方法,是非常廣泛的數(shù)據(jù)預(yù)處理方法;降維是將高維度的數(shù)據(jù)保留下最重要的一些特征,去除噪聲(干擾結(jié)果的數(shù)據(jù))和不重要的特征; 降維可以提升數(shù)據(jù)處理速度;在實際的生產(chǎn)和應(yīng)用中,降維在一定的信息損失范圍內(nèi),可以為我們節(jié)省大量的時間和成本。作妖作用歸納如下:
數(shù)據(jù)降維的技術(shù)
- 降維的算法有很多,主要有:
- 奇異值分解(SVD)
- 主成分分析(PCA)
- 因子分析(FA)
- 獨立成分分析(ICA)
- 提示
- 這里主要講解PCA
Sklearn的PCA實現(xiàn)的應(yīng)用
- 在sklearn中已經(jīng)提供PCA方法的實現(xiàn)
PCA定義
- PCA類的定義說明
class sklearn.decomposition.PCA(
n_components=None, # 指定保留的特征數(shù)量(降維以后的維數(shù))
copy=True, # 訓(xùn)練過程中是否影響原始樣本數(shù)據(jù),也影響到最后降維數(shù)據(jù)的返回方式
whiten=False, # 是否對降維后的數(shù)據(jù)提供白化處理。(白化就是每一維的特征做一個標(biāo)準(zhǔn)差歸一化處理,除以一個標(biāo)準(zhǔn)偏差)
svd_solver=’auto’, # SVD分解的計算方法
tol=0.0, # 計算奇異值的公差
iterated_power=’auto’, # 采用svd_solver采用randomized方式的迭代次數(shù)。
random_state=None) # 同來創(chuàng)建隨機數(shù)的實例,比如隨機種
-
PCA參數(shù)說明
-
n_components: int, float, None or string-
int:指定降維以后的維數(shù),如果不設(shè)置,則降維維數(shù)維去原始數(shù)據(jù)維數(shù)與樣本數(shù)的最小值:n_components == min(n_samples, n_features);
- 如果svd_solver == 'arpack',則 n_components必須嚴(yán)格小于min(n_samples, n_features)
float:當(dāng)svd_solver == 'full'時,選擇的特征數(shù)大于n_components指定的百分比。
string:n_components == 'mle' 且svd_solver == 'full',使用Minka的MLE算法估算n_components的值。
None:n_components == min(n_samples, n_features) - 1
-
-
copy: bool (default True),- False:返回降維數(shù)據(jù)使用:fit_transform(X)
- True:返回降維數(shù)據(jù)使用:fit(X).transform(X)
-
whiten: bool, optional (default False)- 降維后的數(shù)據(jù)進(jìn)行白化處理(標(biāo)準(zhǔn)差歸一化處理)。
-
svd_solver: string {‘a(chǎn)uto’, ‘full’, ‘a(chǎn)rpack’, ‘randomized’}- auto:根據(jù)基于x.shape和n_components選擇svd_solver:
- 如果輸入數(shù)據(jù)大于500x500且要選擇的特征維數(shù)小于數(shù)據(jù)最小維數(shù)的80%,則使用更有效的“randomized”方法。
- 否則完全使用SVD,并選擇性地選擇特征。
- full:調(diào)用scipy.linalg.svd執(zhí)行svd奇異值分解,然后選擇特征
- arpack:調(diào)用scipy.sparse.linalg.svds進(jìn)行奇異值分解,然后選擇特征;嚴(yán)格要求:0 < n_components < min(X.shape)
- randomized:采用Halko的隨機SVD(隨機奇異值分解)
- auto:根據(jù)基于x.shape和n_components選擇svd_solver:
-
tol: float >= 0, optional (default .0)- 公差:在svd_solver == ‘a(chǎn)rpack’計算奇異值方法中需要使用的公差。
-
iterated_power: int >= 0, or ‘a(chǎn)uto’, (default ‘a(chǎn)uto’)- 使用svd_solver == ‘randomized’計算SVD需要用到的冪法迭代次數(shù)。
-
random_state: int, RandomState instance or None, optional (default None)- 如果為int,則隨機數(shù)生成器使用的種子;如果為random state實例,則隨機數(shù)生成器為randomstate;如果為none,則隨機數(shù)生成器為np.random使用的randomstate實例。當(dāng)svd_solver=='arpack'或'randomized'時使用。
-
- 提示:
- 盡管上面參數(shù)顯得有點復(fù)雜,并涉及數(shù)學(xué)計算的概念,但大部分情況下,除了第一個參數(shù),其他參數(shù)我們采用默認(rèn)參數(shù)即可。
- PCA主要方法與函數(shù)
- 下面的所有y參數(shù)都是沒有意義,或者被忽略。這是sklearn統(tǒng)一調(diào)用接口的結(jié)果(屬于設(shè)計模式導(dǎo)致的瑕疵)。
-
fit(X[, y])- 訓(xùn)練數(shù)據(jù)。返回PCA對象
-
transform(X)- 使用訓(xùn)練的結(jié)果,對X降維
-
fit_transform(X[, y])- 訓(xùn)練數(shù)據(jù),并應(yīng)用降維到X。
-
get_covariance()
-計算數(shù)據(jù)協(xié)方差( 用生成模型)。 -
get_precision()- 計算數(shù)據(jù)精度矩陣( 用生成模型)。
-
inverse_transform(X)- 計算降維以后的原始數(shù)據(jù)
-
score(X[, y])- 計算所有樣本的log似然平均值。
-
score_samples(X)- 返回每個樣本的對數(shù)似然值。
-
set_params(**params)- 設(shè)置PCA的參數(shù)。
-
get_params([deep])- 得到PCA的參數(shù)
PCA應(yīng)用
% matplotlib inline
import matplotlib.pyplot as plt
import sklearn.datasets as ds
import sklearn.decomposition as de
# 加載數(shù)據(jù)集
data, target = ds.load_iris(return_X_y=True)
# 構(gòu)建PCA對象
pca = de.PCA(n_components=2) #, svd_solver='arpack',copy=True)
# 訓(xùn)練數(shù)據(jù)
pca.fit(data) # 返回pca本身
# 對數(shù)據(jù)降維
# data_de = pca.transform(data)
# data_de = pca.fit_transform(data)
data_de
# 數(shù)據(jù)可視化
fig = plt.figure('PCA降維', figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.scatter(data_de[0:50, 0], data_de[0:50:, 1], s=9, c='r')
ax.scatter(data_de[50:100, 0], data_de[50:100:, 1], s=9, c='g')
ax.scatter(data_de[100:150, 0], data_de[100:150:, 1], s=9, c='b')
plt.show()

print(pca.get_precision())
print('-------')
print(pca.get_covariance())
print('-------')
print(pca.singular_values_)
print('-------')
print(pca.explained_variance_)
print('-------')
print(pca.explained_variance_ratio_)
print('-------')
print(pca.noise_variance_)
# 均值處理
print(np.mean(data_de))
[[10.38525514 -6.82204502 -4.20572606 -1.7510368 ]
[-6.82204502 11.21577598 3.34261 1.41240052]
[-4.20572606 3.34261 4.90734692 -6.14476038]
[-1.7510368 1.41240052 -6.14476038 16.99268128]]
-------
[[ 0.67919741 -0.03258618 1.27066452 0.5321852 ]
[-0.03258618 0.18113034 -0.31863564 -0.13363564]
[ 1.27066452 -0.31863564 3.11934547 1.28541527]
[ 0.5321852 -0.13363564 1.28541527 0.58961806]]
-------
[25.08986398 6.00785254]
-------
[4.22484077 0.24224357]
-------
[0.92461621 0.05301557]
-------
0.05110346761007829
1.5395092608135505e-16
- 降維后的數(shù)據(jù)再用于其他機器學(xué)習(xí)算法,可以提高計算速度,降低計算成本。
PCA算法模型
數(shù)據(jù)與符號表示
- 假設(shè)數(shù)據(jù)樣本為
,特征維數(shù)是
,樣本總數(shù)是
-
其中
-
表示所有樣本形成的矩陣。
-
標(biāo)識一個具有
維特征的樣本。
- 整個數(shù)據(jù)集樣本個數(shù)是
個。
-
表示第
個樣本的第
個特征。
-
如果使用特征來表示
- 其中
-
表示所有樣本形成的矩陣。
-
標(biāo)識一個具有
樣本的特征變量。
- 整個數(shù)據(jù)集樣本特征維數(shù)是
個。
-
數(shù)據(jù)樣本例子
- 鳶尾花數(shù)據(jù)集
import sklearn.datasets as ds
# 加載數(shù)據(jù)集
data, target = ds.load_iris(return_X_y=True)
data.shape # 150就是樣本個數(shù),4就是特征維數(shù),每一行表示一個樣本,每列表示一個特征
(150, 4)
協(xié)方差矩陣模型
協(xié)方差模型公式
- 假設(shè)
是表示兩個樣本總數(shù)為
的特征(再數(shù)學(xué)上稱呼為特征變量)。
- 如果使用向量或者矩陣表示,則是下面公式
協(xié)方差實現(xiàn)
import sklearn.datasets as ds
import numpy as np
# 加載數(shù)據(jù)集
data, target = ds.load_iris(return_X_y=True)
# 取前面兩個特征做例子
Y_0 = data[:,0]
Y_1 = data[:,1]
Y_0,Y_1
(array([5.1, 4.9, 4.7, 4.6, 5. , 5.4, 4.6, 5. , 4.4, 4.9, 5.4, 4.8, 4.8,
4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5. ,
5. , 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5. , 5.5, 4.9, 4.4,
5.1, 5. , 4.5, 4.4, 5. , 5.1, 4.8, 5.1, 4.6, 5.3, 5. , 7. , 6.4,
6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5. , 5.9, 6. , 6.1, 5.6,
6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8, 6.7,
6. , 5.7, 5.5, 5.5, 5.8, 6. , 5.4, 6. , 6.7, 6.3, 5.6, 5.5, 5.5,
6.1, 5.8, 5. , 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, 6.3, 5.8, 7.1, 6.3,
6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8, 5.7, 5.8, 6.4, 6.5,
7.7, 7.7, 6. , 6.9, 5.6, 7.7, 6.3, 6.7, 7.2, 6.2, 6.1, 6.4, 7.2,
7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4, 6. , 6.9, 6.7, 6.9, 5.8,
6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9]),
array([3.5, 3. , 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3. ,
3. , 4. , 4.4, 3.9, 3.5, 3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3. ,
3.4, 3.5, 3.4, 3.2, 3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.1, 3. ,
3.4, 3.5, 2.3, 3.2, 3.5, 3.8, 3. , 3.8, 3.2, 3.7, 3.3, 3.2, 3.2,
3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2. , 3. , 2.2, 2.9, 2.9,
3.1, 3. , 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3. , 2.8, 3. ,
2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3. , 3.4, 3.1, 2.3, 3. , 2.5, 2.6,
3. , 2.6, 2.3, 2.7, 3. , 2.9, 2.9, 2.5, 2.8, 3.3, 2.7, 3. , 2.9,
3. , 3. , 2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3. , 2.5, 2.8, 3.2, 3. ,
3.8, 2.6, 2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2, 2.8, 3. , 2.8, 3. ,
2.8, 3.8, 2.8, 2.8, 2.6, 3. , 3.4, 3.1, 3. , 3.1, 3.1, 3.1, 2.7,
3.2, 3.3, 3. , 2.5, 3. , 3.4, 3. ]))
# 計算平均值
Y_0_mean = np.mean(Y_0) # 按照行計算均值(就是樣本均值)
Y_1_mean = np.mean(Y_1)
Y_0_mean,Y_1_mean
(5.843333333333334, 3.0540000000000003)
# 中心化(中心化以后的樣本均值為0:因為誤差,實際計算中是接近0)
Y_0 = Y_0 - Y_0_mean
Y_1 = Y_1 - Y_1_mean
Y_0.shape, Y_1.shape
((150,), (150,))
# 計算協(xié)方差
cv = np.dot(Y_0, Y_1)/(len(Y_0)-1)
cv
-0.03926845637583892
# numpy的計算結(jié)果
# 注意下面計算的結(jié)果是協(xié)方差矩陣,觀察上面計算的值與下面計算的對應(yīng)的值
np.cov(data[:,0:2].T), np.cov(Y_0), np.cov(Y_1),
(array([[ 0.68569351, -0.03926846],
[-0.03926846, 0.18800403]]), array(0.68569351), array(0.18800403))
協(xié)方差矩陣模型
- 根據(jù)上面的計算細(xì)節(jié),可以把協(xié)方差矩陣的計算公式表示如下。
對特征中心化
-
注意:
- 不是對樣本去中心化,而是特征,這里鳶尾花4個特征,每個特征150個數(shù)據(jù)樣本。
-
表示對某個特征的所有樣本求均值,去中心化公式:
- 其中
表示去中心化后的特征變量
import sklearn.datasets as ds
import numpy as np
# 加載數(shù)據(jù)集
data, target = ds.load_iris(return_X_y=True)
data = np.mat(data) # 使用矩陣類型,可以保持形狀
data_mean = np.mean(data, axis=0)
data_mean # 這個維數(shù)應(yīng)該是樣本個數(shù)(150, 1)
matrix([[5.84333333, 3.054 , 3.75866667, 1.19866667]])
# 去中心化
Y = data - data_mean
data[0], data_mean, data[0] - data_mean, Y[0] # 驗證上面的計算結(jié)果
(matrix([[5.1, 3.5, 1.4, 0.2]]),
matrix([[5.84333333, 3.054 , 3.75866667, 1.19866667]]),
matrix([[-0.74333333, 0.446 , -2.35866667, -0.99866667]]),
matrix([[-0.74333333, 0.446 , -2.35866667, -0.99866667]]))
計算協(xié)方差矩陣
- 協(xié)方差矩陣公式
- 其中
表示的是樣本個數(shù)。(不是特征維數(shù))
Y_cov = np.matmul(Y.T,Y)/ (Y.shape[0]-1)
Y_cov
matrix([[ 0.68569351, -0.03926846, 1.27368233, 0.5169038 ],
[-0.03926846, 0.18800403, -0.32171275, -0.11798121],
[ 1.27368233, -0.32171275, 3.11317942, 1.29638747],
[ 0.5169038 , -0.11798121, 1.29638747, 0.58241432]])
- 這是PCA算出來的協(xié)方差(降維為2的計算結(jié)果)
[[ 0.67919741 -0.03258618 1.27066452 0.5321852 ]
[-0.03258618 0.18113034 -0.31863564 -0.13363564]
[ 1.27066452 -0.31863564 3.11934547 1.28541527]
[ 0.5321852 -0.13363564 1.28541527 0.58961806]]
- 這是PCA算出來的協(xié)方差(降維為2的計算結(jié)果)
[[ 0.68569351 -0.03926846 1.27368233 0.5169038 ]
[-0.03926846 0.18800403 -0.32171275 -0.11798121]
[ 1.27368233 -0.32171275 3.11317942 1.29638747]
[ 0.5169038 -0.11798121 1.29638747 0.58241432]]
# 使用numpy計算的協(xié)方差矩陣驗證
np.cov(Y.T) # 與上面比對,驗證計算的正確性
array([[ 0.68569351, -0.03926846, 1.27368233, 0.5169038 ],
[-0.03926846, 0.18800403, -0.32171275, -0.11798121],
[ 1.27368233, -0.32171275, 3.11317942, 1.29638747],
[ 0.5169038 , -0.11798121, 1.29638747, 0.58241432]])
Y_cov[3,0],Y_cov[0,3] # 這是一個對稱矩陣
(0.5169038031319912, 0.5169038031319912)
特征向量模型
- 特征向量與特征值,通過矩陣的奇異值分解得到。
特征方程的定義
- 特征方程值得是對一個矩陣
,如果存在一個標(biāo)量
與列向量
,滿足如下等式:
稱
為矩陣
的特征值,
為矩陣
的特征向量
- 求解特征值與特征向量的方法就是奇異值分解算法。
- 其中
與列向量
不是唯一的。所有的特征值與特征向量可以表達(dá)成如下公式。
- 其中
- 如果全部使用矩陣表達(dá),則可以表達(dá)如下:
-
如果對于方陣 ,推導(dǎo)一下可以得到:
SVD自己實現(xiàn)比較痛苦,對這種完全已經(jīng)理解,并信任的實現(xiàn),可以調(diào)用第三方實現(xiàn),這里調(diào)用numpy的函數(shù)實現(xiàn)。
numpy.linalg.svd(
a, # 被求解的矩陣(方陣)
full_matrices=True, # 影響輸出的特征向量的維度,采用默認(rèn)值即可
compute_uv=True) # 計算特征向量
- 返回左特征向量矩陣 , 特征值矩陣,右特征向量(在方陣情況下,就是左特征向量矩陣的逆)
import numpy.linalg as la
u,s,v = la.svd(Y_cov)
u.shape
(4, 4)
v.shape
(4, 4)
s.shape
(4,)
s # 這里的特征值與PCA計算出來的有差異
array([4.22484077, 0.24224357, 0.07852391, 0.02368303])
# 使用PCA降維為2的協(xié)方差的結(jié)果
import numpy as np
import numpy.linalg as la
M = np.mat(
[[ 0.67919741, -0.03258618, 1.27066452, 0.5321852 ],
[-0.03258618, 0.18113034, -0.31863564, -0.13363564],
[ 1.27066452, -0.31863564, 3.11934547, 1.28541527],
[ 0.5321852, -0.13363564, 1.28541527, 0.58961806]]
)
la.svd(M)
(matrix([[-0.36158968, -0.65653989, 0.50672256, -0.42595836],
[ 0.08226889, -0.72971236, -0.51869935, 0.43783865],
[-0.85657211, 0.17576741, -0.47327155, -0.10678992],
[-0.35884393, 0.07470646, 0.50019723, 0.78450794]]),
array([4.22484077, 0.24224357, 0.05110347, 0.05110347]),
matrix([[-0.36158968, 0.08226889, -0.85657211, -0.35884393],
[-0.65653989, -0.72971236, 0.17576741, 0.07470646],
[ 0.50672256, -0.51869935, -0.47327155, 0.50019723],
[-0.42595836, 0.43783865, -0.10678992, 0.78450794]]))
# 使用scipy的奇異值分解
import scipy.linalg as sla
import numpy.linalg as la
M = np.mat(
[[ 0.67919741, -0.03258618, 1.27066452, 0.5321852 ],
[-0.03258618, 0.18113034, -0.31863564, -0.13363564],
[ 1.27066452, -0.31863564, 3.11934547, 1.28541527],
[ 0.5321852, -0.13363564, 1.28541527, 0.58961806]]
)
sla.svd(M)
(array([[-0.36158968, -0.65653989, 0.50672256, -0.42595836],
[ 0.08226889, -0.72971236, -0.51869935, 0.43783865],
[-0.85657211, 0.17576741, -0.47327155, -0.10678992],
[-0.35884393, 0.07470646, 0.50019723, 0.78450794]]),
array([4.22484077, 0.24224357, 0.05110347, 0.05110347]),
array([[-0.36158968, 0.08226889, -0.85657211, -0.35884393],
[-0.65653989, -0.72971236, 0.17576741, 0.07470646],
[ 0.50672256, -0.51869935, -0.47327155, 0.50019723],
[-0.42595836, 0.43783865, -0.10678992, 0.78450794]]))
降維模型
- 選擇對應(yīng)最大特征值的兩個特征向量
[-0.36158968, -0.65653989, 0.50672256, -0.42595836],
[ 0.08226889, -0.72971236, -0.51869935, 0.43783865],
# 選擇的特征
e = v[:, 0:2] # 在V中取兩列,或者u中取兩行。
e
matrix([[-0.36158968, 0.08226889],
[-0.65653988, -0.72971237],
[ 0.58099728, -0.59641809],
[ 0.31725455, -0.32409435]])
# 計算降維后的數(shù)據(jù)樣本
de_data = np.matmul(data, e)
de_data.shape
(150, 2)
% matplotlib inline
import matplotlib.pyplot as plt
import sklearn.datasets as ds
import sklearn.decomposition as de
# 數(shù)據(jù)可視化
fig = plt.figure('PCA降維', figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.scatter(list(de_data[0:50, 0]), list(de_data[0:50:, 1]), s=9, c='r')
ax.scatter(list(de_data[50:100, 0]), list(de_data[50:100:, 1]), s=9, c='g')
ax.scatter(list(de_data[100:150, 0]), list(de_data[100:150:, 1]), s=9, c='b')
plt.show()

PCA算法數(shù)學(xué)基礎(chǔ)
數(shù)據(jù)集準(zhǔn)備
import sklearn.datasets as ds
import numpy as np
# 加載數(shù)據(jù)集
data, target = ds.load_iris(return_X_y=True)
均值的概念
- 樣本總體的均值
np.mean(data,axis=0)
array([5.84333333, 3.054 , 3.75866667, 1.19866667])
- 一個樣本的均值
np.mean(data[0])
2.55
方差的概念
# numpy的計算
np.var(data,axis=0)
array([0.68112222, 0.18675067, 3.09242489, 0.57853156])
# 手工計算
m = np.mean(data,axis=0)
s = np.zeros(shape=4)
for d in data:
c = (d - m) * (d-m)
s += c
r = s /len(data)
r
array([0.68112222, 0.18675067, 3.09242489, 0.57853156])
協(xié)方差的概念
- 相同向量的協(xié)方差
# numpy的實現(xiàn)
np.cov(data[:,0])
array(0.68569351)
# 手工計算的結(jié)果
# 使用向量的每個特征 - 向量特征均值
a1 = data[:,0]-np.mean(data[:,0])
# 計算每個特征的平方
a2 = a1 * a1
# 計算平方和
a3 = a2.sum()
# 求均值(無偏:除以n-1)
a4 = a3 / (len(data[:,0]) - 1)
a4
0.6856935123042507
- 不同向量的協(xié)方差
- numpy中自動形成對稱的矩陣(就是協(xié)方差矩陣)
# numpy的實現(xiàn)(使用兩個參數(shù))
np.cov(data[:,0],data[:,1])
array([[ 0.68569351, -0.03926846],
[-0.03926846, 0.18800403]])
# numpy的實現(xiàn)(使用一個參數(shù):等同于上面參數(shù)的合并)
np.cov(data[:,0:2].T)
array([[ 0.68569351, -0.03926846],
[-0.03926846, 0.18800403]])
# 手工計算的結(jié)果
# 使用向量的每個特征 - 向量特征均值
x1 = data[:,0]-np.mean(data[:,0])
y1 = data[:,1]-np.mean(data[:,1])
# 計算每個特征的平方
a2 = x1 * y1
# 計算平方和
a3 = a2.sum()
# 求均值(無偏:除以n-1)
a4 = a3 / (len(data[:,0]) - 1)
a4
-0.03926845637583893
協(xié)方差矩陣的概念
- numpy的cov函數(shù)返回的協(xié)方差矩陣,協(xié)方差矩陣是向量與向量的轉(zhuǎn)置,對應(yīng)求方差得到的矩陣,現(xiàn)在說明如下(使用上面的符號):
-
其中
-
表示所有樣本形成的矩陣。
-
標(biāo)識一個具有
樣本的特征變量。
- 整個數(shù)據(jù)集樣本特征維數(shù)是
個。
-
X的協(xié)方差矩陣
就是:
- 協(xié)方差矩陣的維數(shù)為
,其中n為特征維數(shù))
對鳶尾花數(shù)據(jù)而言就是(4,4)
# numpy的實現(xiàn)
np.cov(data.T).shape
np.cov(data.T)
array([[ 0.68569351, -0.03926846, 1.27368233, 0.5169038 ],
[-0.03926846, 0.18800403, -0.32171275, -0.11798121],
[ 1.27368233, -0.32171275, 3.11317942, 1.29638747],
[ 0.5169038 , -0.11798121, 1.29638747, 0.58241432]])
PCA算法完整實現(xiàn)(numpy實現(xiàn))
% matplotlib inline
import matplotlib.pyplot as plt
import sklearn.datasets as ds
import numpy as np
import numpy.linalg as la
# 加載數(shù)據(jù)集
data, target = ds.load_iris(return_X_y=True)
data = np.mat(data) # 使用矩陣類型,可以保持形狀
# 計算均值
data_mean = np.mean(data, axis=0) # 按照特征,返回(1,4)向量
# 使用均值中心化
Y = data - data_mean
# 計算Y的協(xié)方差
Y_cov = np.matmul(Y.T,Y)/ (Y.shape[0]-1)
# 求奇異值分解
u,s,v = la.svd(Y_cov)
# 選擇特征向量
e = u[:, 0:2] # 在V中取兩列,或者u中取兩行。
# 計算降維后的數(shù)據(jù)樣本
de_data = np.matmul(data, e)
de_data = np.mean(de_data)-de_data #中心化處理的算法中做了一個簡單的中心化處理
# 可視化降維以后的數(shù)據(jù)
fig = plt.figure('PCA降維', figsize=(6, 4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.scatter(list(de_data[0:50, 0]), list(de_data[0:50:, 1]), s=9, c='r')
ax.scatter(list(de_data[50:100, 0]), list(de_data[50:100:, 1]), s=9, c='g')
ax.scatter(list(de_data[100:150, 0]), list(de_data[100:150:, 1]), s=9, c='b')
plt.show()

-
對比下PCA可視化降維的效果
sklearn模塊運算可視化結(jié)果
