轉:PCA的Python實現
http://blog.csdn.net/jerr__y/article/details/53188573
本文主要參考下面的文章,文中的代碼基本是把第二篇文章的代碼手寫實現了一下。
- pca講解:http://www.cnblogs.com/jerrylead/archive/2011/04/18/2020209.html
- python實現:http://blog.csdn.net/u012162613/article/details/42177327
總體代碼
"""
總的代碼.
Func: 對原始的特征矩陣進行降維, lowDataMat為降維之後返回新的特征矩陣。
Usage: lowDDataMat = pca(dataMat, k)
"""
# 零均值化
def zeroMean(dataMat):
# 求各列特征的平均值
meanVal = np.mean(dataMat, axis=0)
newData = dataMat - meanVal
return newData, meanVal
def pca(dataMat,k):
newData,meanVal=zeroMean(dataMat)
covMat=np.cov(newData,rowvar=0) #求協方差矩陣,return ndarray;若rowvar非0,一列代表一個樣本,為0,一行代表一個樣本
eigVals,eigVects=np.linalg.eig(np.mat(covMat))#求特征值和特征向量,特征向量是按列放的,即一列代表一個特征向量
eigValIndice=np.argsort(eigVals) #對特征值從小到大排序
k_eigValIndice=eigValIndice[-1:-(k+1):-1] #最大的k個特征值的下標
k_eigVect=eigVects[:,k_eigValIndice] #最大的k個特征值對應的特征向量
lowDDataMat=newData*k_eigVect #低維特征空間的數據
return lowDDataMat
# reconMat=(lowDDataMat*k_eigVect.T)+meanVal #重構數據
# return lowDDataMat,reconMat
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
下面逐步來實現PCA
(0)先準備好數據
import numpy as np
- 1
# n維的原始數據,本例中n=2。
data = np.array([[2.5,2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7], [2, 1.6], [1, 1.1], [1.5, 1.6], [1.1, 0.9]])
print data
- 1
- 2
- 3
- 4
[[ 2.5 2.4] [ 0.5 0.7] [ 2.2 2.9] [ 1.9 2.2] [ 3.1 3. ] [ 2.3 2.7] [ 2. 1.6] [ 1. 1.1] [ 1.5 1.6] [ 1.1 0.9]]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
(1)零均值化
# (1)零均值化
def zeroMean(dataMat):
# 求各列特征的平均值
meanVal = np.mean(dataMat, axis=0)
newData = dataMat - meanVal
return newData, meanVal
newData, meanVal = zeroMean(data)
print ‘the newData is \n‘, newData
print ‘the meanVal is \n‘, meanVal
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
the newData is
[[ 0.69 0.49]
[-1.31 -1.21]
[ 0.39 0.99]
[ 0.09 0.29]
[ 1.29 1.09]
[ 0.49 0.79]
[ 0.19 -0.31]
[-0.81 -0.81]
[-0.31 -0.31]
[-0.71 -1.01]]
the meanVal is
[ 1.81 1.91]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
(2)對各維特征的協方差矩陣
# (2)求協方差矩陣,rowvar=036表示每列對應一維特征
covMat = np.cov(newData, rowvar=0)
print covMat
# 若rowvar=1表示沒行是一維特征,每列表示一個樣本,顯然咱們的數據不是這樣的
# covMat2 = np.cov(newData, rowvar=1)
# print covMat2
- 1
- 2
- 3
- 4
- 5
- 6
[[ 0.61655556 0.61544444]
[ 0.61544444 0.71655556]]
- 1
- 2
- 3
(3)求(2)中的協方差矩陣的特征值和特征向量
# (3)求協方差矩陣的特征值和特征向量,利用numpy中的線性代數模塊linalg中的eig函數
eigVals, eigVects = np.linalg.eig(np.mat(covMat))
print ‘特征值為:\n‘, eigVals
print ‘特征向量為\n‘, eigVects
- 1
- 2
- 3
- 4
特征值為:
[ 0.0490834 1.28402771]
特征向量為
[[-0.73517866 -0.6778734 ]
[ 0.6778734 -0.73517866]]
- 1
- 2
- 3
- 4
- 5
- 6
上面的結果中:
特征值為:
[ 0.0490834 1.28402771]
特征向量為
[[-0.73517866 -0.6778734 ]
[0.6778734 -0.73517866]]
特征值0.0490834對應的特征向量是第一列(-0.73517866 0.6778734)T
(4)降維到k維(k < n)
# (4)保留主要的成分,將特征值按照從大到小的順序排序,選擇其中最大的k個,然後將對應的k個特征向量分別作為列向量組成的特征向量矩陣。
# 比如本例子中保留1.28402771對應的特征向量(-0.6778734 -0.73517866)^T
k = 1 # 此例中取k = 1
eigValIndice = np.argsort(eigVals) # 從小到大排序
n_eigValIndice = eigValIndice[-1:-(k+1):-1] # 取值最大的k個下標
n_eigVect = eigVects[:, n_eigValIndice] # 取對應的k個特征向量
print n_eigVect
print n_eigVect.shape
lowDataMat = newData*n_eigVect # 低維特征空間的數據
reconMat = (lowDataMat * n_eigVect.T) + meanVal # 重構數據,得到降維之後的數據
print ‘將樣本點投影到選取的低維特征向量上,實際使用的是這個結果作為新的特征:\n‘, lowDataMat
print ‘降維之後的樣本:\n‘, reconMat
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
[[-0.6778734 ]
[-0.73517866]]
(2L, 1L)
- 1
- 2
- 3
- 4
將樣本點投影到選取的低維特征向量上,實際使用的是這個結果作為新的特征:
[[-0.82797019]
[ 1.77758033]
[-0.99219749]
[-0.27421042]
[-1.67580142]
[-0.9129491 ]
[ 0.09910944]
[ 1.14457216]
[ 0.43804614]
[ 1.22382056]]
降維之後的樣本:
[[ 2.37125896 2.51870601]
[ 0.60502558 0.60316089]
[ 2.48258429 2.63944242]
[ 1.99587995 2.11159364]
[ 2.9459812 3.14201343]
[ 2.42886391 2.58118069]
[ 1.74281635 1.83713686]
[ 1.03412498 1.06853498]
[ 1.51306018 1.58795783]
[ 0.9804046 1.01027325]]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
降維之後的樣本:
[[ 2.37125896 2.51870601]
[ 0.60502558 0.60316089]
[ 2.48258429 2.63944242]
[ 1.99587995 2.11159364]
[ 2.9459812 3.14201343]
[ 2.42886391 2.58118069]
[ 1.74281635 1.83713686]
[ 1.03412498 1.06853498]
[ 1.51306018 1.58795783]
[ 0.9804046 1.01027325]]
原始樣本:
[[ 2.5 2.4]
[ 0.5 0.7]
[ 2.2 2.9]
[ 1.9 2.2]
[ 3.1 3. ]
[ 2.3 2.7]
[ 2. 1.6]
[ 1. 1.1]
[ 1.5 1.6]
[ 1.1 0.9]]
通過比較可以看出,通過降維之後我們成功地實現了特征從二維降到了一維,降維之後會和原始數據有一定的變化,
我們可以認為通過這種方式消除了一部分的噪聲(當然實際上很可能損失了部分真實信息)。
——————————————-分割線———————————————————
利用sklearn實現PCA
- 參考博文:http://blog.csdn.net/u012162613/article/details/42192293
# 原始數據
data = np.array([[2.5,2.4], [0.5, 0.7], [2.2, 2.9], [1.9, 2.2], [3.1, 3.0], [2.3, 2.7], [2, 1.6], [1, 1.1], [1.5, 1.6], [1.1, 0.9]])
# print data
- 1
- 2
- 3
- 4
# 好吧,就是這麽簡單
from sklearn.decomposition import PCA
pca = PCA(n_components=1)
new_feature = pca.fit_transform(data)
print new_feature
- 1
- 2
- 3
- 4
- 5
[[-0.82797019]
[ 1.77758033]
[-0.99219749]
[-0.27421042]
[-1.67580142]
[-0.9129491 ]
[ 0.09910944]
[ 1.14457216]
[ 0.43804614]
[ 1.22382056]]
轉:PCA的Python實現