Python 中的主成分分析

2024-04-04

我想使用主成分分析(PCA)来降维。 numpy 或 scipy 是否已经有了它,或者我必须使用自己的numpy.linalg.eigh http://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.eigh.html?

我不仅仅想使用奇异值分解 (SVD),因为我的输入数据非常高维(~460 维),所以我认为 SVD 会比计算协方差矩阵的特征向量慢。

我希望找到一个预制的、经过调试的实现,它已经就何时使用哪种方法做出了正确的决定,并且可能还进行了我不知道的其他优化。


几个月后,这是一个小类 PCA 和一张图片:

#!/usr/bin/env python
""" a small class for Principal Component Analysis
Usage:
    p = PCA( A, fraction=0.90 )
In:
    A: an array of e.g. 1000 observations x 20 variables, 1000 rows x 20 columns
    fraction: use principal components that account for e.g.
        90 % of the total variance

Out:
    p.U, p.d, p.Vt: from numpy.linalg.svd, A = U . d . Vt
    p.dinv: 1/d or 0, see NR
    p.eigen: the eigenvalues of A*A, in decreasing order (p.d**2).
        eigen[j] / eigen.sum() is variable j's fraction of the total variance;
        look at the first few eigen[] to see how many PCs get to 90 %, 95 % ...
    p.npc: number of principal components,
        e.g. 2 if the top 2 eigenvalues are >= `fraction` of the total.
        It's ok to change this; methods use the current value.

Methods:
    The methods of class PCA transform vectors or arrays of e.g.
    20 variables, 2 principal components and 1000 observations,
    using partial matrices U' d' Vt', parts of the full U d Vt:
    A ~ U' . d' . Vt' where e.g.
        U' is 1000 x 2
        d' is diag([ d0, d1 ]), the 2 largest singular values
        Vt' is 2 x 20.  Dropping the primes,

    d . Vt      2 principal vars = p.vars_pc( 20 vars )
    U           1000 obs = p.pc_obs( 2 principal vars )
    U . d . Vt  1000 obs, p.obs( 20 vars ) = pc_obs( vars_pc( vars ))
        fast approximate A . vars, using the `npc` principal components

    Ut              2 pcs = p.obs_pc( 1000 obs )
    V . dinv        20 vars = p.pc_vars( 2 principal vars )
    V . dinv . Ut   20 vars, p.vars( 1000 obs ) = pc_vars( obs_pc( obs )),
        fast approximate Ainverse . obs: vars that give ~ those obs.


Notes:
    PCA does not center or scale A; you usually want to first
        A -= A.mean(A, axis=0)
        A /= A.std(A, axis=0)
    with the little class Center or the like, below.

See also:
    http://en.wikipedia.org/wiki/Principal_component_analysis
    http://en.wikipedia.org/wiki/Singular_value_decomposition
    Press et al., Numerical Recipes (2 or 3 ed), SVD
    PCA micro-tutorial
    iris-pca .py .png

"""

from __future__ import division
import numpy as np
dot = np.dot
    # import bz.numpyutil as nu
    # dot = nu.pdot

__version__ = "2010-04-14 apr"
__author_email__ = "denis-bz-py at t-online dot de"

#...............................................................................
class PCA:
    def __init__( self, A, fraction=0.90 ):
        assert 0 <= fraction <= 1
            # A = U . diag(d) . Vt, O( m n^2 ), lapack_lite --
        self.U, self.d, self.Vt = np.linalg.svd( A, full_matrices=False )
        assert np.all( self.d[:-1] >= self.d[1:] )  # sorted
        self.eigen = self.d**2
        self.sumvariance = np.cumsum(self.eigen)
        self.sumvariance /= self.sumvariance[-1]
        self.npc = np.searchsorted( self.sumvariance, fraction ) + 1
        self.dinv = np.array([ 1/d if d > self.d[0] * 1e-6  else 0
                                for d in self.d ])

    def pc( self ):
        """ e.g. 1000 x 2 U[:, :npc] * d[:npc], to plot etc. """
        n = self.npc
        return self.U[:, :n] * self.d[:n]

    # These 1-line methods may not be worth the bother;
    # then use U d Vt directly --

    def vars_pc( self, x ):
        n = self.npc
        return self.d[:n] * dot( self.Vt[:n], x.T ).T  # 20 vars -> 2 principal

    def pc_vars( self, p ):
        n = self.npc
        return dot( self.Vt[:n].T, (self.dinv[:n] * p).T ) .T  # 2 PC -> 20 vars

    def pc_obs( self, p ):
        n = self.npc
        return dot( self.U[:, :n], p.T )  # 2 principal -> 1000 obs

    def obs_pc( self, obs ):
        n = self.npc
        return dot( self.U[:, :n].T, obs ) .T  # 1000 obs -> 2 principal

    def obs( self, x ):
        return self.pc_obs( self.vars_pc(x) )  # 20 vars -> 2 principal -> 1000 obs

    def vars( self, obs ):
        return self.pc_vars( self.obs_pc(obs) )  # 1000 obs -> 2 principal -> 20 vars


