PCA的python实现
原理部分:
https://blog.csdn.net/ws_developer/article/details/81634059这篇博客介绍的很详细,让我在本子上记了不少东西。
实现:
1.直接调用函数
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 3 10:10:52 2019
@author: Administrator
"""
from sklearn import datasets,decomposition
import matplotlib.pyplot as plt
#Data
digits=datasets.load_digits()
x=digits.data
y=digits.target
#Model
pca=decomposition.PCA()
pca.fit(x)
plt.figure()
plt.plot(pca.explained_variance_,'k')
plt.xlabel('n_components',fontsize=16)
plt.ylabel('explained_variance',fontsize=16)
plt.show()
2.手动实现PCA
# -*- coding: utf-8 -*-
"""
PCA
利用 Numpy Pandas Matplotlib 实现&可视化
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
digits=datasets.load_digits()
x=digits.data
y=digits.target
class DimensionValueError(ValueError):
'''定义异常类'''
pass
class PCA(object):
'''定义PCA类'''
def __init__(self,x,n_components=None):
"""x的数据结构应为ndarray"""
self.x=x
self.dimension=x.shape[1]#维数为列向量的个数
if n_components and n_components>=self.dimension:
raise DimensionValueError("n_components error")
self.n_components=n_components
'''(1.将原始数据按列组成N行M列的矩阵X)'''
def cov(self):
'''3.求x的协方差矩阵x_cov'''
x_T=np.transpose(self.x)#矩阵转置
print("矩阵x的转置x_T:")
x_cov=np.cov(x_T)#协方差矩阵
print("矩阵x的协方差矩阵x_cov:")
return x_cov
def get_feature(self):
'''4.求协方差矩阵C的特征值a和特征向量b,并且返回过渡矩阵P'''
from numpy import linalg as LA #使用前单独import一下
x_cov=self.cov()
a,b=np.linalg.eig(x_cov)#a是特征值,b是a对应的特征向量
print("特征值a:")
print(a)
print("特征值b:")
print(b)
m=a.shape[0]#计算特征值/特征向量个数
c=np.hstack((a.reshape(m,1),b))#沿着水平方向将数组堆叠起来
c_df=pd.DataFrame(c)
c_df_sort=c_df.sort_values(0,ascending=False)#将特征向量按对应的特征值大小从上到下安航排列成矩阵
print("得到了排好序的特征向量矩阵c_df_sort为:")
print(c_df_sort)
print("以上是得到的排好序的特征向量矩阵c_df_sort")
return c_df_sort
def explained_varience_(self):
c_df_sort=self.get_feature()
return c_df_sort.values[:,0]
def paint_varience_(self):
'''将方差可视化'''
explained_varience_=self.explained_varience_()
plt.figure()
plt.plot(explained_varience_,'k')
plt.xlabel('n_components',fontsize=16)
plt.ylabel('explained_varience_',fontsize=16)
plt.show()
def reduce_dimension(self):
'''6.指定维度降维和根据方差贡献率自动降维'''
c_df_sort=self.get_feature() #获得过渡矩阵P
varience= self.explained_varience_()
print("varience:")
print(varience)
#指定降维维数
if self.n_components:
p=c_df_sort.values[0:self.n_components,1:]
y=np.dot(p,np.transpose(self.x))#做矩阵乘法Y=PX ,即矩阵叉乘
return np.transpose(y)
#根据方差贡献率自动降维
varience_sum=sum(varience)#方差总和
varience_radio=varience/varience_sum#每个方差所占方差总和的比例/
varience_contribution=0#初始化方差贡献率=0,加下来计算
for R in range(self.dimension):
varience_contribution+=varience_radio[R]#前R个方差贡献度之和
if varience_contribution>=0.99:
break
p=c_df_sort.values[0:R+1,1:]#取前R个特征向量
y=np.dot(p,np.transpose(self.x))#矩阵叉乘得到降维后的结果矩阵Y=PX
return np.transpose(y)
if __name__=='__main__':
pca=PCA(x)
y=pca.reduce_dimension()
pca.paint_varience_()
主要使用了线性代数的知识。
1的结果
2的结果