????????PCA降維,一般是用于數據分析和機器學習。它的作用是把一個高維的數據在保留最大信息量的前提下降低到一個低維的空間,從而使我們能夠提取數據的主要特征分量,從而得到對數據影響最大的主成分,便于我們對數據進行分析等后續(xù)操作。
????????例如,在機器學習中,當你想跟據一個數據集來進行預測工作時,往往要采用特征構建、不同特征相乘、相加等操作,來擴建特征,所以,當數據處理完畢后,每個樣本往往會有很多個特征,但是,如果把所有數據全部喂入模型,可能會導致糟糕的結果。在高維數據集中,往往只有部分特征有良好的預測能力,很多特征純粹是噪音(沒有預測能力),很多特征彼此之間也可能高度相關,這些因素會降低模型的預測精度,訓練模型的時間也更長。降低數據集的維度在某種程度上能解決這些問題,這時候就用到了PCA降維。
? ? ? ? 假設原始數據集的特征有500個,通過PCA降維,降到了400,那么我們就可以用降維后得到的這400個特征代替原始數據集的那500個,此時再喂給模型,那么模型的預測能力相比之前會有所提升。但要明白一點的是,降維后得到的這400個特征是新的特征,是原始數據集在高維空間某一平面上的投影,能夠反映原特征提供的大部分信息,并不是指在原來的500個中篩選400個特征。
PCA降維的一般步驟為:
1.將原始數據進行標準化(一般是去均值,如果特征在不同的數量級上,則還要將其除以標準差)
2.計算標準化數據集的協(xié)方差矩陣
3.計算協(xié)方差矩陣的特征值和特征向量
4.保留最重要(特征值最大)的前k個特征(k就表示降維后的維度)
5.找到這k個特征值對應的特征向量
6.將標準化數據集乘以該k個特征向量,得到降維后的結果
具體步驟如下:
1.去均值:
????????其中,為標準化后的矩陣,
為矩陣A的均值。
2.求標準化數據集的協(xié)方差矩陣:
3.計算協(xié)方差矩陣的特征值和特征向量。設數λ和n維非0列向量x滿足下式:
????????則λ為C的特征值,x稱為C的對應于特征值λ的特征向量。C為數據集的協(xié)方差矩陣。
4.保留最重要的前k個特征。k即為你想降維到的維數。
5.找到這k個特征值對應的特征向量
6.將標準化數據集乘以這k個特征向量,得到降維后的結果
????????上式中,表示上述的k個特征值分別對應的特征向量組成的矩陣。
實現(xiàn)PCA降維,一般有兩種方法:
首先先來解釋一下代碼中用到的數據集:
????????在這兩個代碼中,用的是sklean庫中自帶的iris(鳶尾花)數據集。iris數據集包含150個樣本,每個樣本包含四個屬性特征(花萼長度、花萼寬度、花瓣長度、花瓣寬度)和一個類別標簽(分別用0、1、2表示山鳶尾、變色鳶尾和維吉尼亞鳶尾)。
data = load_iris()
y = data.target
x = data.data
y就表示數據集中的類別標簽,x表示數據集中的屬性數據。因為鳶尾花類別分為三類,所以我們降維后,要跟據y的值,分別對這三類數據點進行繪圖。
第一種,就是依照上面PCA的步驟,通過矩陣運算,最終得到降維后的結果:
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
def pca(dataMat, topNfeat):
meanVals = np.mean(dataMat, axis=0)
meanRemoved = dataMat - meanVals # 標準化(去均值)
covMat = np.cov(meanRemoved, rowvar=False)
eigVals, eigVets = np.linalg.eig(np.mat(covMat)) # 計算矩陣的特征值和特征向量
eigValInd = np.argsort(eigVals) # 將特征值從小到大排序,返回的是特征值對應的數組里的下標
eigValInd = eigValInd[:-(topNfeat + 1):-1] # 保留最大的前K個特征值
redEigVects = eigVets[:, eigValInd] # 對應的特征向量
lowDDatMat = meanRemoved * redEigVects # 將數據轉換到低維新空間
# reconMat = (lowDDatMat * redEigVects.T) + meanVals # 還原原始數據
return lowDDatMat
def plotPCA(lowMat):
reconArr = np.array(lowMat)
red_x, red_y = [], []
blue_x, blue_y = [], []
green_x, green_y = [], []
for i in range(len(reconArr)):
if y[i] == 0:
red_x.append(reconArr[i][0])
red_y.append(reconArr[i][1])
elif y[i] == 1:
blue_x.append(reconArr[i][0])
blue_y.append(reconArr[i][1])
else:
green_x.append(reconArr[i][0])
green_y.append(reconArr[i][1])
plt.scatter(red_x, red_y, c='r', marker='x')
plt.scatter(blue_x, blue_y, c='b', marker='D')
plt.scatter(green_x, green_y, c='g', marker='.')
plt.show()
if __name__ == '__main__':
data = load_iris()
y = data.target
x = data.data
matx = np.mat(x)
lowDMat = pca(matx, 2)
plotPCA(lowDMat)
第二種,是在sklearn庫中調用PCA算法來實現(xiàn):
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA # 加載PCA算法包
from sklearn.datasets import load_iris
import numpy as np
data = load_iris()
y = data.target
x = data.data
pca = PCA(n_components=2) # 加載PCA算法,設置降維后主成分數目為2
reduced_x = pca.fit_transform(x) # 對樣本進行降維
# reduced_x = np.dot(reduced_x, pca.components_) + pca.mean_ # 還原數據
red_x, red_y = [], []
blue_x, blue_y = [], []
green_x, green_y = [], []
# print(reduced_x)
for i in range(len(reduced_x)):
if y[i] == 0:
red_x.append(reduced_x[i][0])
red_y.append(reduced_x[i][1])
elif y[i] == 1:
blue_x.append(reduced_x[i][0])
blue_y.append(reduced_x[i][1])
else:
green_x.append(reduced_x[i][0])
green_y.append(reduced_x[i][1])
plt.scatter(red_x, red_y, c='r', marker='x')
plt.scatter(blue_x, blue_y, c='b', marker='D')
plt.scatter(green_x, green_y, c='g', marker='.')
plt.show()
????????在第二個代碼中,值得一說的是fit_transform()這個函數,它其實就是fit()和transform()這兩個函數的結合,相當于先調用fit()再調用transform()。fit()和transform()這兩個函數在sklearn庫中經常出現(xiàn),fit()函數可以理解為求傳入的數據集的一些固有的屬性(如方差、均值等等),相當于一個訓練過程,而transform()函數,可以理解為對訓練后的數據集進行相應的操作(如歸一化、降維等等)。在不同的模塊中,這兩個函數的具體實現(xiàn)也不一樣,比如在PCA模塊里,fit()相當于去均值,transform()則相當于降維。
這兩種代碼運行后,生成的圖像如下(圖一為第一種代碼,圖二為第二種代碼):
圖一
圖二
????????可以看到,第一種代碼畫出的圖像與第二種代碼畫出的圖像關于y=0這條直線對稱,雖然不清楚這是什么原因(后續(xù)有空的話我會去找找原因),但是這并不影響降維的結果。
降維前的數據(部分):? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
降維后的數據(部分):
?
? ? ? ?
????????所以,此時我們使用降維后的二維數據集就可以用來表示降維前四維數據集的大部分信息。
? ? ? ? 降維后得到的數據可以通過逆操作來進行數據集的還原,具體原理就不過多解釋,具體操作代碼的話我已在代碼的注釋里面寫出,但是重建出來的數據會和原始數據有一定的誤差(如下圖)
????????原因的話你可以這樣理解:我們的原始數據為四維空間,現(xiàn)在用PCA降維到二維空間,則保留數據投影方差最大的兩個軸向,因此舍棄掉了另外兩個相對不重要的特征軸,從而造成了一定的信息丟失,所以會產生重構誤差。文章來源:http://www.zghlxwxcb.cn/news/detail-416693.html
最后,希望大家能指出我的錯誤或者不足,我一定及時改正。文章來源地址http://www.zghlxwxcb.cn/news/detail-416693.html
到了這里,關于Python PCA(主成分分析法)降維的兩種實現(xiàn)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!