zoukankan      html  css  js  c++  java
  • 在SCIKIT中做PCA 逆变换 -- 新旧特征转换

    PCA(Principal Component Analysis)是一种常用的数据分析方法。PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降维。

    在Scikit中运用PCA很简单:

    import numpy as np
    from sklearn import decomposition
    from sklearn import datasets
    
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target
    
    pca = decomposition.PCA(n_components=3)
    pca.fit(X)
    X = pca.transform(X)

    以上代码是将含有4个特征的数据经过PCA压缩为3个特征。PCA的压缩由如下特点:

    • 新的3个特征并不是随便删除一个特征后留下的,而是4个特征的线性组合。
    • 新的3个特征保留了原有4个特征的绝大部分信息,换句话说就是略有损失。

    那么PCA的损失到底是什么? 新特征能否转回旧特征?

    这要从PCA过程说起,我把过程缩减如下,毕竟本文重点不是说PCA过程: 

    PCA过程

    1.均值化矩阵X

    2.通过一系列矩阵运算得出  特征矩阵P

    3.矩阵运算 Y = P * X

    Y 即为原始数据降维后的结果,也就是说,得到矩阵P后,我们还可以通过Y=P * X这个算式, 反推回X:

     Y = P * X ==>   P(-1) * Y = P(-1) * P * X,  P(-1)是P的逆矩阵, 即 P(-1) * P = 1

                    ==>   P(-1) * Y = X

    需要注意的是,程序一开始就已经将原始数据均值化,所以实际上, P(-1)*Y的结果需要去均值化才是原来的样子

    在Scikit中,pca.components_就是P的逆矩阵.  从源代码就可以看出(行号33)

     1    def transform(self, X, y=None):
     2         """Apply dimensionality reduction to X.
     3 
     4         X is projected on the first principal components previously extracted
     5         from a training set.
     6 
     7         Parameters
     8         ----------
     9         X : array-like, shape (n_samples, n_features)
    10             New data, where n_samples is the number of samples
    11             and n_features is the number of features.
    12 
    13         Returns
    14         -------
    15         X_new : array-like, shape (n_samples, n_components)
    16 
    17         Examples
    18         --------
    19 
    20         >>> import numpy as np
    21         >>> from sklearn.decomposition import IncrementalPCA
    22         >>> X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
    23         >>> ipca = IncrementalPCA(n_components=2, batch_size=3)
    24         >>> ipca.fit(X)
    25         IncrementalPCA(batch_size=3, copy=True, n_components=2, whiten=False)
    26         >>> ipca.transform(X) # doctest: +SKIP
    27         """
    28         check_is_fitted(self, ['mean_', 'components_'], all_or_any=all)
    29         print self.mean_
    30         X = check_array(X)
    31         if self.mean_ is not None:
    32             X = X - self.mean_
    33         X_transformed = fast_dot(X, self.components_.T)
    34         if self.whiten:
    35             X_transformed /= np.sqrt(self.explained_variance_)
    36         return X_transformed


    回到开头的压缩代码增加一些输出语句:

    iris = datasets.load_iris()
    X = iris.data
    y = iris.target
    
    print X[0]
    pca = decomposition.PCA(n_components=3)
    pca.fit(X)
    X = pca.transform(X)
    
    a = np.matrix(X)
    b = np.matrix(pca.components_)
    c = a * b
    mean_of_data = np.matrix([5.84333333, 3.054,       3.75866667,  1.19866667])
    
    print c[0]
    print c[0] + mean_of_data

    程序打印出原始数据中的第一行,然后将降维后的数据乘上特征矩阵的逆矩阵,加上均值还原回原来的4特征。

    输出如下:

    1 [ 5.1  3.5  1.4  0.2]
    2 
    3 [[-0.74365254  0.44632609 -2.35818399 -0.99942241]]
    4 
    5 [[ 5.09968079  3.50032609  1.40048268  0.19924426]]

    由此可看, 经还原后的特征值(行号5)和原来(行号1)相比,每一个特征都略有变化。

    如果维度不降,我们可以再看看结果

    pca = decomposition.PCA(n_components=4)
    pca.fit(X)
    X = pca.transform(X)
    
    a = np.matrix(X)
    b = np.matrix(pca.components_)
    c = a * b
    mean_of_data = np.matrix([5.84333333, 3.054,       3.75866667,  1.19866667])
    
    print c[0]
    print c[0] + mean_of_data


    完美还原:

    1 [ 5.1  3.5  1.4  0.2]
    2 
    3 [[-0.74333333  0.446      -2.35866667 -0.99866667]]
    4 
    5 [[ 5.1  3.5  1.4  0.2]]
  • 相关阅读:
    LeetCode OJ String to Integer (atoi) 字符串转数字
    HDU 1005 Number Sequence(AC代码)
    HDU 1004 Let the Balloon Rise(AC代码)
    HDU 1003 Max Sum(AC代码)
    012 Integer to Roman 整数转换成罗马数字
    011 Container With Most Water 盛最多水的容器
    010 Regular Expression Matching 正则表达式匹配
    007 Reverse Integer 旋转整数
    006 ZigZag Conversion
    005 Longest Palindromic Substring 最长回文子串
  • 原文地址:https://www.cnblogs.com/okokok/p/6822885.html
Copyright © 2011-2022 走看看