机器学习实验:主成分分析法PCA的实现
主成分分析是最常用的线性降维方法,它的目标是通过某种线性投影,将高维的数据映射到低维的空间中,并期望在所投影的维度上数据的方差最大,以此使用较少的维度,同时保留较多原数据的维度。
代码实现:
- 导入相关库
import sys
defaultencoding = 'utf-8'
from math import *
import random as rd
import numpy as np
- 零均值化矩阵
"""
矩阵dataMat为原始数据集,dataMat中每一行代表一个样本,每一列代表同一个特征
零均值化就是求每一列的平均值,然后该列上的所有数都减去这个均值,
也就是说,这里的零均值化是对每一个特征而言的,零均值化后没个特征的均值变为0
numpy.mean()用来求均值,axis=0表示按列求均值
该函数返回两个变量,newData是零均值化后的数据,meanVal是每个特征的均值,是给后面重构数据用的。
"""
def zeroMean(dataMat):
#按列求平均值,即求各个特征的均值
meanVal = np.mean(dataMat,axis = 0) #计算该轴上的统计值(0为列,1为行)
newData = dataMat - meanVal
return newData,meanVal
- PCA算法实现
def pca(dataMat,percent=0.19):
'''求协方差矩阵
若rowvar=0,说明传入的数据一行代表一个样本,若非0
说明传入的数据一列代表一个样本。因为newData每一行代表一个样本,所以将rowvar设置为0 '''
"""求协方差矩阵,numpy中的cov函数用于求协方差矩阵,参数rowvar很重要,
若rowvar=0,说明传入的数据一行代表一个样本,若非0,说明传入的数据一列代表一个样本。
因为newData每一行代表一个样本,所以将rowval设置为0
covMat即所求的协方差矩阵
"""
newData,meanVal=zeroMean(dataMat)
covMat=np.cov(newData,rowvar=0)
"""numpy中的线性代数模块linalg中的eig函数用来计算特征向量 ,np.mat()将列表矩阵化
eigVals存放特征值,行向量
eigVects存放特征向量,每一列代表一个特征向量
特征值和特征向量是一一对应的"""
eigVals,eigVects = np.linalg.eig(np.mat(covMat))
n=percentage2n(eigVals,percent) #要达到percent的方差百分比,需要前n个特征向量
print(str(n) + u'vectors')
#u表示unicode字符串,通常不带u,但是中文,必须标明所需编码,否则会出现乱码
#print(str(n))
"""保留主要成分:即保留值比较大的前n个特征
前面已经得到了特征向量eigVals,假设里面有m个特征值,我们可以对其排序,排在前面的n个特征值
所对应的特征向量就是我们要保留的,它们组成了新的特征空间的一组基n_eigVect,
将零均值化后的数据乘以n_eigVect就可以得到降维后的数据lowDDataMat
reconMat是重构的数据
"""
eigValIndice=np.argsort(eigVals) #对特征值从小到大排序
n_eigValIndice=eigValIndice[-1:-(n+1):-1] #最大的n个特征值的下标
n_eigVect=eigVects[:,n_eigValIndice] #最大的n个特征值对应的特征向量
lowDDataMat=newData * n_eigVect #低维特征空间的数据
reconMat=(lowDDataMat * n_eigVect.T) + meanVal #重构数据
return reconMat,lowDDataMat,n
- 通过百分比确定降维后的维数
"""通过方差百分比来确定n
函数传入参数是percentage和特征向量,然后根据百分比确定n
"""
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
- 调用函数
data = np.random.randint(1,20,size = (6,8))
print(data) #输出原始数据,n=6,m=8,n代表样本,m代表特征
fin = pca(data,0.9)
mat =fin[1]
print(mat)
输出结果:
[[ 8 1 7 14 16 3 17 10]
[ 3 17 17 2 8 6 9 18]
[ 3 19 9 7 11 8 10 17]
[12 14 12 2 16 6 11 5]
[ 5 12 2 2 10 2 8 7]
[17 17 12 7 7 1 8 19]]
4vectors
[[-15.80265905 6.08753142 -3.85979554 0.67332485]
[ 9.98073794 -0.47983651 -4.73390654 3.27243541]
[ 5.69434533 -1.28182868 -6.06741985 -0.81275338]
[ -3.02227799 -4.47908086 6.69017732 6.53634951]
[ -4.03128265 -8.3523634 1.44643482 -6.40350074]
[ 7.18113641 8.50557802 6.5245098 -3.26585565]]