【机器学习】PCA(特征值降维和奇异值降维)—— python3 实现方案

 算法流程很简单,但要究其原理,着实费了不少功夫。原因还是在于对矩阵的知识忘得太多了。在参考各篇博文的时候,突然就冒出很多矩阵名词,没办法,想理解算法原貌,只得重新一个个取查含义,重新学习了这些基础知识点后,理解原理相对来说还是简单的,这里推荐这篇博文https://blog.csdn.net/shizhixin/article/details/51181379

看了许多,这篇讲的更容易理解些,排版清晰,公式推导严谨。但纵观那么多文章,却没有提及怎么选择 维度“K”的,吴恩达的机器学习课程,提到用平方误差和 与 训练集的方差 的比例,来衡量选取k维后,对原数据的保留程度,但没有详细说明怎么做。后来还是在《机器学习实战》上找到了方法,就是用  t=选取的特征值的和 / 所有特征值的和 ,来表示降维后,信息的保留程度。之所以能这样做,是因为在推导过程中发现,特征值等于原数据在对应特征向量降维后的方差,而方差反应了信息量的大小。

吴恩达的推荐使用matlab的SVD(奇异值分解)求解。 numpy上也有对应的函数可以调用,两种方法可以得到同样的结果。

import numpy as np

class PCA():
    '''
    PCA降维算法
    '''
    def pca(self, dataSet, dimenK):
        '''
        使用主成分分析算法,把n维数据集降为k维数据
        :param dataSet: n*m数据集,n为维度,m为样本数量,np.array
        :param dimenK: 需要降到的维度
        :return:  降维后的数据集 k*m,和信息量占比t
        '''
        meanRemoved = dataSet - np.mean(dataSet, axis=0)  # 去均值化
        covMat = np.cov(meanRemoved)  # 计算协方差矩阵
        eigVals, eigVects = np.linalg.eig(covMat)  # 计算协方差矩阵的特征值和特征向量
        eigValsInd = np.argsort(eigVals)  # 返回从小到大排序后,元素的索引
        eigValsInd = eigValsInd[: : -1][: dimenK]  # 获取前k个最大的特征值的索引
        redEigVects = eigVects[:, eigValsInd]  # 根据索引获取对应的特征向量
        lowDDataMat = np.dot(redEigVects.T, meanRemoved)  # 特征向量*去均值化的原数据=降维后的数据
        t = np.sum(eigVals[eigValsInd]) / np.sum(eigVals)  # 在PCA,特征值等于对应特征向量*原数据后的方差,这里用方差代表信息量,该值衡量降维后保留的原数据多少的信息量


        # 以下使用SVD(奇异值分解)求解
        # u, s, vt = np.linalg.svd(covMat)  # s存储奇异值,u存储对应的特征向量
        # eigVals = s[: dimenK]  # 选取前K个奇异值,对应上面的特征值
        # redEigVects = u[:, : dimenK]  # 选取对应的特征向量, n*k
        # lowDDataMat = np.dot(redEigVects.T, meanRemoved)  # 通过左乘基向量矩阵,降维
        # t = np.sum(eigVals) / np.sum(s)  # 计算信息保留度

        return lowDDataMat, t



# 以下是测试数据
dataSet = np.random.rand(8, 10) * 10
pca = PCA()
print(pca.pca(dataSet, 5)[1])

猜你喜欢

转载自blog.csdn.net/zhenghaitian/article/details/81275618