一、首先先問一個問題:為什麼要進行降維操作呢?
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB9kMJpXT4lkeNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzETN2QDN0ATMwEDNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
降維的主要方法有:
二、主成分分析PCA
2.PCA的python 實作過程
有人會問為什麼要去均值呢?
我們進行PCA降維的主要目的是為了得到方差最大的前N個特征,為了減少計算量,我們第一步就将資料所特征的均值變為0,來達到取出均值的目的。
在學習的過程中首先我們根據算法的實作過程一步步進行代碼實作,然後再封裝成函數的形式,這樣就有助于調用
代碼實作過程如下所示
首先先導入資料集以及需要用到的包
#導入包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#導入資料
testSet = pd.read_table('testSet.txt',header=None)
testSet.head()#該資料集是一個隻有兩個特征的資料
#可以将其進行可視化展示
#檢視資料的分布
plt.scatter(testSet.iloc[:,0],testSet.iloc[:,1],marker='o',c='b')
plt.show()
結果如下:
0 1
0 10.235186 11.321997
1 10.122339 11.810993
2 9.190236 8.904943
3 9.306371 9.847394
4 8.330131 8.340352
開始實作pca操作
(1)去除均值
dataset=testSet #為了不改變原始資料,一般可以先複制一個新的資料集
meanval=dataset.mean(0)
new_data=dataset-meanval
new_data.head()
結果如下:
0 1
0 1.171250 2.225995
1 1.058403 2.714991
2 0.126300 -0.191059
3 0.242435 0.751392
4 -0.733805 -0.755650
(2)計算協方差矩陣
#np.cov()函數用于直接生成協方差,np.mat()将結果轉化為矩陣的形式
covmat=np.mat(np.cov(new_data,rowvar=0))
covmat
結果:
matrix([[ 1.05198368, 1.1246314 ],
[ 1.1246314 , 2.21166499]])
(3)計算協方差矩陣的特征值和特征向量
#np.linalg.eig()函數用來求特征值和特征向量
eigvals,eigvects=np.linalg.eig(covmat)
print(eigvals)
print('***'*3)
print(eigvects)
結果為
[ 0.36651371 2.89713496]
*********
[[-0.85389096 -0.52045195]
[ 0.52045195 -0.85389096]]
(4)将特征值進行從大到小排序
#對特征值進行排序
# eigvaind=np.argsort(eigvals)
#預設是按照從小到大排序的,我們需要從大到小進行排序
# eigvaind
# 方法二:按照降序排序(前面加上-号就是按照降序排序了)
eigvaind=np.argsort(-eigvals)
eigvaind
取出前面的最大的N個特征值的索引
N=1
eigvaind=eigvaind[:N]
eigvaind
結果為:
array([1], dtype=int64)
(5)保留前N個特征值的對應的特征向量
#取出特征向量
redEigvects=eigvects[:,eigvaind]
(6)将資料換到N個特征向量組成的新空間中
将原始資料構成的矩陣乘以取出的N個特征向量組成的矩陣就得到降維後的心得資料集
newdatamat=np.mat(meanremoved)*redEigvects
#注意這裡需要将資料集轉化成矩陣的形式才能夠進行矩陣相乘
newdatamat[:5]
結果:
matrix([[-2.51033597],
[-2.86915379],
[ 0.09741085],
[-0.76778222],
[ 1.02715333]])
以上是對實作過程進行一步步的實作過程,在實際的程式設計 過程中往往這樣是不太現實的哈哈,我們為了更加友善,我們把以上實作過程封裝成一個函數,友善調用。
封裝函數如下所示:
#對于以上的步驟我們可以将其封裝成一個函數
def pca(dataset,N=99999):
meanval=dataset.mean(0)
meanremoved=dataset-meanval
covmat=np.mat(np.cov(meanremoved,rowvar=0))#計算協方差矩陣
eigvals,eigvects=np.linalg.eig(covmat)#計算特征值 和特征向量
eigvaind=np.argsort(-eigvals)#按照降序進行排序特征值的索引值
reigvaind=eigvaind[0]
redeigvect=eigvects[:,reigvaind]#擷取特征向量
newdataset=np.mat(meanremoved)*redeigvect#生成降維後的新的資料集
reconmat=(newdataset*(redeigvect.T))+np.mat(meanval)#表示生成和原資料集相似的資料集
return newdataset,reconmat
#調用函數
newdataset,reconmat=pca(testSet,N=1)
print(newdataset[:5])
print('***'*6)
print(reconmat)
輸出結果如下所示:
[[-2.51033597]
[-2.86915379]
[ 0.09741085]
[-0.76778222]
[ 1.02715333]]
******************
[[ 10.37044569 11.23955536]
[ 10.55719313 11.54594665]
[ 9.01323877 9.01282393]
...,
[ 9.32502753 9.52436704]
[ 9.0946364 9.14637075]
[ 9.16271152 9.2580597 ]]
三、下面給出以個小的案例-PCA對半導體資料進行降維
(1)導入資料
secom = pd.read_table('secom.data',sep = ' ',header = None)
secom.head()
secom.shape
結果:
(1567, 590)
這是一個資料特征比較多的資料集
為了不改變原始資料集,我們先copy()一個資料集
secom1=secom.copy()
(2)遇到比較大的資料我們首先需要進行資料處理,比如删除一些缺失值過多的列
np.isnan(secom1.iloc[:,0]).mean()#為了計算一列資料的缺失比率
結果為:
0.0038289725590299937
下面用一個循環來計算資料集中特征列的缺失比率
#1.删除缺失值大于等于80%的特征
secom1=secom.copy()
nanInd = []
for i in range(secom1.shape[1]):
nan = np.isnan(secom1.iloc[:,i]).mean()
if nan*100>=80:
print(f'第{i}列的缺失值比例為{round(nan*100,2)}%')#round()函數
nanInd.append(i)
結果:
第85列的缺失值比例為85.58%
第157列的缺失值比例為91.19%
第158列的缺失值比例為91.19%
第220列的缺失值比例為85.58%
第292列的缺失值比例為91.19%
第293列的缺失值比例為91.19%
第358列的缺失值比例為85.58%
第492列的缺失值比例為85.58%
其中 nanInd種存儲的是缺失值超過80%的列,我們需要把這些列删除
secom1.drop(secom1.columns[nanInd],axis=1,inplace=True)
secom1.shape
結果:
(1567, 582)
對于有的缺失值比較少的直接删除會影響結果,我們可以填補缺失值的方法是資料變得完整。
#2.缺失值比例小于80%的特征用均值填補缺失值
for i in secom1.columns:
secom1[i].fillna(secom1[i].mean(),inplace = True)
為了防止出問題,我們檢查一下還是否存在缺失值
(secom1.isnull()).sum().value_counts()
資料的基本處理已經完成了,現在我們開始PCA的實作過程了。和上面的過程是一模一樣的,自己動動手把,很簡單的。