数据降维技术:主成分分析PCA

00、背景

比如,要考核一个研发人员,存在多个维度的评价指标,如:交付效率(需求交付周期、开发交付周期、交付吞吐量)、交付质量(线上缺陷密度 、故障恢复时间、首次提测通过率、单元测试覆盖率、代码评审通过率)、交付能力360度反馈等多个维度。那么多维度的数据,该如何计算呢?

降维技术提供了一种方法,它捕获数据中的基本信息,同时丢弃冗余或信息较少的特征。

数据降维,至少有以下几点好处:

  • 使数据集易使用
  • 降低算法计算开销
  • 去除噪声
  • 结果易懂
  • 发现隐性相关变量

降维主要实现技术有很多,比如主成分分析(PCA)线性判别分析(LDA)奇异值分解(SVD)因子分析(FA)独立成分分析(ICA)

其中,PCA 的应用目前最为广泛。

01、什么是PCA?

PCA = 主成分分析(Principal Component Analysis)

PCA是一种数学降维方法, 利用正交变换 (orthogonal transformation)把一系列可能线性相关的变量转换为一组线性不相关的新变量,也称为主成分,从而利用新变量在更小的维度下展示数据的特征。

简单来说,就是找出一个或几个最主要的特征,然后进行分析。

注意:

降维是通过减少数据中的指标以化简数据的过程

这里的减少指标,并不是随意加减,而是用复杂的数理知识,得到几个"综合指标"来代表整个数据。

而这里的综合指标就是所谓的主成分

它不是原来的指标中的任何一个,而是由所有原有指标数据线性组合而来。

02、实现步骤

将数据转换为N个主成分的步骤:

  1. 去除平均值
  2. 计算协方差矩阵
  3. 计算协方差矩阵的特征值和特征向量
  4. 将特征值从小到大排序,保留前N个
  5. 5. 将数据转换到这N个特征向量构建的新空间中

03、优缺点及适用场景

优点降低数据复杂性,识别多个特征缺点可能损失有用信息适用场景数值型数据

04、举例

1、一个简单的测试数据集

1.1 原始数据文件testSet.txt,19K

1.2 打印矩阵长度

1.3 效果图

2、另一个半导体制造数据集

2.1 原始数据:共1567行数据,有590列维度

2.2 打印矩阵长度、数据及均值

2.3 画出方差变化与特征个数的关系图

2.4 得出结论

从方差百分比与主成分个数之间的关系可以看出,大概只需要6个特征,就可以包括大部分的方差,后面的成分并不会损失太多信息。如果保留前6个主成分,则数据集就实现了从590个特征简化到6个特征,实现了近100:1的压缩。

3、完整代码

'''
Author: wujianming
Date: 2023-10-18
'''
import numpy as np 
import matplotlib.pyplot as plt 
from pylab import *
mpl.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

def loadData(filename,delim='\t'):
    fr=open(filename)
    stringArr=[line.strip().split(delim) for line in fr.readlines()]
    dataArr=[list(map(float,line)) for line in stringArr]
    return np.array(dataArr)

# 主成分分析
def pca(dataArr,topN=9999999):
    """
    dataArr为数据集
    topN参数可选,表示应用的N个特征,
    或原数据中全部特征
    """
    meanVal=np.mean(dataArr,axis=0)
    newArr=dataArr-meanVal
    # 协方差矩阵
    covMat=np.cov(np.mat(newArr),rowvar=0)
    eigVal,eigVec=np.linalg.eig(np.mat(covMat))
    index=np.argsort(eigVal)
    index=index[:-(topN+1):-1]
    vecArr=eigVec[:,index]
    lowDataMat=np.mat(newArr)*vecArr
    retDataArr=(lowDataMat*vecArr.T)+meanVal
    return lowDataMat,retDataArr

def load_clear_Data():
    import pandas as pd
    data=pd.read_csv('./secom.data',sep=' ',header=None,index_col=None)
    for i in range(data.shape[1]):
        data[i]=data[i].fillna(data[i].mean(),)    
    dataArr=np.array(data)
    return dataArr

def plot_var(dataMat):
    meanVals = np.mean(dataMat, axis=0)
    meanRemoved = dataMat - meanVals 
    covMat = np.cov(meanRemoved, rowvar=0)
    eigVals,eigVects = np.linalg.eig(np.mat(covMat))
    eigValInd = np.argsort(eigVals)
    eigValInd = eigValInd[::-1]
    sortedEigVals = eigVals[eigValInd]
    total = np.sum(sortedEigVals)
    varPercentage = sortedEigVals/total*100
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(range(1, 21), varPercentage[:20], marker='^')
    plt.xlabel('主成分个数')
    plt.ylabel('方差百分比')
    plt.show()

def plot_data(dataArr,reconMat):
    fig=plt.figure()
    ax=fig.add_subplot(111)
    ax.scatter(dataArr[:,0],dataArr[:,1],marker='^',s=90,c='b')
    ax.scatter(np.array(reconMat[:,0]),np.array(reconMat[:,1]),marker='o',s=50,c='r')
    plt.show()

if __name__=='__main__':
    dataArr=loadData('./testSet.txt')
    lowData,reconMat=pca(dataArr,1)
    plot_data(dataArr,reconMat)
    
    dataArr2=load_clear_Data()
    plot_var(dataArr2)

05、小结

为什么主成分可以代表原来那么多的指标呢?

其实我们仔细看一下,原来的许多指标是有相关性的,比如线上缺陷密度与单元测试覆盖率、代码评审通过率等有关联性。

通过降维就可以帮助我们去除这些指标中重叠、多余的信息,把数据最本质和关键的信息提取出来。

举报
评论 0