一、PCA的原理
import numpy as np
from sklearn import datasets
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
X,y = datasets.load_iris(True)
pca = PCA(n_components=0.95,whiten=True) # whiten 白化理,
#n_components=0.95--保留特征的数量
标准化(方差是1,平均值是0)正太分布
X_pca = pca.fit_transform(X)
X_pca.shape
display(X_pca.std(axis = 0))
display(X_pca.mean(axis = 0))
array([0.99666109, 0.99666109])
array([-1.42108547e-15, -1.81188398e-15])
自己写代码,实现,PCA
矩阵的特征值,和特征向量
线性代数中的概念A
第一步,去中心化
# 特征,将每个特征的平均值求解,
# 数据有四个特征,返回四个数
A = X - X.mean(axis = 0)
第二步,求解协方差
# 协方差,方差
# 方差是协方差的一种特殊形式
# 圆是椭圆的一种特例
# 方差表示属性内在的关系
# 协方差,两个属性,进行对比
# 学校里,吴同学,受女同学的欢迎程度(属性)和吴同学的猥琐程度(另一个属性) ---->协方差
# rowvar row 行 = True默认计算行和行的协方差
B = np.cov(A,rowvar=False)#计算列,二维数组中:行表示样本,列表示的属性(excel,pandas、mysql)
# 4 * 4 = 16
B
array([[ 0.68569351, -0.042434 , 1.27431544, 0.51627069],
[-0.042434 , 0.18997942, -0.32965638, -0.12163937],
[ 1.27431544, -0.32965638, 3.11627785, 1.2956094 ],
[ 0.51627069, -0.12163937, 1.2956094 , 0.58100626]])
# 方差计算公式
np.var(X[:,0])/149*150
0.6856935123042507
((X[:,0] - X[:,0].mean())**2).sum()/149
0.6856935123042507
第三步,进行特征值和特征向量的计算
value,vector = np.linalg.eigh(B)
display(value,vector)
array([0.02383509, 0.0782095 , 0.24267075, 4.22824171])
array([[ 0.31548719, 0.58202985, 0.65658877, -0.36138659],
[-0.3197231 , -0.59791083, 0.73016143, 0.08452251],
[-0.47983899, -0.07623608, -0.17337266, -0.85667061],
[ 0.75365743, -0.54583143, -0.07548102, -0.3582892 ]])
第四步,根据特征值的权重,筛选特征向量
C = vector[:,2:]
v = value[::-1]
v
array([4.22824171, 0.24267075, 0.0782095 , 0.02383509])
# 累加和
v.cumsum()/v.sum()
array([0.92461872, 0.97768521, 0.99478782, 1. ])
pca = PCA(n_components=0.93)#下限,只要大于,就可以
pca.fit_transform(X).shape
(150, 2)
第五步,进行矩阵运算
D = A.dot(C)
r,c = D.shape
coef = [-1 if (i+1)%2 == 0 else 1 for i in range(c)]#偶数列,乘了负一
E = (D*coef)[:,[1,0]]
E[:5]
array([[-2.68412563, 0.31939725],
[-2.71414169, -0.17700123],
[-2.88899057, -0.14494943],
[-2.74534286, -0.31829898],
[-2.72871654, 0.32675451]])
X_pca[:5]
array([[-1.30533786, 0.64836932],
[-1.31993521, -0.35930856],
[-1.40496732, -0.29424412],
[-1.33510889, -0.64613986],
[-1.32702321, 0.6633044 ]])
第六步,进行标准化
F = (E - E.mean(axis = 0))/E.std(axis = 0)
F[:5]
array([[-1.30971087, 0.65054141],
[-1.32435711, -0.36051227],
[-1.40967409, -0.29522986],
[-1.33958163, -0.64830449],
[-1.33146886, 0.66552653]])
X_pca[:5]
array([[-1.30533786, 0.64836932],
[-1.31993521, -0.35930856],
[-1.40496732, -0.29424412],
[-1.33510889, -0.64613986],
[-1.32702321, 0.6633044 ]])
二、代码实例
import numpy as np
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
# 降解:由多变少,化繁为简
# principle component analysis 主要成分
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
X,y = datasets.load_iris(True)
# 搬家,丢掉很多,没有的东西!
X.shape#150样本,4个属性,4个属性,必然是,有的重要,有的不重要,希望去掉的不重要。
(150, 4)
# n_components保留几个最重要特征
# whiten 白色,标准化
# n_components=0.9 90%重要性的特征保留下来(一个特征50%,另一个41%)
pca = PCA(n_components=0.98,whiten = False)
'''y : None
Ignored variable.'''
# 为了以后,可以兼容,后面版本,改进,加入y
# sklearn 写代码,深思熟虑,保留了y位置,现在,没用!
pca.fit(X)
X_pca = pca.transform(X)#变换
# 降维,样本数量150会变化吗?
X_pca.shape# 经过PCA降维,发现数据由原来的150*4 ------> 150*2
(150, 3)
没有降维的数据,进行训练预测
knn = KNeighborsClassifier(n_neighbors=5)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.2,random_state = 1024)
knn.fit(X_train,y_train)
knn.score(X_test,y_test)
0.9666666666666667
降维的数据,效果
knn = KNeighborsClassifier(n_neighbors=5)
X_train,X_test,y_train,y_test = train_test_split(X_pca,y,test_size = 0.2,random_state = 1024)
knn.fit(X_train,y_train)
knn.score(X_test,y_test)
0.9666666666666667