当数据维数很高的时候,我们可以用PCA降维,但是降维前通常我们要对数据进行标准化,为什么要这样做?这有什么好处?
4个回答
PCA(主成分分析)所对应的数学理论是SVD(矩阵的奇异值分解)。而奇异值分解本身是完全不需要对矩阵中的元素做标准化或者去中心化的。
但是对于机器学习,我们通常会对矩阵(也就是数据)的每一列先进行标准化。
PCA通常是用于高维数据的降维,它可以将原来高维的数据投影到某个低维的空间上并使得其方差尽量大。如果数据其中某一特征(矩阵的某一列)的数值特别大,那么它在整个误差计算的比重上就很大,那么可以想象在投影到低维空间之后,为了使低秩分解逼近原数据,整个投影会去努力逼近最大的那一个特征,而忽略数值比较小的特征。因为在建模前我们并不知道每个特征的重要性,这很可能导致了大量的信息缺失。为了“公平”起见,防止过分捕捉某些数值大的特征,我们会对每个特征先进行标准化处理,使得它们的大小都在相同的范围内,然后再进行PCA。
此外,从计算的角度讲,PCA前对数据标准化还有另外一个好处。因为PCA通常是数值近似分解,而非求特征值、奇异值得到解析解,所以当我们使用梯度下降等算法进行PCA的时候,我们最好先要对数据进行标准化,这是有利于梯度下降法的收敛。
SofaSofa数据科学社区DS面试题库 DS面经没做标准化的PCA是找covariance matrix的eigenvector,标准化后的PCA是找correlation matrix的eigenvector。如清风说的第一点,如果没有做标准化,eigenvector会偏向方差最大的变量,偏离理论上的最佳值。
举例说明。假设一个2维Gaussian,correlation matrix是[1 0.4;0.4 1], $std(x_1)=10, std(x_2)=1$。理论上最佳的分解向量是椭圆的长轴,如果没有做标准化,PCA算出的向量和长轴会有偏差。标准化后偏差会减到很小。
#standarization of PCA
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
np.set_printoptions(precision=3)
np.random.seed(0)
n=1000000
mu=[0,0]
corr=np.array([[1.,.4],[.4,1.]])
std_vector=[10.,1]
A_ori=np.random.multivariate_normal(mu,corr,n)
A_scaled=np.matmul(A_ori,np.diag(std_vector))
scaler = StandardScaler()
scaler.fit(A_scaled)
A_standarized=scaler.transform(A_scaled)
pca = PCA()
pca.fit(A_scaled)
pca1 = PCA()
pca1.fit(A_standarized)
print('Correlation Coefficient matrix is:')
print(corr)
print('std vector is:')
print(std_vector)
print('Covariance matrix is:')
print(np.cov(A_scaled.T))
print('---Before standarization---')
print('Components:')
print(pca.components_)
print('Sigular values:')
print(pca.explained_variance_)
print('---After standarization---')
print('Components:')
print(pca1.components_)
print('Sigular values:')
print(pca1.explained_variance_)
# draw PCA components
t1=np.linspace(-20,20,100)
t2=t1*std_vector[1]/std_vector[0]
plt.figure(figsize=[10,5])
plt.subplot(121)
plt.hist2d(A_scaled[:,0],A_scaled[:,1],100,alpha=0.7)
plt.plot(t1,t2,'--k')
c=pca.components_
r=np.sqrt(pca.explained_variance_)
plt.arrow(0,0,c[0,0]*r[0],c[0,1]*r[0],color='red',head_width=.3)
plt.arrow(0,0,c[1,0]*r[1],c[1,1]*r[1],color='blue',head_width=.3)
# plt.axis('equal')
plt.title('before standarized')
t1=np.linspace(-20,20,100)
cov=np.cov(A_standarized.T)
t2=t1*cov[1,1]
plt.subplot(122)
plt.hist2d(A_standarized[:,0],A_standarized[:,1],100,alpha=0.7)
plt.plot(t1,t2,'--k')
c=pca1.components_
r=np.sqrt(pca1.explained_variance_)
plt.arrow(0,0,c[0,0]*r[0],c[0,1]*r[0],color='red',head_width=.2)
plt.arrow(0,0,c[1,0]*r[1],c[1,1]*r[1],color='blue',head_width=.2)
# plt.axis('equal')
plt.title('after standarized')
plt.show()
SofaSofa数据科学社区DS面试题库 DS面经PCA实现的方式其实有四种:
- 标准化数据后的协方差矩阵
- 标准化数据后的相关系数矩阵
- 未标准化数据后的相关系数矩阵
- 标准化数据后的svd方式
这四种方式是等价的。
SofaSofa数据科学社区DS面试题库 DS面经