机器学习实验:主成分分析法PCA的代码实现

机器学习实验:主成分分析法PCA的实现

主成分分析是最常用的线性降维方法,它的目标是通过某种线性投影,将高维的数据映射到低维的空间中,并期望在所投影的维度上数据的方差最大,以此使用较少的维度,同时保留较多原数据的维度。

代码实现:

  1. 导入相关库
import sys
defaultencoding = 'utf-8'
from math import *
import random as rd
import numpy as np
  1. 零均值化矩阵
"""
矩阵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
  1. 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
  1. 通过百分比确定降维后的维数
"""通过方差百分比来确定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 
  1. 调用函数
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]]
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值