关于PCA算法在机器学习中是经常会用到,特别在维度数比较大的情况下,为了提取主要的维度成分,使用PCA对维度进行降维操作,一方面在保证数据高精确性情况下,另一方面减少维度数量,降低由于维度带来的运算资源的消耗及运算的时间消耗 。PCA能够有效解决因维度带来的灾难。
关于PCA的原理在很多书本、博客等地方都有所介绍,关于原理在这里不再详述。在这里我主要介绍PCA在matlab及python的实现。
关于matlab的实现:
%% 打开文件
fileID = fopen('FIFA2018 Statistics.csv','r','n','utf-8');
%% 加载表头
C = textscan(fileID,'%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s',1,'delimiter',',','EmptyValue',0,'EndOfLine','\r\n');
%% 每次读取数据均为全量读取
%% 加载数据 ,不要 diff_max_login_time 和 shensu_detail_flag 字段
data=textscan(fileID,'%s %s %s %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %s %f %s %s %f %f %f','delimiter',',','EmptyValue',0,'EndOfLine','\r\n');
%% 关闭文件
fclose(fileID);
%% 归一化
data=cat(2,data{5:10})';
[pn,minp,maxp]=premnmx(data);
%% 调动PCA提取个指标的特征,以95%的信息为主
% [p,princ,egenvalue]=princomp(pn');
% p主成分系数
% princ主成分得分
% egenvalue主成分的特征根
[coeff, score, latent, tsquared, explained] = pca(pn');
% coeff 主成分系数,一列一个主成分系数
% score 主成分得分,
% latent 主成分的特征根
% tsquared 是Hotelling的T2检验,Hotelling的T2检验统计量是描述每一测量值与数据中心距离的统计量,用它可以找到数据中的极值点:
% explained 为各主成分的贡献率
%% 求累计贡献率
sum_explained=cumsum(explained,1);
%% 得到累计贡献率>95%的主成分个数
pos=find(sum_explained>95);
%% 根据累计贡献率>95%为准,计算每个uid的分值
contribute = zeros(size(pn,2),1);
for k=1:pos(1)
contribute = explained(k,1)/100.*score(:,k) + contribute;
end
主要成分系数:
特征根:
关于python的实现:
# -*- coding: utf-8 -*-
"""
Created on Tue Jul 31 20:52:42 2018
@author: linxiaojie
"""
import numpy as np
import pandas as pd
'''通过方差的百分比来计算将数据降到多少维是比较合适的,
函数传入的参数是特征值和百分比percentage,返回需要降到的维度数num'''
def eigValPct(eigVals,percentage):
sortArray=np.sort(eigVals) #使用numpy中的sort()对特征值按照从小到大排序
sortArray=sortArray[-1::-1] #特征值从大到小排序
arraySum=np.sum(sortArray) #数据全部的方差arraySum
tempSum=0
num=0
for i in sortArray:
tempSum+=i
num+=1
if tempSum>=arraySum*percentage:
return num
'''pca函数有两个参数,其中dataMat是已经转换成矩阵matrix形式的数据集,列表示特征;
其中的percentage表示取前多少个特征需要达到的方差占比,默认为0.9'''
def pca(dataMat,percentage=0.9):
meanVals=np.mean(dataMat,axis=0) #对每一列求平均值,因为协方差的计算中需要减去均值
meanRemoved=dataMat-meanVals
covMat=np.cov(meanRemoved,rowvar=0) #cov()计算方差
eigVals,eigVects=np.linalg.eig(np.mat(covMat)) #利用numpy中寻找特征值和特征向量的模块linalg中的eig()方法
print(eigVects)
k=eigValPct(eigVals,percentage) #要达到方差的百分比percentage,需要前k个向量
eigValInd=np.argsort(eigVals) #对特征值eigVals从小到大排序
eigValInd=eigValInd[:-(k+1):-1] #从排好序的特征值,从后往前取k个,这样就实现了特征值的从大到小排列
redEigVects=eigVects[:,eigValInd] #返回排序后特征值对应的特征向量redEigVects(主成分)
lowDDataMat=meanRemoved*redEigVects #将原始数据投影到主成分上得到新的低维数据lowDDataMat
reconMat=(lowDDataMat*redEigVects.T) + meanVals #得到重构数据reconMat
return lowDDataMat,reconMat, eigVals, eigVects
# 对目标进行归一化操作,其中归一化的范围为[-1,1]之间,其中一列一个样本
def np_premnmx(data_array):
min_1=np.min(data_array, axis=1)[:,np.newaxis] # 按行求最小值
max_1=np.max(data_array, axis=1)[:,np.newaxis] # 按行求最大值
an=2*(data_array-min_1)/(max_1-min_1)-1 # 矩阵点除
return an,min_1,max_1
if __name__ == "__main__":
df = pd.read_csv('FIFA2018 Statistics.csv')
values = df.values
# 转换为numpy的array
source_data = values[:,4:10].astype('float32').T
# 对矩阵按列进行归一化
dataMat, min_1,max_1 = np_premnmx(source_data)
# 进行pca分析
lowDDataMat,reconMat, eigVals, eigVects = pca(dataMat.T,percentage=0.95)
主要成分系数:
特征根: