摘要: 手把手教你PCA降维技术!(有案例)数组
数据是机器学习模型的生命燃料。对于特定的问题,总有不少机器学习技术可供选择,但若是没有不少好的数据,问题将不能很好的解决。数据一般是大部分机器学习应用程序中性能提高背后的驱动因素。机器学习
有时,数据可能很复杂。在那么多的数据中,知道哪些数据是真正重要的,具备必定的挑战性。降维是一种能够帮助咱们更好地了解数据的技术,它减小了数据集的特征数量,所以只剩下最重要的部分特征。性能
主成分分析(PCA)是一种用于降维的简单而强大的技术。经过它,咱们能够直接减小特征变量的数量,从而减小重要特征并节省计算量。从高层次来看,PCA有三个主要步骤:学习
(1)计算数据的协方差矩阵;this
(2)计算该协方差矩阵的特征值和向量;code
(3)经过特征值和向量来只选择最重要的特征向量,而后将数据转换为这些向量以下降维度。component
(1)计算协方差矩阵orm
PCA产生一个特征子空间,使特征向量的方差最大化。所以,为了正确计算这些特征向量的方差,必须对它们进行适当的平衡。为实现此目的,咱们首先将数据归一化为零均值和单位方差,以便在计算中对每一个特征进行加权。假设咱们的数据集为X:blog
from sklearn.preprocessing import StandardScaler X = StandardScaler().fit_transform(X)
两个变量的协方差衡量它们是如何“相关”的。若是两个变量的协方差是正的,那么当一个变量增长时,另外一个变量增长;在协方差为负的状况下,特征变量的值将在相反方向上改变。协方差矩阵只是一个数组,其中每一个值基于矩阵中的x-y位置指定两个特征变量之间的协方差。公式是:排序
其中带有上划线的x是X的每一个特征的均值向量,将转置矩阵乘以原始矩阵时,咱们最终将每一个数据点的每一个特征相乘!在numpy代码中实现以下:
import numpy as np # Compute the mean of the data mean_vec = np.mean(X, axis=0) # Compute the covariance matrix cov_mat = (X - mean_vec).T.dot((X - mean_vec)) / (X.shape[0]-1) # OR we can do this with one line of numpy: cov_mat = np.cov(X.T)
(2)计算特征值和向量
咱们的协方差矩阵的特征向量(主成分)表示新特征空间的向量方向,而特征值表示这些向量的大小。因为咱们正在研究协方差矩阵,所以特征值量化了每一个向量的贡献方差。
若是特征向量具备相应的高幅度特征值,则意味着咱们的数据在特征空间中沿着该向量具备高方差。所以,该向量包含有关数据的大量信息,由于沿着该向量的任何移动都会致使大的“方差”。另外一方面,具备小特征值的向量具备低方差,所以当沿着该向量移动时,咱们的数据不会有很大变化。因为在沿着特定特征向量移动时没有任何变化,即改变该特征向量的值不会对咱们的数据产生很大影响,那么咱们能够说这个特征不是很重要,能够忽略它。
这是PCA中特征值和向量的所有本质,找到表示数据最重要的向量,并丢弃其他的向量。计算协方差矩阵的特征向量和值是一个简单的单线性的numpy。以后,咱们将根据它们的特征值按降序对特征向量进行排序。
# Compute the eigen values and vectors using numpy eig_vals, eig_vecs = np.linalg.eig(cov_mat) # Make a list of (eigenvalue, eigenvector) tuples eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))] # Sort the (eigenvalue, eigenvector) tuples from high to low eig_pairs.sort(key=lambda x: x[0], reverse=True)
(3)映射到新的向量上
此时,咱们有一个特征向量列表,这些特征向量基于它们的特征值按照数据集的“重要性”进行排序。如今要作的是选择最重要的特征向量并丢弃其他的,能够经过查看向量的可解释方差百分比来巧妙地作到这一点。该百分比量化了总100%中每一个主成分可归因于多少信息(方差)。
咱们举一个例子来讲明。假设一个最初有10个特征向量的数据集。在计算协方差矩阵以后,特征值是:
[12,10,8,7,5,1,0.1,0.03,0.005,0.0009]
该数组的总和= 43.1359,但前6个值表明:43 / 43.1359 =总数的99.68%!这意味着咱们的前6个特征向量有效地保持了99.68%有关数据集的信息。所以,能够丢弃最后4个特征向量,由于它们只包含0.32%的信息,这就节省了40%的计算量。
所以,咱们能够简单地定义一个阈值,这个阈值能够决定是保留仍是丢弃每一个特征向量。在下面的代码中,设定阈值97%来决定每一个特征向量是否丢弃。
# Only keep a certain number of eigen vectors based on # the "explained variance percentage" which tells us how # much information (variance) can be attributed to each # of the principal components exp_var_percentage = 0.97 # Threshold of 97% explained variance tot = sum(eig_vals) var_exp = [(i / tot)*100 for i in sorted(eig_vals, reverse=True)] cum_var_exp = np.cumsum(var_exp) num_vec_to_keep = 0 for index, percentage in enumerate(cum_var_exp): if percentage > exp_var_percentage: num_vec_to_keep = index + 1 break
最后一步是将咱们的数据实际投射到决定保留的向量上。咱们经过构建投影矩阵来作到这一点:咱们将经过相乘将数据投影到新的向量上。为了建立它,简单地与决定保留的全部特征向量进行链接,最后一步是简单地在原始数据和投影矩阵之间取点积。
维度下降了!
# Compute the projection matrix based on the top eigen vectors num_features = X.shape[1] proj_mat = eig_pairs[0][1].reshape(num_features,1) for eig_vec_idx in range(1, num_vec_to_keep): proj_mat = np.hstack((proj_mat, eig_pairs[eig_vec_idx][1].reshape(num_features,1))) # Project the data pca_data = X.dot(proj_mat)