1 PCA简述
PCA(Principal Component Analysis)主成分分析算法,在进行图像识别以及高维度数据降维处理中有很强的应用性,算法主要通过计算选择特征值较大的特征向量来对原始数据进行线性变换,不仅可以去除无用的噪声,还能减少计算量。
2 算法过程
2.1 对所有的样本进行中心化;
数据集的每个样本的不同特征减去所有样本对应特征的均值,处理过的不同特征上的数据均值为0。这样处理的好处是可以减少特征之间的差异性,可以使得不同的特征具有相同的尺度,让不同特征对参数的影响程度一致。
2.2 计算样本的协方差矩阵(每列代表一个特征,每行代表一个样本)
2.2.1 计算样本矩阵每一列的均值
2.2.2 样本矩阵的每个样本减去对应列的均值
2.2.3 通过以下公式得到协方差矩阵 (m为样本总数)
2.3 对协方差矩阵进行特征值分解,得到特征值和特征向量;
2.4 取出最大的k个特征值对应的特征向量,组成投影矩阵W;
2.5 对样本集中的每一个样本,都乘以投影矩阵W进行转化,得到降维的数据;
3 Python代码实例
#encoding:GBK
"""
Created on 2019/09/23 16:19:11
@author: Sirius_xuan
"""
'''
基于PCA的图像降维及重构
'''
import numpy as np
import cv2 as cv
#数据中心化
def Z_centered(dataMat):
rows,cols=dataMat.shape
meanVal = np.mean(dataMat, axis=0) # 按列求均值,即求各个特征的均值
meanVal = np.tile(meanVal,(rows,1))
newdata = dataMat-meanVal
return newdata, meanVal
#协方差矩阵
def Cov(dataMat):
meanVal = np.mean(data,0) #压缩行,返回1*cols矩阵,对各列求均值
meanVal = np.tile(meanVal, (rows,1)) #返回rows行的均值矩阵
Z = dataMat - meanVal
Zcov = (1/(rows-1))*Z.T * Z
return Zcov
#最小化降维造成的损失,确定k
def Percentage2n(eigVals, percentage):
sortArray = np.sort(eigVals) # 升序
sortArray = sortArray[-1::-1] # 逆转,即降序
arraySum = sum(sortArray)
tmpSum = 0
num = 0
for i in sortArray:
tmpSum += i
num += 1
if tmpSum >= arraySum * percentage:
return num
#得到最大的k个特征值和特征向量
def EigDV(covMat, p):
D, V = np.linalg.eig(covMat) # 得到特征值和特征向量
k = Percentage2n(D, p) # 确定k值
print("保留99%信息,降维后的特征个数:"+str(k)+"\n")
eigenvalue = np.argsort(D)
K_eigenValue = eigenvalue[-1:-(k+1):-1]
K_eigenVector = V[:,K_eigenValue]
return K_eigenValue, K_eigenVector
#得到降维后的数据
def getlowDataMat(DataMat, K_eigenVector):
return DataMat * K_eigenVector
#重构数据
def Reconstruction(lowDataMat, K_eigenVector, meanVal):
reconDataMat = lowDataMat * K_eigenVector.T + meanVal
return reconDataMat
#PCA算法
def PCA(data, p):
dataMat = np.float32(np.mat(data))
#数据中心化
dataMat, meanVal = Z_centered(dataMat)
#计算协方差矩阵
#covMat = Cov(dataMat)
covMat = np.cov(dataMat, rowvar=0)
#得到最大的k个特征值和特征向量
D, V = EigDV(covMat, p)
#得到降维后的数据
lowDataMat = getlowDataMat(dataMat, V)
#重构数据
reconDataMat = Reconstruction(lowDataMat, V, meanVal)
return reconDataMat
def main():
imagePath = 'D:/desktop/banana.jpg'
image = cv.imread(imagePath)
image=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
rows,cols=image.shape
print("降维前的特征个数:"+str(cols)+"\n")
print(image)
print('----------------------------------------')
reconImage = PCA(image, 0.99)
reconImage = reconImage.astype(np.uint8)
print(reconImage)
cv.imshow('test',reconImage)
cv.waitKey(0)
cv.destroyAllWindows()
if __name__=='__main__':
main()
4 结果
重构前
重构后
5 总结
不难发现,在保留99%信息的情况下,维度由1000降到了44,这大大减小了图像分类时的计算量,重构前和重构后的特征依然明显,读者也可自行调整percentage参数,体验PCA的效果。
PS:喜欢的读者,欢迎随时评论,觉得受益的话,给博主点个赞吧!!