PCA算法框架
找到数据方差最大的投影方向;
利用数据协方差矩阵的特征值向量矩阵作为基,定义了新空间。
输入:训练数据集X 输出:以新的基表示的特征Y 1). 数据清洗,并规范化训练数据,使变量中心为0,方差为1;(减均值,除方差) 2). 求数据的协方差矩阵∑:∑=XTX;(T代表X的转置) 3). 求协方差矩阵的特征值λ:det(X-λI)=0; 4). 求协方差矩阵特征向量v:∑v = λv;(求出的特征向量要进行标准化处理) 5). 创建协方差矩阵∑的特征向量矩阵:E=[v1, v2, ..., vn] 6). 求变换后的矩阵Y:Y = XE
编码实现采用Numpy,numpy中的cov函数已经实现了中心化的步骤,并且numpy采用无偏估计,如下代码所示,cov_mat1与cov_mat2是相等的
matrix = np.mat([[4, 4, 0, 2, 2], [4, 0, 0, 3, 3], [4, 0, 0, 1, 1], [1, 1, 1, 2, 0], [2, 2, 2, 0, 0], [1, 1, 1, 0, 0], [5, 5, 5, 0, 0]]) meaned_matrix = matrix - np.mean(matrix, axis=0) cov_mat1 = np.cov(matrix, rowvar=False) cov_mat2 = meaned_matrix.T * meaned_matrix / (meaned_matrix.shape[0] - 1)
利用numpy进行PCA,只需要进行4步:
# 1. 计算协方差矩阵cov_matrix = np.cov(matrix, rower=False)# 2. 计算特征值及特征向量eig_vals, eig_vects = np.linalg.eig(cov_matrix) # 3. 生成主成分的特征向量矩阵eig_val_index = np.argsort(eig_vals)[:-(dimension + 1):-1] eig_vectors_mat = eig_vects[:, eig_val_index]# 4. 求压缩后的矩阵transformed_mat = mean_removed * eig_vectors_mat# 5. 重建降维后的矩阵reconstructed_mat = (transformed_mat * eig_vectors_mat.T) + mean_vals
问题概述
半导体是在一些极为先进的工厂中制造出来的。设备的生命早期有限,并且花费极其巨大。 虽然通过早期测试和频繁测试来发现有瑕疵的产品,但仍有一些存在瑕疵的产品通过测试。 如果我们通过机器学习技术用于发现瑕疵产品,那么它就会为制造商节省大量的资金。 具体来讲,它拥有590个特征。我们看看能否对这些特征进行降维处理。 对于数据的缺失值的问题,我们有一些处理方法(参考第5章) 目前该章节处理的方案是:将缺失值NaN(Not a Number缩写),全部用平均值来替代(如果用0来处理的策略就太差劲了)。
一. 首先分析数据,获取主成分方向的数目
def analyse_data(data_mat, threshold=0.9): # 返回结果 pri_dir_num = -1 # 协方差矩阵 cov_mat = np.cov(data_mat, rowvar=False) # 求特征值和特征向量 eig_vals, eig_vects = np.linalg.eig(cov_mat) # 将特征值从大到小排序,返回对应的下标;特征值越大说明数据在对应的特征向量方向方差越大,越重要 eig_val_index = np.argsort(eig_vals)[:-(data_mat.shape[1] + 1):-1] ''' 特征值的重要性评估,如果选出的主方向的重要性比例达到threshold要求, 则停止,并返回主方向数 ''' cov_all_score = np.float(sum(eig_vals)) sum_cov_score = 0 for i in range(0, len(eig_val_index)): line_cov_score = np.float(eig_vals[eig_val_index[i]]) sum_cov_score += line_cov_score # 方差占比 variance_ratio = line_cov_score / cov_all_score * 100 # 累积方差占比,压缩的精度 cumulative_variance_ratio = sum_cov_score / cov_all_score * 100 print('主成分:%s, 方差占比:%s%%, 累积方差占比:%s%%' % (format(i + 1, '2.0f'), format(variance_ratio, '5.2f'), format(cumulative_variance_ratio, '4.1f'))) # 如果满足精度要求则返回主方向数目 if cumulative_variance_ratio >= threshold * 100: pri_dir_num = i + 1 break return pri_dir_num
二. 根据最佳的主成分列,压缩数据
def pca(data_matrix, dimension=9999999): """ PCA降维 :param data_matrix: 原数据集矩阵 :param dimension: 保留的特征维数 :return: transformed_mat 降维后数据集 reconstructed_mat 新的数据集空间 """ # 计算每一列的均值 mean_vals = np.mean(data_matrix, axis=0) # 每个向量同时都减去 均值 mean_removed = data_matrix - mean_vals # cov协方差=[(x1-x均值)*(y1-y均值)+(x2-x均值)*(y2-y均值)+...+(xn-x均值)*(yn-y均值)]/(n-1) # 协方差矩阵:(多维)度量各个维度偏离其均值的程度 covariance_mat = np.cov(data_matrix, rowvar=False) # eig_vals为特征值, eig_vects为特征向量 eig_vals, eig_vects = np.linalg.eig(covariance_mat) # 对特征值,进行从小到大的排序,返回从小到大的index下标 # -1表示倒序,将特征值从大到小排序 eig_val_index = np.argsort(eig_vals)[:-(dimension + 1):-1] # 创建特征向量矩阵,eig_vects从大到小排序 eig_vectors_mat = eig_vects[:, eig_val_index] # 求变换后的矩阵 transformed_mat = mean_removed * eig_vectors_mat # 重建数据,由于特征向量矩阵满足正交性,所以特征值矩阵的逆和转置是相等的 reconstructed_mat = (transformed_mat * eig_vectors_mat.T) + mean_vals return transformed_mat, reconstructed_mat
由于特征向量的矩阵是正交的,所以ET=E-1,ETE=E-1E=I。
因此,设R代表reconstructed_mat,MR代表mean_removed,E代表eig_vectors_mat,MV代表mean_vals:
R = MR * E * ET + MV = MR + MV (即原矩阵抽取主成分后的结果)
红色为主成分
补充:
两个对称方阵A,B,满足A = PTBP,P是正交矩阵:ET=E-1,那么A和B为正交相似
任何一个对称矩阵A都可以正交相似于一个对角矩阵D,总存在一个正交矩阵P,使得A=PTDP
作者:ChongmingLiu
链接:https://www.jianshu.com/p/009357e8b689