PCA底层原理和python实现(详解)

**本文章才用的是鸢尾花数据进行检测,对其进行降维操作,通过使用PCA 对数据的特征进行降维,从而选择出合适的属性值**
import numpy as np

import matplotlib.pyplot as plt
%matplotlib inline

# decomposition:降解
# 降解,化学变化降解之后得到数据,原来的数据不太一样
# 属性变了
# pca将数据属性变少,少量的数据代表原来的比较多的数据
from sklearn.decomposition import PCA

from sklearn.linear_model import LogisticRegression

from sklearn import datasets
from sklearn.model_selection import train_test_split
X,y = datasets.load_iris(True)
# 降维  找出最合适的两个属性
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
X_pca[:10]
array([[-2.68412563,  0.31939725],
       [-2.71414169, -0.17700123],
       [-2.88899057, -0.14494943],
       [-2.74534286, -0.31829898],
       [-2.72871654,  0.32675451],
       [-2.28085963,  0.74133045],
       [-2.82053775, -0.08946138],
       [-2.62614497,  0.16338496],
       [-2.88638273, -0.57831175],
       [-2.6727558 , -0.11377425]])

可以看出最后两个属性对于元数据来说最重要,下面我们看他是如何计算出来的

PCA原理

1、去中心化

B = X - X.mean(axis = 0)
B[:5]
array([[-0.74333333,  0.44266667, -2.358     , -0.99933333],
       [-0.94333333, -0.05733333, -2.358     , -0.99933333],
       [-1.14333333,  0.14266667, -2.458     , -0.99933333],
       [-1.24333333,  0.04266667, -2.258     , -0.99933333],
       [-0.84333333,  0.54266667, -2.358     , -0.99933333]])

2、协方差的求解

# 方差是协方差特殊形式
# 协方差矩阵 下面两种方法一样
V = np.cov(B,rowvar=False,bias = True)
# V = np.cov(B.T,bias = True)

3、协方差矩阵的特征值和特征向量
这里使用numpy中的linalg中内置方法eig来求解举证的特征值和特征向量!!

# 特征值和特征向量矩阵的概念
eigen,ev = np.linalg.eig(V)
display(eigen,ev)
array([4.20005343, 0.24105294, 0.0776881 , 0.02367619])

array([[ 0.36138659, -0.65658877, -0.58202985,  0.31548719],
       [-0.08452251, -0.73016143,  0.59791083, -0.3197231 ],
       [ 0.85667061,  0.17337266,  0.07623608, -0.47983899],
       [ 0.3582892 ,  0.07548102,  0.54583143,  0.75365743]])

4、降维标准

#  百分比,计算各特征值,占权重,累加可以
cond = (eigen/eigen.sum()).cumsum() >= 0.98

index = cond.argmax()

vector = ev[:,:index + 1]

5、进行矩阵运算

pca_result = B.dot(vector)
# pca_result 这个结果可以看出,他底层的正负值发生了一定的改变,这一步是为了让符号对应,这个是剖析源代码得出来的!欣然接受就可以哈哈!!
pca_result[:,1::2]*=-1
pca_result[:5]
array([[-2.68412563,  0.31939725, -0.02791483],
       [-2.71414169, -0.17700123, -0.21046427],
       [-2.88899057, -0.14494943,  0.01790026],
       [-2.74534286, -0.31829898,  0.03155937],
       [-2.72871654,  0.32675451,  0.09007924]])
X_pca[:5]

可以看出通过我们手动计算之后和它用算法的得出的结果保持一致,这就很完美啦,主要就是进行了以上几个步骤
下面是一个小小的拓展:
pca = PCA(n_components=2,whiten=True)
X_pca = pca.fit_transform(X)
这里会有另外一个参数whiten=True表示是否进行标准化,如果等于True就会在原来的基础上使用下面的标准化操作即可,也是很方便,容易理解

6、标准化

pca_result2 = (pca_result -pca_result.mean(axis = 0))/pca_result.std(axis = 0)
pca_result2[:5]
array([[-1.30971087,  0.65054141, -0.10015155],
       [-1.32435711, -0.36051227, -0.75509418],
       [-1.40967409, -0.29522986,  0.06422173],
       [-1.33958163, -0.64830449,  0.11322729],
       [-1.33146886,  0.66552653,  0.32318222]])

验证降维的数据,准确

*这里是采用的逻辑斯蒂回归算法进行的验证,准确率还是很高的~~~~*

import warnings
warnings.filterwarnings('ignore')
# 降维的数据,准确率是93%
lr = LogisticRegression()

X_train,X_test,y_train,y_test = train_test_split(X_pca,y,test_size = 0.2,random_state = 1024)

lr.fit(X_train,y_train)

lr.score(X_test,y_test)
0.9
X.shape
(150, 4)
# 原数据准确率是96%
lr = LogisticRegression()

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.2,random_state = 1024)

lr.fit(X_train,y_train)

lr.score(X_test,y_test)
0.9666666666666667
# 原数据准确率是96%
lr = LogisticRegression()

X_train,X_test,y_train,y_test = train_test_split(pca_result2,y,test_size = 0.2,random_state = 1024)

lr.fit(X_train,y_train)

lr.score(X_test,y_test)
0.8333333333333334
# 原数据准确率是96%
lr = LogisticRegression()

X_train,X_test,y_train,y_test = train_test_split(X_pca,y,test_size = 0.2,random_state = 1024)

lr.fit(X_train,y_train)

lr.score(X_test,y_test)
0.9

猜你喜欢

转载自blog.csdn.net/qq_42166308/article/details/103375418