class Center:
    """ A -= A.mean() /= A.std(), inplace -- use A.copy() if need be
        uncenter(x) == original A . x
    """
        # mttiw
    def __init__( self, A, axis=0, scale=True, verbose=1 ):
        self.mean = A.mean(axis=axis)
        if verbose:
            print "Center -= A.mean:", self.mean
        A -= self.mean
        if scale:
            std = A.std(axis=axis)
            self.std = np.where( std, std, 1. )
            if verbose:
                print "Center /= A.std:", self.std
            A /= self.std
        else:
            self.std = np.ones( A.shape[-1] )
        self.A = A

    def uncenter( self, x ):
        return np.dot( self.A, x * self.std ) + np.dot( x, self.mean )


#...............................................................................
if __name__ == "__main__":
    import sys

    csv = "iris4.csv"  # wikipedia Iris_flower_data_set
        # 5.1,3.5,1.4,0.2  # ,Iris-setosa ...
    N = 1000
    K = 20
    fraction = .90
    seed = 1
    exec "\n".join( sys.argv[1:] )  # N= ...
    np.random.seed(seed)
    np.set_printoptions( 1, threshold=100, suppress=True )  # .1f
    try:
        A = np.genfromtxt( csv, delimiter="," )
        N, K = A.shape
    except IOError:
        A = np.random.normal( size=(N, K) )  # gen correlated ?

    print "csv: %s  N: %d  K: %d  fraction: %.2g" % (csv, N, K, fraction)
    Center(A)
    print "A:", A

    print "PCA ..." ,
    p = PCA( A, fraction=fraction )
    print "npc:", p.npc
    print "% variance:", p.sumvariance * 100

    print "Vt[0], weights that give PC 0:", p.Vt[0]
    print "A . Vt[0]:", dot( A, p.Vt[0] )
    print "pc:", p.pc()

    print "\nobs <-> pc <-> x: with fraction=1, diffs should be ~ 0"
    x = np.ones(K)
    # x = np.ones(( 3, K ))
    print "x:", x
    pc = p.vars_pc(x)  # d' Vt' x
    print "vars_pc(x):", pc
    print "back to ~ x:", p.pc_vars(pc)

    Ax = dot( A, x.T )
    pcx = p.obs(x)  # U' d' Vt' x
    print "Ax:", Ax
    print "A'x:", pcx
    print "max |Ax - A'x|: %.2g" % np.linalg.norm( Ax - pcx, np.inf )

    b = Ax  # ~ back to original x, Ainv A x
    back = p.vars(b)
    print "~ back again:", back
    print "max |back - x|: %.2g" % np.linalg.norm( back - x, np.inf )

# end pca.py
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的主成分分析 的相关文章

