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 函数已经实现了规范化的步骤, 所以在代码中我们不必再进行规范化处理, 只需要进行 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
来源: http://www.jianshu.com/p/009357e8b689