随机推荐

  • Spring MVC 中如何处理静态内容?

    我正在使用 Spring MVC 3 开发一个 web 应用程序 并且有DispatcherServlet像这样捕获所有对 的请求 web xml
  • 在 React 中将函数传递给 setState() 有什么好处?

    我有一个函数叫做onRemove是这样写的 const todos setTodos useState todoData const onRemove useCallback id gt setTodos todos filter todo
  • 如何在 photoLibrary 或相机中快速裁剪 4*3 图像

    我想在使用相机后裁剪图像或从照片库中选择图像 目前 我只能裁剪方形图像 不知道如何裁剪 4 3 图像 这是我的部分代码 let imagePicker UIImagePickerController UIImagePickerControl
  • VSCode,如何获取setup.bash等环境变量文件?

    所以我正在使用 WSL ROS 和 VSCode 在 Ubuntu 上工作时 我只需在运行 VsCode 之前获取 opt ros ros distro setup bash 来获取环境变量 使用 WSL 时 我需要一种从已打开的 VSCo
  • 从正则表达式重定向中排除目录

    我希望将所有带有下划线的 URL 重定向到其对应的虚线 E g nederland amsterdam car rental变成 nederland amsterdam car rental 为此 我使用此处描述的技术 如何使用 Nginx
  • Delphi:如何在本地创建和使用线程?

    我的数据库位于 VPS 中 我应该从我的表中获取一些查询 由于从服务器获取查询需要很长时间 取决于互联网速度 我想使用线程来获取查询 现在我创建一个线程并获取查询 然后通过发送和处理消息将结果发送到我的表单 我想知道是否可以在本地创建和使用
  • 多线程中的Tornado多个IOLoop

    我正在尝试在多个线程中运行多个 IOLoop 我想知道 IOLoop 实际上是如何工作的 class WebThread threading Thread def init self threading Thread init self n
  • 如何在 PHP 中获取两个日期之间的所有月份?

    我有 2 个约会 我想获得所有月份的总天数 我怎样才能在 PHP 中做到这一点 例如 date1 2013 11 13 yy mm dd format date2 2014 02 14 Output Months Total Days 11
  • C# 上的 DllImport

    如何在 C 中访问 C DLL 的函数 以下是 DLL 的原型 NOMANGLE int CCONV SSPSendCommand SSP COMMAND cmd SSP COMMAND INFO sspInfo NOMANGLE int
  • 使用 ~(波形符)导入 SCSS 文件在 Angular 6 中不起作用

    我有两个问题scssAngular6 中的文件导入 我需要将我的部分内容导入到我的所有内容中吗 component scss在全局中导入一次后的文件src sass styles scss 导入一次还不够吗 我如何导入SCSS使用导入快捷方
  • 浮点除以零而不是 constexpr

    编译时 constexpr double x 123 0 constexpr double y x 0 0 std cout lt lt x lt lt 0 lt lt y lt lt n 编译器 gcc 4 9 2 std c 11 或
  • 在 Dart 中进行系统调用?

    我想从 dart 内部执行 python 或 java 类 以下是我从 stackoverflow 问题 Java 中使用的片段 Runtime currentRuntime Runtime getRuntime Process execu
  • 计算相机近平面和远平面边界

    我正在尝试执行中提到的计算使用 THREE Frustum 计算近 远平面顶点 https stackoverflow com questions 12018710 calculate near far plane vertices usi
  • 用css根据屏幕尺寸制作圆形图像

    我正在尝试将我的图像制作为圆形 尽管该图像具有不同的宽度和高度 但我希望它是圆形 看起来它们具有相同的宽度和高度长度 例如 我的图像尺寸 250X300 但我希望它是200X200圆 实际上我可以轻松做到这一点 问题是根据屏幕尺寸执行此操作
  • 即使连接了硬件键盘也显示 iPhone 软键盘

    我的 iPad 应用程序使用充当硬件键盘的外部 设备 但是 在设置中的某个时刻 我需要输入文本 但无法使用 设备 设备 不是键盘 那么 即使我连接了硬件键盘 有没有办法强制弹出软键盘 是的 当用户拥有与设备配对的蓝牙扫描仪 键盘 时 我们已
  • 通过 MediatR PipelineBehavior 进行单元测试验证

    我正在使用 FluentValidation 和 MediatR PipelineBehavior 来验证 CQRS 请求 我应该如何在单元测试中测试这种行为 Use the 测试扩展 https docs fluentvalidation
  • Java中不使用队列的二叉树右视图

    HERE http www geeksforgeeks org print right view binary tree 2 是不使用队列的二叉树右视图的C 实现 当我尝试将其转换为 Java 时 它不起作用 这是我的Java代码 我认为很
  • 如何修复 cordova 构建错误:不支持的类文件主要版本 62 [重复]

    这个问题在这里已经有答案了 我运行时收到此错误cordova build android在我的Mac上 FAILURE Build failed with an exception Where Script Users ad8kunle M
  • “触发快照依赖项的更改”似乎无法正常工作

    我正在将 TeamCity 6 5 1 与一个项目和大约 10 个构建配置一起使用 我有一个类似于 Core gt Framework gt Apps 的依赖链 Framework 依赖于 Core App 也依赖于 Core 和 Fram
  • Python 中的主成分分析

    我想使用主成分分析 PCA 来降维 numpy 或 scipy 是否已经有了它 或者我必须使用自己的numpy linalg eigh http docs scipy org doc numpy reference generated nu